changeset 9255:9be51f776798

Merge from 3.2.1
author gernotbelger
date Fri, 13 Jul 2018 11:56:22 +0200
parents 68ff4087b987 (diff) 14200ded6d67 (current diff)
children 6c24c857ccf9
files gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixationPanel.java java.header
diffstat 615 files changed, 66780 insertions(+), 25535 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Feb 09 15:39:49 2018 +0100
+++ b/.hgignore	Fri Jul 13 11:56:22 2018 +0200
@@ -3,6 +3,10 @@
 artifacts/\.classpath # eclipse
 artifacts/\.project   # eclipse
 artifacts/\.settings  # eclipse
+artifacts/doc/artifactsdb
+artifacts/doc/datacagedb
+artifacts/doc/cache
+artifacts/build
 artifacts/test-output # eclipse junit/testng plugin output
 backend/target      # maven output
 backend/\.classpath # eclipse
@@ -25,3 +29,12 @@
 \.swo
 \.pyc
 TAGS
+syntax: glob
+.project
+.settings
+artifacts/doc/*.map
+artifacts/doc/*.log.*
+artifacts/doc/*.log
+artifacts/doc/shapefiles/*
+artifacts/doc/conf/sinfo_tkh_sohlhoehen_Elbe.properties
+artifacts/doc/conf/sinfo_tkh_sohlhoehen_Rhein.properties
--- a/artifacts/TODO	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/TODO	Fri Jul 13 11:56:22 2018 +0200
@@ -1,1 +1,1 @@
-- Validation of the input values of an incoming feed() call
+- Validation of the input values of an incoming feed() call
\ No newline at end of file
Binary file artifacts/contrib/fonts/roboto.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/artifacts/bundu.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<artifact name="bundu">
+  <states>
+    <state id="state.bundu.river" description="state.bundu.river" helpText="help.state.bundu.river" state="org.dive4elements.river.artifacts.states.RiverSelect">
+      <data name="river" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.river" />
+      <to state="state.bundu.calculation.mode" />
+    </transition>
+
+    <state id="state.bundu.calculation.mode" helpText="help.state.bundu.calculation.mode" description="state.bundu.calculation.mode" state="org.dive4elements.river.artifacts.bundu.CalculationSelectBundu">
+      <data name="calculation_mode" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.calculation.mode" />
+      <to state="state.bundu.location" />
+      <condition data="calculation_mode" value="bundu_analysis" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.calculation.mode" />
+      <to state="state.bundu.location" />
+      <condition data="calculation_mode" value="bundu_vollmer" operator="equal" />
+    </transition>
+
+    <state id="state.bundu.location" description="state.bundu.location" helpText="help.state.bundu.location" state="org.dive4elements.river.artifacts.states.fixation.LocationSelect">
+      <data name="ld_from" type="Double" />
+      <data name="ld_to" type="Double" />
+      <data name="ld_step" type="Double" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.location" />
+      <to state="state.bundu.period" />
+      <condition data="calculation_mode" value="bundu_vollmer" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.location" />
+      <to state="state.bundu.period" />
+      <condition data="calculation_mode" value="bundu_analysis" operator="equal" />
+    </transition>
+
+    <state id="state.bundu.period" description="state.bundu.period" helpText="help.state.bundu.period" state="org.dive4elements.river.artifacts.states.fixation.FixationPeriod">
+      <data name="start" type="Long" />
+      <data name="end" type="Long" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.period" />
+      <to state="state.bundu.gaugerange" />
+    </transition>
+
+    <state id="state.bundu.gaugerange" description="state.bundu.gaugerange" helpText="help.state.bundu.gaugerange" state="org.dive4elements.river.artifacts.states.fixation.GaugeRange">
+      <data name="q1" type="Integer" />
+      <data name="q2" type="Integer" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.gaugerange" />
+      <to state="state.bundu.eventselect" />
+    </transition>
+
+    <state id="state.bundu.eventselect" description="state.bundu.eventselect" helpText="help.state.bundu.eventselect" state="org.dive4elements.river.artifacts.states.fixation.EventSelect">
+      <data name="events" type="intarray" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.eventselect" />
+      <to state="state.bundu.analysis.referenceperiod" />
+      <condition data="calculation_mode" value="bundu_analysis" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.eventselect" />
+      <to state="state.bundu.vollmer.function" />
+      <condition data="calculation_mode" value="bundu_vollmer" operator="equal" />
+    </transition>
+
+    <state id="state.bundu.analysis.referenceperiod" helpText="help.state.bundu.analysis.referenceperiod" description="state.bundu.analysis.referenceperiod" state="org.dive4elements.river.artifacts.states.fixation.ReferencePeriod">
+      <data name="ref_start" type="Long" />
+      <data name="ref_end" type="Long" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.analysis.referenceperiod" />
+      <to state="state.bundu.analysis.analysisperiods" />
+    </transition>
+
+    <state id="state.bundu.analysis.analysisperiods" helpText="help.state.bundu.analysis.analysisperiods" description="state.bundu.analysis.analysisperiods" state="org.dive4elements.river.artifacts.states.fixation.AnalysisPeriods">
+      <data name="ana_data" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.analysis.analysisperiods" />
+      <to state="state.bundu.analysis.function" />
+    </transition>
+
+    <state id="state.bundu.analysis.function" helpText="help.state.bundu.analysis.function" description="state.bundu.analysis.function" state="org.dive4elements.river.artifacts.states.fixation.FunctionSelect">
+      <data name="function" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.analysis.function" />
+      <to state="state.bundu.analysis.preprocessing" />
+    </transition>
+
+    <state id="state.bundu.analysis.preprocessing" helpText="help.state.bundu.analysis.preprocessing" description="state.bundu.analysis.preprocessing" state="org.dive4elements.river.artifacts.states.fixation.PreprocessingSelect">
+      <data name="preprocessing" type="Boolean" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.analysis.preprocessing" />
+      <to state="state.bundu.analysis.compute" />
+    </transition>
+
+    <state id="state.bundu.analysis.compute" helpText="help.state.bundu.analysis.compute" description="state.bundu.analysis.compute" state="org.dive4elements.river.artifacts.states.fixation.FixAnalysisCompute">
+      <outputmodes>
+        <outputmode name="fix_deltawt_export" description="output.fix_deltawt_export" mine-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.fix_deltawt.csv" />
+            <facet name="pdf" description="facet.fix_deltawt.pdf" />
+          </facets>
+        </outputmode> 
+        <outputmode name="fix_parameters_export" description="output.fix_parameters_export" mine-type="text/plain" type="export">
+          <facets>
+            <facet name="fix_parameters" description="facet.fix_parameters.csv" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_wq_curve_at_export" description="output.fix_wq_curve_at_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="at" description="facet.fix_wq_curve_export.at" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_wq_curve" description="output.fix_wq_curve" mine-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_wq_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_analysis_events_wq" description="Raw event values used in the calculation" />
+            <facet name="fix_reference_events_wq" description="Raw event values used in the calculation" />
+            <facet name="fix_wq_curve" description="WQ curve" />
+            <facet name="qsectors" description="qsectors." />
+            <facet name="fix_outlier" description="The outliers" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+            <facet name="other.wkms" description="facet.other.wkms" />
+            <facet name="other.wkms.marks" description="facet.other.wkms.makrs" />
+            <facet name="other.wqkms" description="facet.other.wqkms" />
+            <facet name="longitudinal_section.w" description="facet.longitudinal_section.w" />
+            <facet name="other.wq" description="Point-like data like fixations" />
+            <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points" />
+            <facet name="discharge_curve.curve" description="facet.discharge_curve.curve" />
+            <facet name="fix_wq_curve.manualpoints" description="Manual points" />
+            <facet name="mainvalues.q" description="mainvalues.q" />
+            <facet name="mainvalues.w" description="mainvalues.w" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_deltawt_curve" description="output.fix_deltawt_curve" mine-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_dwt_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_dwt_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_dwt_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_dwt_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_analysis_events_dwt" description="Raw event values used in the calculation" />
+            <facet name="fix_reference_events_dwt" description="Raw event values used in the calculation" />
+            <facet name="fix_analysis_periods_dwt" description="Dateranges of analysis periods." />
+            <facet name="fix_deviation_dwt" description="The standard variance" />
+            <facet name="fix_deltawt_curve.manualpoints" description="Manual points" />
+            <facet name="fix_reference_period_dwt" description="Reference period" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_longitudinal_section_curve" description="output.fix_longitudinal_section_curve" mine-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_ls_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_3" description="Average values for Ws in Q sectors." />
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            <facet name="fix_deviation_ls" description="The standard variance" />
+            <facet name="fix_analysis_events_ls" description="Average values for Ws in Q sectors." />
+            <facet name="fix_reference_events_ls" description="Average values for Ws in Q sectors." />
+            <facet name="fix_longitudinal_section_curve.manualpoints" description="Manual points" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_derivate_curve" description="output.fix_derivate_curve" mine-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_derivate_curve" description="Derivate curve" />
+            <facet name="fix_derivate_curve.manualpoints" description="Manual points" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_report" description="output.fix_report.report" mime-type="text/plain" type="report">
+          <facets>
+            <facet name="report" description="facet.fix.report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+    <state id="state.bundu.vollmer.function" helpText="help.state.bundu.vollmer.function" description="state.bundu.vollmer.function" state="org.dive4elements.river.artifacts.states.fixation.FunctionSelect">
+      <data name="function" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.vollmer.function" />
+      <to state="state.bundu.vollmer.preprocessing" />
+    </transition>
+
+    <state id="state.bundu.vollmer.preprocessing" helpText="help.state.bundu.vollmer.preprocessing" description="state.bundu.vollmer.preprocessing" state="org.dive4elements.river.artifacts.states.fixation.PreprocessingSelect">
+      <data name="preprocessing" type="Boolean" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.vollmer.preprocessing" />
+      <to state="state.bundu.vollmer.qs" />
+    </transition>
+
+    <state id="state.bundu.vollmer.qs" description="state.bundu.vollmer.qs" helpText="help.state.bundu.vollmer.qs" state="org.dive4elements.river.artifacts.states.WQFixing">
+      <data name="wq_isq" type="String" />
+      <data name="wq_values" type="WQTriple" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.bundu.vollmer.qs" />
+      <to state="state.bundu.vollmer.compute" />
+    </transition>
+
+    <state id="state.bundu.vollmer.compute" helpText="help.state.bundu.vollmer.compute" description="state.bundu.vollmer.compute" state="org.dive4elements.river.artifacts.states.fixation.FixRealizingCompute">
+      <outputmodes>
+        <outputmode name="longitudinal_section" description="output.longitudinal_section" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="longitudinal_section.w" description="facet.longitudinal_section.w" />
+            <facet name="longitudinal_section.q" description="facet.longitudinal_section.q" />
+            <facet name="w_differences" description="facet.w_differences" />
+            <facet name="other.wkms" description="facet.other.wkms" />
+            <facet name="other.wq" description="WQ-Type of data" />
+            <facet name="other.wqkms" description="facet.other.wqkms" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+            <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points" />
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            <facet name="longitudinal_section.area" description="facet.longitudinal_section.area" />
+            <facet name="longitudinal_section.manualpoints" description="Manuelle Punkte" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_wq_curve" description="output.fix_wq_curve" mine-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_wq_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_analysis_events_wq" description="Raw event values used in the calculation" />
+            <facet name="fix_wq_curve" description="WQ curve" />
+            <facet name="fix_wq_ls" description="WQ LS curve" />
+            <facet name="fix_outlier" description="The outliers" />
+            <facet name="qsectors" description="qsectors." />
+            <facet name="fix_events_wqkms" description="WQKMS-Type of data" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+            <facet name="other.wkms" description="facet.other.wqkms" />
+            <facet name="other.wqkms" description="facet.other.wqkms" />
+            <!--issue1383: facet name="longitudinal_section.w" description="facet.longitudinal_section.w"/ -->
+            <facet name="other.wq" description="Point-like data like fixations" />
+            <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points" />
+            <facet name="discharge_curve.curve" description="facet.discharge_curve.curve" />
+            <facet name="mainvalues.w" description="facet.fix_wq.mainvalues.w" />
+            <facet name="mainvalues.q" description="facet.fix_wq.mainvalues.q" />
+          </facets>
+        </outputmode>
+        <outputmode name="cross_section" description="output.cross_section" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="cross_section_water_line" description="facet.cross_section_water_line" />
+            <facet name="cross_section" description="facet.cross_section" />
+            <facet name="area" description="an area" />
+            <facet name="cross_section.area" description="an area" />
+            <facet name="cross_section.manualpoints" description="points" />
+            <facet name="cross_section.manualline" description="line" />
+            <facet name="hyk" description="hyks" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_wq_curve_at_export" description="output.fix_wq_curve_at_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="at" description="facet.fix_wq_curve_export.at" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_waterlevel_export" description="output.fix_waterlevel_export" mine-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.waterlevel_export.csv" />
+            <facet name="wst" description="facet.waterlevel_export.wst" />
+            <facet name="pdf" description="facet.waterlevel_export.pdf" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_report" description="output.fix_report.report" mime-type="text/plain" type="report">
+          <facets>
+            <facet name="report" description="facet.fix.report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+
+
+    <!-- Bezugswasserstände bezugswst -->
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.calculation.mode" />
+      <to state="state.bundu.location" />
+      <condition data="calculation_mode" value="bundu_bezugswst" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.location" />
+      <to state="state.bundu.yearselect" />
+      <condition data="calculation_mode" value="bundu_bezugswst" operator="equal" />
+    </transition>
+
+
+    <state id="state.bundu.yearselect" helpText="state.bundu.yearselect" description="state.bundu.yearselect" state="org.dive4elements.river.artifacts.bundu.bezugswst.LoadSingleYearSelectState">
+      <data name="singleyear" type="String" />
+    </state>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.yearselect" />
+      <to state="state.bundu.fixationchoice" />
+      <condition data="calculation_mode" value="bundu_bezugswst" operator="equal" />
+    </transition>
+
+    <state id="state.bundu.fixationchoice" helpText="state.bundu.fixationchoice" description="state.bundu.fixationchoice" state="org.dive4elements.river.artifacts.bundu.bezugswst.FixationChoice">
+      <data name="fix_choice" type="String" />
+    </state>
+ 
+   
+   <!-- <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.bundu.fixationchoice" />
+      <to state="state.bundu.yearselect" />
+      <condition data="fix_choice" value="bundu_bezugswst" operator="equal" />
+    </transition>
+    TODO: to be continued -->  
+
+
+
+
+  </states>
+</artifact>
--- a/artifacts/doc/conf/artifacts/fixanalysis.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/artifacts/fixanalysis.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -1,337 +1,306 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <artifact name="fixanalysis">
-    <states>
-        <state id="state.fix.river" description="state.fix.river"
-            helpText="help.state.fix.river"
-            state="org.dive4elements.river.artifacts.states.RiverSelect">
-            <data name="river" type="String" />
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.river"/>
-            <to state="state.fix.calculation.mode"/>
-        </transition>
-
-        <state id="state.fix.calculation.mode"
-            helpText="help.state.fix.calculation.mode"
-            description="state.fix.calcuation.mode"
-            state="org.dive4elements.river.artifacts.states.fixation.FixationSelect">
-            <data name="calculation.mode" type="String"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.calculation.mode"/>
-            <to state="state.fix.location"/>
-        </transition>
-
-        <state id="state.fix.location" description="state.fix.location"
-            helpText="help.state.fix.location"
-            state="org.dive4elements.river.artifacts.states.fixation.LocationSelect">
-            <data name="ld_from" type="Double"/>
-            <data name="ld_to" type="Double"/>
-            <data name="ld_step" type="Double"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.location"/>
-            <to state="state.fix.period"/>
-        </transition>
-
-        <state id="state.fix.period" description="state.fix.period"
-            helpText="help.state.fix.period"
-            state="org.dive4elements.river.artifacts.states.fixation.FixationPeriod">
-            <data name="start" type="Long"/>
-            <data name="end" type="Long"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.period"/>
-            <to state="state.fix.gaugerange"/>
-        </transition>
-
-        <state id="state.fix.gaugerange" description="state.fix.gaugerange"
-            helpText="help.state.fix.gaugerange"
-            state="org.dive4elements.river.artifacts.states.fixation.GaugeRange">
-            <data name="q1" type="Integer"/>
-            <data name="q2" type="Integer"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.gaugerange"/>
-            <to state="state.fix.eventselect"/>
-        </transition>
-
-        <state id="state.fix.eventselect" description="state.fix.eventselect"
-            helpText="help.state.fix.eventselect"
-            state="org.dive4elements.river.artifacts.states.fixation.EventSelect">
-            <data name="events" type="intarray"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
-            <from state="state.fix.eventselect"/>
-            <to state="state.fix.analysis.referenceperiod"/>
-            <condition data="calculation.mode" value="calculation.analysis"
-                operator="equal"/>
-        </transition>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
-            <from state="state.fix.eventselect"/>
-            <to state="state.fix.vollmer.function"/>
-            <condition data="calculation.mode" value="calculation.vollmer"
-                operator="equal"/>
-        </transition>
-
-        <state id="state.fix.analysis.referenceperiod"
-            helpText="help.state.fix.analysis.referenceperiod"
-            description="state.fix.analysis.referenceperiod"
-            state="org.dive4elements.river.artifacts.states.fixation.ReferencePeriod">
-            <data name="ref_start" type="Long"/>
-            <data name="ref_end" type="Long"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.analysis.referenceperiod"/>
-            <to state="state.fix.analysis.analysisperiods"/>
-        </transition>
-
-        <state id="state.fix.analysis.analysisperiods"
-            helpText="help.state.fix.analysis.analysisperiods"
-            description="state.fix.analysis.analysisperiods"
-            state="org.dive4elements.river.artifacts.states.fixation.AnalysisPeriods">
-            <data name="ana_data" type="String"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.analysis.analysisperiods"/>
-            <to state="state.fix.analysis.function"/>
-        </transition>
-
-        <state id="state.fix.analysis.function"
-            helpText="help.state.fix.analysis.function"
-            description="state.fix.analysis.function"
-            state="org.dive4elements.river.artifacts.states.fixation.FunctionSelect">
-            <data name="function" type="String"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.analysis.function"/>
-            <to state="state.fix.analysis.preprocessing"/>
-        </transition>
-
-        <state id="state.fix.analysis.preprocessing"
-            helpText="help.state.fix.analysis.preprocessing"
-            description="state.fix.analysis.preprocessing"
-            state="org.dive4elements.river.artifacts.states.fixation.PreprocessingSelect">
-            <data name="preprocessing" type="Boolean"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.analysis.preprocessing"/>
-            <to state="state.fix.analysis.compute"/>
-        </transition>
+  <states>
+    <state id="state.fix.river" description="state.fix.river" helpText="help.state.fix.river" state="org.dive4elements.river.artifacts.states.RiverSelect">
+      <data name="river" type="String" />
+    </state>
 
-        <state id="state.fix.analysis.compute"
-            helpText="help.state.fix.analysis.compute"
-            description="state.fix.analysis.compute"
-            state="org.dive4elements.river.artifacts.states.fixation.FixAnalysisCompute">
-            <outputmodes>
-                <outputmode name="fix_deltawt_export" description="output.fix_deltawt_export" mine-type="text/plain" type="export">
-                    <facets>
-                        <facet name="csv" description="facet.fix_deltawt.csv" />
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_parameters_export" description="output.fix_parameters_export" mine-type="text/plain" type="export">
-                    <facets>
-                        <facet name="fix_parameters" description="facet.fix_parameters.csv" />
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_wq_curve_at_export" description="output.fix_wq_curve_at_export" mime-type="text/plain" type="export">
-                    <facets>
-                        <facet name="at" description="facet.fix_wq_curve_export.at"/>
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_wq_curve" description="output.fix_wq_curve" mine-type="image/png" type="chart">
-                    <facets>
-                        <facet name="fix_sector_average_wq_0" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_wq_1" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_wq_2" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_wq_3" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_analysis_events_wq" description="Raw event values used in the calculation"/>
-                        <facet name="fix_reference_events_wq" description="Raw event values used in the calculation"/>
-                        <facet name="fix_wq_curve" description="WQ curve"/>
-                        <facet name="qsectors" description="qsectors."/>
-                        <facet name="fix_outlier" description="The outliers"/>
-                        <facet name="other.wqkms.q"          description="W-Type of data" />
-                        <facet name="other.wqkms.w"          description="W-Type of data" />
-                        <facet name="other.wkms" description="facet.other.wkms"/>
-                        <facet name="other.wkms.marks" description="facet.other.wkms.makrs"/>
-                        <facet name="other.wqkms" description="facet.other.wqkms"/>
-                        <facet name="longitudinal_section.w" description="facet.longitudinal_section.w"/>
-                        <facet name="other.wq"    description="Point-like data like fixations"/>
-                        <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points"/>
-                        <facet name="discharge_curve.curve" description="facet.discharge_curve.curve"/>
-                        <facet name="fix_wq_curve.manualpoints" description="Manual points"/>
-                        <facet name="mainvalues.q" description="mainvalues.q"/>
-                        <facet name="mainvalues.w" description="mainvalues.w"/>
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_deltawt_curve" description="output.fix_deltawt_curve" mine-type="image/png" type="chart">
-                    <facets>
-                        <facet name="fix_sector_average_dwt_0" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_dwt_1" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_dwt_2" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_dwt_3" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_analysis_events_dwt" description="Raw event values used in the calculation"/>
-                        <facet name="fix_reference_events_dwt" description="Raw event values used in the calculation"/>
-                        <facet name="fix_analysis_periods_dwt" description="Dateranges of analysis periods."/>
-                        <facet name="fix_deviation_dwt" description="The standard variance"/>
-                        <facet name="fix_deltawt_curve.manualpoints" description="Manual points"/>
-                        <facet name="fix_reference_period_dwt" description="Reference period"/>
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_longitudinal_section_curve" description="output.fix_longitudinal_section_curve" mine-type="image/png" type="chart">
-                    <facets>
-                        <facet name="fix_sector_average_ls_0" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_ls_1" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_ls_2" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_ls_3" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_ls_deviation_0" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_ls_deviation_1" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_ls_deviation_2" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_ls_deviation_3" description="Average values for Ws in Q sectors."/>
-                        <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations"/>
-                        <facet name="fix_deviation_ls" description="The standard variance"/>
-                        <facet name="fix_analysis_events_ls" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_reference_events_ls" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_longitudinal_section_curve.manualpoints" description="Manual points"/>
-                        <facet name="other.wqkms.q"          description="W-Type of data" />
-                        <facet name="other.wqkms.w"          description="W-Type of data" />
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_derivate_curve" description="output.fix_derivate_curve" mine-type="image/png" type="chart">
-                    <facets>
-                        <facet name="fix_derivate_curve" description="Derivate curve"/>
-                        <facet name="fix_derivate_curve.manualpoints" description="Manual points"/>
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_report" description="output.fix_report.report" mime-type="text/plain" type="report">
-                    <facets>
-                        <facet name="report" description="facet.fix.report" />
-                    </facets>
-                </outputmode>
-            </outputmodes>
-        </state>
-
-        <state id="state.fix.vollmer.function"
-            helpText="help.state.fix.vollmer.function"
-            description="state.fix.vollmer.function"
-            state="org.dive4elements.river.artifacts.states.fixation.FunctionSelect">
-            <data name="function" type="String"/>
-        </state>
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.river" />
+      <to state="state.fix.calculation.mode" />
+    </transition>
 
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.vollmer.function"/>
-            <to state="state.fix.vollmer.preprocessing"/>
-        </transition>
-
-        <state id="state.fix.vollmer.preprocessing"
-            helpText="help.state.fix.vollmer.preprocessing"
-            description="state.fix.vollmer.preprocessing"
-            state="org.dive4elements.river.artifacts.states.fixation.PreprocessingSelect">
-            <data name="preprocessing" type="Boolean"/>
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.vollmer.preprocessing"/>
-            <to state="state.fix.vollmer.qs"/>
-        </transition>
-
-        <state id="state.fix.vollmer.qs" description="state.fix.vollmer.qs"
-            helpText="help.state.fix.vollmer.qs"
-            state="org.dive4elements.river.artifacts.states.WQFixing">
-            <data name="wq_isq"   type="String" />
-            <data name="wq_values" type="WQTriple" />
-        </state>
-
-        <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.fix.vollmer.qs"/>
-            <to state="state.fix.vollmer.compute"/>
-        </transition>
+    <state id="state.fix.calculation.mode" helpText="help.state.fix.calculation.mode" description="state.fix.calcuation.mode" state="org.dive4elements.river.artifacts.states.fixation.FixationSelect">
+      <data name="calculation.mode" type="String" />
+    </state>
 
-        <state id="state.fix.vollmer.compute"
-            helpText="help.state.fix.vollmer.compute"
-            description="state.fix.vollmer.compute"
-            state="org.dive4elements.river.artifacts.states.fixation.FixRealizingCompute">
-            <outputmodes>
-                <outputmode name="longitudinal_section" description="output.longitudinal_section" mime-type="image/png" type="chart">
-                    <facets>
-                    	<facet name="longitudinal_section.w" description="facet.longitudinal_section.w"/>
-                    	<facet name="longitudinal_section.q" description="facet.longitudinal_section.q"/>
-                        <facet name="w_differences" description="facet.w_differences"/>
-                        <facet name="other.wkms" description="facet.other.wkms"/>
-                        <facet name="other.wq"               description="WQ-Type of data" />
-                        <facet name="other.wqkms" description="facet.other.wqkms"/>
-                        <facet name="other.wqkms.q"          description="W-Type of data" />
-                        <facet name="other.wqkms.w"          description="W-Type of data" />
-                        <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points"/>
-                        <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations"/>
-                        <facet name="longitudinal_section.area" description="facet.longitudinal_section.area"/>
-                        <facet name="longitudinal_section.manualpoints" description="Manuelle Punkte"/>
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_wq_curve" description="output.fix_wq_curve" mine-type="image/png" type="chart">
-                    <facets>
-                        <facet name="fix_sector_average_wq_0" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_wq_1" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_wq_2" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_sector_average_wq_3" description="Average values for Ws in Q sectors."/>
-                        <facet name="fix_analysis_events_wq" description="Raw event values used in the calculation"/>
-                        <facet name="fix_wq_curve" description="WQ curve"/>
-                        <facet name="fix_wq_ls" description="WQ LS curve"/>
-                        <facet name="fix_outlier" description="The outliers"/>
-                        <facet name="qsectors" description="qsectors."/>
-                        <facet name="fix_events_wqkms"          description="WQKMS-Type of data" />
-                        <facet name="other.wqkms.q"          description="W-Type of data" />
-                        <facet name="other.wqkms.w"          description="W-Type of data" />
-                        <facet name="other.wkms" description="facet.other.wqkms"/>
-                        <facet name="other.wqkms" description="facet.other.wqkms"/>
-                        <!--issue1383: facet name="longitudinal_section.w" description="facet.longitudinal_section.w"/-->
-                        <facet name="other.wq"    description="Point-like data like fixations"/>
-                        <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points"/>
-                        <facet name="discharge_curve.curve" description="facet.discharge_curve.curve"/>
-                        <facet name="mainvalues.w" description="facet.fix_wq.mainvalues.w"/>
-                        <facet name="mainvalues.q" description="facet.fix_wq.mainvalues.q"/>
-                    </facets>
-                </outputmode>
-                <outputmode name="cross_section" description="output.cross_section" mime-type="image/png" type="chart">
-                  <facets>
-                    <facet name="cross_section_water_line"   description="facet.cross_section_water_line"/>
-                    <facet name="cross_section"              description="facet.cross_section"/>
-                    <facet name="area"                       description="an area"/>
-                    <facet name="cross_section.area"         description="an area"/>
-                    <facet name="cross_section.manualpoints" description="points"/>
-                    <facet name="cross_section.manualline"   description="line"/>
-                    <facet name="hyk"                        description="hyks"/>
-                  </facets>
-                </outputmode>
-                <outputmode name="fix_wq_curve_at_export" description="output.fix_wq_curve_at_export" mime-type="text/plain" type="export">
-                    <facets>
-                        <facet name="at" description="facet.fix_wq_curve_export.at"/>
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_waterlevel_export" description="output.fix_waterlevel_export" mine-type="text/plain" type="export">
-                    <facets>
-                        <facet name="csv" description="facet.waterlevel_export.csv" />
-                        <facet name="wst" description="facet.waterlevel_export.wst" />
-                        <facet name="pdf" description="facet.waterlevel_export.pdf" />
-                    </facets>
-                </outputmode>
-                <outputmode name="fix_report" description="output.fix_report.report" mime-type="text/plain" type="report">
-                    <facets>
-                        <facet name="report" description="facet.fix.report" />
-                    </facets>
-                </outputmode>
-            </outputmodes>
-        </state>
-    </states>
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.calculation.mode" />
+      <to state="state.fix.location" />
+    </transition>
+
+    <state id="state.fix.location" description="state.fix.location" helpText="help.state.fix.location" state="org.dive4elements.river.artifacts.states.fixation.LocationSelect">
+      <data name="ld_from" type="Double" />
+      <data name="ld_to" type="Double" />
+      <data name="ld_step" type="Double" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.location" />
+      <to state="state.fix.period" />
+    </transition>
+
+    <state id="state.fix.period" description="state.fix.period" helpText="help.state.fix.period" state="org.dive4elements.river.artifacts.states.fixation.FixationPeriod">
+      <data name="start" type="Long" />
+      <data name="end" type="Long" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.period" />
+      <to state="state.fix.gaugerange" />
+    </transition>
+
+    <state id="state.fix.gaugerange" description="state.fix.gaugerange" helpText="help.state.fix.gaugerange" state="org.dive4elements.river.artifacts.states.fixation.GaugeRange">
+      <data name="q1" type="Integer" />
+      <data name="q2" type="Integer" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.gaugerange" />
+      <to state="state.fix.eventselect" />
+    </transition>
+
+    <state id="state.fix.eventselect" description="state.fix.eventselect" helpText="help.state.fix.eventselect" state="org.dive4elements.river.artifacts.states.fixation.EventSelect">
+      <data name="events" type="intarray" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.fix.eventselect" />
+      <to state="state.fix.analysis.referenceperiod" />
+      <condition data="calculation.mode" value="calculation.analysis" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.fix.eventselect" />
+      <to state="state.fix.vollmer.function" />
+      <condition data="calculation.mode" value="calculation.vollmer" operator="equal" />
+    </transition>
+
+    <state id="state.fix.analysis.referenceperiod" helpText="help.state.fix.analysis.referenceperiod" description="state.fix.analysis.referenceperiod" state="org.dive4elements.river.artifacts.states.fixation.ReferencePeriod">
+      <data name="ref_start" type="Long" />
+      <data name="ref_end" type="Long" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.analysis.referenceperiod" />
+      <to state="state.fix.analysis.analysisperiods" />
+    </transition>
+
+    <state id="state.fix.analysis.analysisperiods" helpText="help.state.fix.analysis.analysisperiods" description="state.fix.analysis.analysisperiods" state="org.dive4elements.river.artifacts.states.fixation.AnalysisPeriods">
+      <data name="ana_data" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.analysis.analysisperiods" />
+      <to state="state.fix.analysis.function" />
+    </transition>
+
+    <state id="state.fix.analysis.function" helpText="help.state.fix.analysis.function" description="state.fix.analysis.function" state="org.dive4elements.river.artifacts.states.fixation.FunctionSelect">
+      <data name="function" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.analysis.function" />
+      <to state="state.fix.analysis.preprocessing" />
+    </transition>
+
+    <state id="state.fix.analysis.preprocessing" helpText="help.state.fix.analysis.preprocessing" description="state.fix.analysis.preprocessing" state="org.dive4elements.river.artifacts.states.fixation.PreprocessingSelect">
+      <data name="preprocessing" type="Boolean" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.analysis.preprocessing" />
+      <to state="state.fix.analysis.compute" />
+    </transition>
+
+    <state id="state.fix.analysis.compute" helpText="help.state.fix.analysis.compute" description="state.fix.analysis.compute" state="org.dive4elements.river.artifacts.states.fixation.FixAnalysisCompute">
+        <outputmodes>
+          <outputmode name="fix_deltawt_export" description="output.fix_deltawt_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.fix_deltawt.csv" /> 
+          </facets>
+        </outputmode>
+         <outputmode name="fix_waterlevel_export" description="output.fix_waterlevel_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.waterlevel_export.csv" />
+            <facet name="wst" description="facet.waterlevel_export.wst" />
+            <facet name="pdf" description="facet.waterlevel_export.pdf" />
+          </facets>
+        </outputmode>
+
+        <outputmode name="fix_parameters_export" description="output.fix_parameters_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="fix_parameters" description="facet.fix_parameters.csv" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_wq_curve_at_export" description="output.fix_wq_curve_at_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="at" description="facet.fix_wq_curve_export.at" />
+          </facets>
+        </outputmode>
+ 
+        <outputmode name="fix_wq_curve" description="output.fix_wq_curve" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_wq_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_analysis_events_wq" description="Raw event values used in the calculation" />
+            <facet name="fix_reference_events_wq" description="Raw event values used in the calculation" />
+            <facet name="fix_wq_curve" description="WQ curve" />
+            <facet name="qsectors" description="qsectors." />
+            <facet name="fix_outlier" description="The outliers" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+            <facet name="other.wkms" description="facet.other.wkms" />
+            <facet name="other.wkms.marks" description="facet.other.wkms.makrs" />
+            <facet name="other.wqkms" description="facet.other.wqkms" />
+            <facet name="longitudinal_section.w" description="facet.longitudinal_section.w" />
+            <facet name="other.wq" description="Point-like data like fixations" />
+            <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points" />
+            <facet name="discharge_curve.curve" description="facet.discharge_curve.curve" />
+            <facet name="fix_wq_curve.manualpoints" description="Manual points" />
+            <facet name="mainvalues.q" description="mainvalues.q" />
+            <facet name="mainvalues.w" description="mainvalues.w" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_deltawt_curve" description="output.fix_deltawt_curve" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_dwt_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_dwt_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_dwt_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_dwt_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_analysis_events_dwt" description="Raw event values used in the calculation" />
+            <facet name="fix_reference_events_dwt" description="Raw event values used in the calculation" />
+            <facet name="fix_analysis_periods_dwt" description="Dateranges of analysis periods." />
+            <facet name="fix_deviation_dwt" description="The standard variance" />
+            <facet name="fix_deltawt_curve.manualpoints" description="Manual points" />
+            <facet name="fix_reference_period_dwt" description="Reference period" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_longitudinal_section_curve" description="output.fix_longitudinal_section_curve" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_ls_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_ls_deviation_3" description="Average values for Ws in Q sectors." />
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            <facet name="fix_deviation_ls" description="The standard variance" />
+            <facet name="fix_analysis_events_ls" description="Average values for Ws in Q sectors." />
+            <facet name="fix_reference_events_ls" description="Average values for Ws in Q sectors." />
+            <facet name="fix_longitudinal_section_curve.manualpoints" description="Manual points" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_derivate_curve" description="output.fix_derivate_curve" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_derivate_curve" description="Derivate curve" />
+            <facet name="fix_derivate_curve.manualpoints" description="Manual points" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_report" description="output.fix_report.report" mime-type="text/plain" type="report">
+          <facets>
+            <facet name="report" description="facet.fix.report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+    <state id="state.fix.vollmer.function" helpText="help.state.fix.vollmer.function" description="state.fix.vollmer.function" state="org.dive4elements.river.artifacts.states.fixation.FunctionSelect">
+      <data name="function" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.vollmer.function" />
+      <to state="state.fix.vollmer.preprocessing" />
+    </transition>
+
+    <state id="state.fix.vollmer.preprocessing" helpText="help.state.fix.vollmer.preprocessing" description="state.fix.vollmer.preprocessing" state="org.dive4elements.river.artifacts.states.fixation.PreprocessingSelect">
+      <data name="preprocessing" type="Boolean" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.vollmer.preprocessing" />
+      <to state="state.fix.vollmer.qs" />
+    </transition>
+
+    <state id="state.fix.vollmer.qs" description="state.fix.vollmer.qs" helpText="help.state.fix.vollmer.qs" state="org.dive4elements.river.artifacts.states.WQFixing">
+      <data name="wq_isq" type="String" />
+      <data name="wq_values" type="WQTriple" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.fix.vollmer.qs" />
+      <to state="state.fix.vollmer.compute" />
+    </transition>
+
+    <state id="state.fix.vollmer.compute" helpText="help.state.fix.vollmer.compute" description="state.fix.vollmer.compute" state="org.dive4elements.river.artifacts.states.fixation.FixRealizingCompute">
+      <outputmodes>
+        <outputmode name="longitudinal_section" description="output.longitudinal_section" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="longitudinal_section.w" description="facet.longitudinal_section.w" />
+            <facet name="longitudinal_section.q" description="facet.longitudinal_section.q" />
+            <facet name="w_differences" description="facet.w_differences" />
+            <facet name="other.wkms" description="facet.other.wkms" />
+            <facet name="other.wq" description="WQ-Type of data" />
+            <facet name="other.wqkms" description="facet.other.wqkms" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+            <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points" />
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            <facet name="longitudinal_section.area" description="facet.longitudinal_section.area" />
+            <facet name="longitudinal_section.manualpoints" description="Manuelle Punkte" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_wq_curve" description="output.fix_wq_curve" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="fix_sector_average_wq_0" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_1" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_2" description="Average values for Ws in Q sectors." />
+            <facet name="fix_sector_average_wq_3" description="Average values for Ws in Q sectors." />
+            <facet name="fix_analysis_events_wq" description="Raw event values used in the calculation" />
+            <facet name="fix_wq_curve" description="WQ curve" />
+            <facet name="fix_wq_ls" description="WQ LS curve" />
+            <facet name="fix_outlier" description="The outliers" />
+            <facet name="qsectors" description="qsectors." />
+            <facet name="fix_events_wqkms" description="WQKMS-Type of data" />
+            <facet name="other.wqkms.q" description="W-Type of data" />
+            <facet name="other.wqkms.w" description="W-Type of data" />
+            <facet name="other.wkms" description="facet.other.wqkms" />
+            <facet name="other.wqkms" description="facet.other.wqkms" />
+            <!--issue1383: facet name="longitudinal_section.w" description="facet.longitudinal_section.w"/ -->
+            <facet name="other.wq" description="Point-like data like fixations" />
+            <facet name="heightmarks_points" description="facet.other.wkms.heightmarks_points" />
+            <facet name="discharge_curve.curve" description="facet.discharge_curve.curve" />
+            <facet name="mainvalues.w" description="facet.fix_wq.mainvalues.w" />
+            <facet name="mainvalues.q" description="facet.fix_wq.mainvalues.q" />
+          </facets>
+        </outputmode>
+        <outputmode name="cross_section" description="output.cross_section" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="cross_section_water_line" description="facet.cross_section_water_line" />
+            <facet name="cross_section" description="facet.cross_section" />
+            <facet name="area" description="an area" />
+            <facet name="cross_section.area" description="an area" />
+            <facet name="cross_section.manualpoints" description="points" />
+            <facet name="cross_section.manualline" description="line" />
+            <facet name="hyk" description="hyks" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_wq_curve_at_export" description="output.fix_wq_curve_at_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="at" description="facet.fix_wq_curve_export.at" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_waterlevel_export" description="output.fix_waterlevel_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.waterlevel_export.csv" />
+            <facet name="wst" description="facet.waterlevel_export.wst" />
+            <facet name="pdf" description="facet.waterlevel_export.pdf" />
+          </facets>
+        </outputmode>
+        <outputmode name="fix_report" description="output.fix_report.report" mime-type="text/plain" type="report">
+          <facets>
+            <facet name="report" description="facet.fix.report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+    
+  </states>
 </artifact>
--- a/artifacts/doc/conf/artifacts/manualpoints.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/artifacts/manualpoints.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -35,6 +35,14 @@
             <facet name="sq_relation_e.manualpoints" />
             <facet name="bed_longitudinal_section.manualpoints" />
             <facet name="sq_relation_f.manualpoints" />
+
+            <facet name="sinfo_flow_depth.manualpoints" />
+            <facet name="sinfo_flow_depth_minmax.manualpoints" />
+            <facet name="sinfo_flow_depth_development.manualpoints" />
+            <facet name="sinfo_flow_depth_development_peryear.manualpoints" />
+            <facet name="sinfo_tkk.manualpoints" />
+            <facet name="sinfo_collision.manualpoints" />
+            <facet name="sinfo_flood_duration.manualpoints" />
           </facets>
         </outputmode>
       </outputmodes>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/artifacts/sinfo.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,462 @@
+<?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>
+
+    <!-- Calculation Mode: Fließtiefen (Flow Depth) -->
+    <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_depth" mime-type="image/png" type="chart">
+          <facets>
+            <!-- REMARK: id's that ends with 'filtered' are handled differently
+              ' -->
+            <facet name="sinfo_facet_flow_depth.filtered" description="flow depth, filtered by current zoom state" />
+            <facet name="sinfo_facet_flow_depth" description="flow depth" />
+
+            <facet name="sinfo_facet_flow_depth_with_tkh.filtered" description="flow depth including tkh, filtered by current zoom state" />
+            <facet name="sinfo_facet_flow_depth_with_tkh" description="flow depth including tkh" />
+
+            <facet name="sinfo_facet_tkh" description="Facet for tkh" />
+
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+
+            <facet name="sinfo_flow_depth.manualpoints" description="Manual Points" />
+          </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>
+
+    <!-- Calculation Mode: Minimale/maximale Fließtiefe -->
+    <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_minmax" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.distance_only" />
+      <to state="state.sinfo.waterlevel_soundings_minmax_select" />
+      <condition data="calculation_mode" value="sinfo_calc_flow_depth_minmax" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.waterlevel_soundings_minmax_select" description="state.sinfo.waterlevel_soundings_minmax_select" state="org.dive4elements.river.artifacts.sinfo.flowdepthminmax.FlowDepthMinMaxPairSelectState" helpText="help.state.sinfo.waterlevel_soundings_minmax_select">
+      <data name="diffids" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.waterlevel_soundings_minmax_select" />
+      <to state="state.sinfo.flow_depth_minmax" />
+      <condition data="calculation_mode" value="sinfo_calc_flow_depth_minmax" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.flow_depth_minmax" description="state.sinfo.flow_depth_minmax" state="org.dive4elements.river.artifacts.sinfo.flowdepthminmax.FlowDepthMinMaxState" helpText="help.state.sinfo.flow_depth_minmax">
+      <outputmodes>
+        <outputmode name="sinfo_flow_depth_minmax" description="output.flow_depth" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="sinfo_facet_flow_depth_min.filtered" description="min flow depth" />
+            <facet name="sinfo_facet_flow_depth_min" description="min flow depth" />
+            <facet name="sinfo_facet_flow_depth_max.filtered" description="max flow depth" />
+            <facet name="sinfo_facet_flow_depth_max" description="max flow depth" />
+
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            
+            <facet name="sinfo_flow_depth_minmax.manualpoints" description="Manual Points" />            
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_flowdepthminmax_export" description="output.sinfo_flowdepthminmax_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.sinfo_flowdepthminmax_export.csv" />
+            <facet name="pdf" description="facet.sinfo_flowdepthminmax_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>
+
+    <!-- Calculation Mode: Fließtiefenentwicklung -->
+    <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_development" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.distance_only" />
+      <to state="state.sinfo.flowdepthdevlopment_current_select" />
+      <condition data="calculation_mode" value="sinfo_calc_flow_depth_development" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.flowdepthdevlopment_current_select" description="state.sinfo.flowdepthdevlopment_current_select" state="org.dive4elements.river.artifacts.sinfo.flowdepthdev.WaterlevelSoundingCurrentPairSelectState" helpText="help.state.sinfo.flowdepthdevlopment_current_select">
+      <data name="diffid_current" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.flowdepthdevlopment_current_select" />
+      <to state="state.sinfo.flowdepthdevlopment_historical_select" />
+      <condition data="calculation_mode" value="sinfo_calc_flow_depth_development" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.flowdepthdevlopment_historical_select" description="state.sinfo.flowdepthdevlopment_historical_select" state="org.dive4elements.river.artifacts.sinfo.flowdepthdev.WaterlevelSoundingHistoricalPairSelectState" helpText="help.state.sinfo.flowdepthdevlopment_historical_select">
+      <data name="diffid_historical" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.flowdepthdevlopment_historical_select" />
+      <to state="state.sinfo.flow_depth_development" />
+      <condition data="calculation_mode" value="sinfo_calc_flow_depth_development" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.flow_depth_development" description="state.sinfo.flow_depth_development" state="org.dive4elements.river.artifacts.sinfo.flowdepthdev.FlowDepthDevelopmentState" helpText="help.state.sinfo.flow_depth_development">
+      <outputmodes>
+        <outputmode name="sinfo_flow_depth_development" description="output.flow_depth_development" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="sinfo_facet_flow_depth_development.filtered" description="flow depth development" />
+            <facet name="sinfo_facet_flow_depth_development" description="flow depth development" />
+
+            <facet name="sinfo_facet_waterlevel_difference.filtered" description="waterlevel difference" />
+            <facet name="sinfo_facet_bedheight_difference.filtered" description="bed Height difference" />
+
+            <facet name="sinfo_facet_flow_depth_current.filtered" description="flow depth current" />
+            <facet name="sinfo_facet_flow_depth_current" description="flow depth current" />
+            <facet name="sinfo_facet_flow_depth_historical.filtered" description="flow depth historical" />
+            <facet name="sinfo_facet_flow_depth_historical" description="flow depth historical" />
+
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            
+            <facet name="sinfo_flow_depth_development.manualpoints" description="Manual Points" />            
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_flow_depth_development_peryear" description="output.flow_depth_development_peryear" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="sinfo_facet_flow_depth_development_per_year.filtered" description="flow depth development per year" />
+            <facet name="sinfo_facet_flow_depth_development_per_year" description="flow depth development per year" />
+
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            
+            <facet name="sinfo_flow_depth_development_peryear.manualpoints" description="Manual Points" />            
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_flowdepthdevelopment_export" description="output.sinfo_flowdepthdevelopment_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.sinfo_flowdepthdevelopment_export.csv" />
+            <facet name="pdf" description="facet.sinfo_flowdepthdevelopment_export.pdf" />
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_flowdepthdevelopment_report" description="output.sinfo_flowdepthdevelopment_report" mime-type="text/xml" type="report">
+          <facets>
+            <facet name="report" description="facet.sinfo_flowdepthdevelopment_report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+
+
+
+    <!-- Calculation Mode: Grundberührungen -->
+
+    <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_collision" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.distance_only" />
+      <to state="state.sinfo.year_epoch" />
+      <condition data="calculation_mode" value="sinfo_calc_collision" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.year_epoch" description="state.sinfo.year_epoch" state="org.dive4elements.river.artifacts.sinfo.collision.YearChoice" helpText="help.state.sinfo.year">
+      <data name="ye_select" type="String" /> 
+    </state>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.year_epoch" />
+      <to state="state.sinfo.load.year" />
+      <condition data="ye_select" value="state.sinfo.year" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.year_epoch" />
+      <to state="state.sinfo.load.epoch" />
+      <condition data="ye_select" value="state.sinfo.epoch" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.load.year" description="state.sinfo.load.year" state="org.dive4elements.river.artifacts.sinfo.collision.LoadMultipleYearSelectState" helpText="help.state.sinfo.load.year">
+      <data name="years" type="String" /> 
+    </state>
+
+    <state id="state.sinfo.load.epoch" description="state.sinfo.load.epoch" state="org.dive4elements.river.artifacts.sinfo.collision.LoadMultipleEpochSelectState" helpText="help.state.sinfo.load.epoch">
+      <data name="epochs" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.load.year" />
+      <to state="state.sinfo.collision" />
+      <condition data="calculation_mode" value="sinfo_calc_collision" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.load.epoch" />
+      <to state="state.sinfo.collision" />
+      <condition data="calculation_mode" value="sinfo_calc_collision" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.collision" description="state.sinfo.collision" state="org.dive4elements.river.artifacts.sinfo.collision.CollisionState" helpText="help.state.sinfo.collision">
+      <outputmodes>
+        <outputmode name="sinfo_collision" description="output.sinfo_collision" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="sinfo_facet_collision_calc_count" description="bed collisions" />
+            <facet name="sinfo_facet_collision_calc_count.2" description="bed collisions" />
+            <facet name="sinfo_facet_collision_calc_count.3" description="bed collisions" />
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+            <facet name="sinfo_collision.manualpoints" description="Manual Points" />
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_collision_export" description="output.sinfo_collision_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.sinfo_collision_export.csv" />
+            <facet name="pdf" description="facet.sinfo_collision_export.pdf" />
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_collision_report" description="output.sinfo_collision_report" mime-type="text/xml" type="report">
+          <facets>
+            <facet name="report" description="facet.sinfo_collision_report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+    <!-- Calculation Mode: Ãœberflutungsdauern Infrastrukturen BWaStr -->
+    <!-- Schrittweite benötigt für wq-state: TODO: vermutlich hier auch nicht? -->
+    <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_flood_duration" operator="equal" />
+    </transition> 
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.distance_only" />
+      <to state="state.sinfo.riverside" />
+      <condition data="calculation_mode" value="sinfo_calc_flood_duration" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.riverside" description="state.sinfo.riverside" state="org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice" helpText="help.state.sinfo.riverside">
+      <data name="riverside" type="String" />
+    </state>
+
+    <state id="state.sinfo.wspl" description="state.sinfo.wspl" state="org.dive4elements.river.artifacts.sinfo.flood_duration.WsplChoice" helpText="help.state.sinfo.wspl">
+      <data name="wspl" type="Boolean" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.riverside" />
+      <to state="state.sinfo.wspl" />
+      <condition data="calculation_mode" value="sinfo_calc_flood_duration" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.wspl" />
+      <to state="state.sinfo.wq" />
+      <condition data="wspl" value="true" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.wspl" />
+      <to state="state.sinfo.flood_duration" />
+      <condition data="wspl" value="false" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.wq" />
+      <to state="state.sinfo.flood_duration" />
+      <condition data="calculation_mode" value="sinfo_calc_flood_duration" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.flood_duration" description="state.sinfo.flood_duration" state="org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationState" helpText="help.state.sinfo.flood_duration">
+      <outputmodes>
+        <outputmode name="sinfo_flood_duration" description="output.sinfo_flood_duration" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="sinfo_facet_flood_duration.left" description="flood duration of the heights of the left bank infrastructures (points)"/>
+            <facet name="sinfo_facet_flood_duration.right" description="flood duration of the heights of the right bank infrastructures (points)"/>
+            <facet name="mainvalue.duration" description="flood duration of W main value"/>
+          </facets>
+        </outputmode>
+        <outputmode name="sinfo_flood_height" description="output.sinfo_flood_height" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="sinfo_facet_flood_height.left" description="flood heights of the left bank infrastructures (points)"/>
+            <facet name="sinfo_facet_flood_height.right" description="flood heights of the right bank infrastructures (points)"/>
+            <facet name="mainvalue.w" description="W of main value"/>
+       
+          </facets>
+        </outputmode>
+        <outputmode name="sinfo_floodduration_curve" description="output.sinfo_duration_curve" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="duration_curve.w" description="facet.duration_curve.w"/>
+            <facet name="duration_curve.q" description="facet.duration_curve.q"/>
+            <facet name="infrastructure.w" description="geodetic height of the infrastructure"/>
+            <facet name="mainvalues.w" description="W Main Values"/>
+            <facet name="mainvalues.q" description="Q Main Values at optional second axis"/>
+            <facet name="infrastructure.q" description="discharge of the infrastructure height"/>
+            <facet name="duration_curve.manualpoints" description="Manuelle Punkte"/>
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_floodduration_export" description="output.sinfo_floodduration_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.sinfo_flood_duration_export.csv" />
+            <facet name="pdf" description="facet.sinfo_flood_duration_export.pdf" />
+          </facets>
+        </outputmode>
+ 
+         <outputmode name="sinfo_flood_duration_report" description="output.sinfo_flood_duration_report" mime-type="text/xml" type="report">
+          <facets>
+            <facet name="report" description="facet.sinfo_flood_duration_report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+    <!-- Calculation Mode: Transportkörperhöhen -->
+    <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_transport_bodies_heights" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.distance_only" />
+      <to state="state.sinfo.wq" />
+      <condition data="calculation_mode" value="sinfo_calc_transport_bodies_heights" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.wq" description="state.sinfo.wq" state="org.dive4elements.river.artifacts.states.WQSelect" helpText="help.state.sinfo.wq">
+      <data name="wq_isq" type="Boolean" />
+      <data name="wq_isfree" type="Boolean" />
+      <data name="wq_isrange" type="Boolean" />
+      <data name="wq_from" type="Double" />
+      <data name="wq_to" type="Double" />
+      <data name="wq_step" type="Double" />
+      <data name="wq_single" type="Double[]" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.sinfo.wq" />
+      <to state="state.sinfo.transport_bodies_heights" />
+      <condition data="calculation_mode" value="sinfo_calc_transport_bodies_heights" operator="equal" />
+    </transition>
+
+    <state id="state.sinfo.transport_bodies_heights" description="state.sinfo.transport_bodies_heights" state="org.dive4elements.river.artifacts.sinfo.tkhstate.TkhState" helpText="help.state.sinfo.transport_bodies_heights">
+      <outputmodes>
+        <outputmode name="sinfo_tkk" description="output.tkk" mime-type="image/png" type="chart">
+          <facets>
+            <!-- REMARK: id's that ends with 'filtered' are handled differently
+              ' -->
+            <!-- FIXME: should be filtered according to spec -->
+            <facet name="sinfo_facet_tkh" description="Facet for tkh" />
+
+            <facet name="longitudinal_section.annotations" description="facet.longitudinal_section.annotations" />
+
+            <facet name="sinfo_tkk.manualpoints" description="Manual Points" />
+
+            <facet name="sinfo_facet_flow_depth.filtered" description="mean flow depth" />
+            <facet name="sinfo_facet_flow_depth" description="mean flow depth" />
+
+            <facet name="sinfo_facet_velocity" description="Velocity" />
+            <facet name="sinfo_facet_d50" description="D50" />
+            <facet name="sinfo_facet_tau" description="Tau" />
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_tkh_export" description="output.sinfo_tkh_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.sinfo_tkh_export.csv" />
+            <facet name="pdf" description="facet.sinfo_tkh_export.pdf" />
+          </facets>
+        </outputmode>
+
+        <outputmode name="sinfo_tkh_report" description="output.sinfo_tkh_report" mime-type="text/xml" type="report">
+          <facets>
+            <facet name="report" description="facet.sinfo_tkh_report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+  </states>
+</artifact>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/artifacts/uinfo.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,427 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<artifact name="uinfo">
+
+  <states>
+    <state id="state.uinfo.river" description="state.uinfo.river" state="org.dive4elements.river.artifacts.states.RiverSelect" helpText="help.state.uinfo.river">
+      <data name="river" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
+      <from state="state.uinfo.river" />
+      <to state="state.uinfo.calculation_mode" />
+    </transition>
+
+    <state id="state.uinfo.calculation_mode" description="state.uinfo.calculation_mode" state="org.dive4elements.river.artifacts.uinfo.CalculationSelectUinfo" helpText="help.state.uinfo.calculation_mode">
+      <data name="calculation_mode" type="String" />
+    </state>
+
+    <state id="state.uinfo.distance_only" description="state.uinfo.distance_only" state="org.dive4elements.river.artifacts.states.DistanceOnlySelect" helpText="help.state.uinfo.distance_only">
+      <data name="ld_from" type="Double" />
+      <data name="ld_to" type="Double" />
+    </state>
+
+    <state id="state.uinfo.inundationduration.distance_only" description="state.uinfo.inundationduration.distance_only" state="org.dive4elements.river.artifacts.states.DistanceOnlyInundationDurSelect" helpText="help.state.uinfo.distance_only">
+      <data name="ld_from" type="Double" />
+      <data name="ld_to" type="Double" />
+    </state>
+
+    <state id="state.uinfo.distance" description="state.uinfo.distance" state="org.dive4elements.river.artifacts.states.DistanceSelect" helpText="help.state.uinfo.distance_only">
+      <data name="ld_from" type="Double" />
+      <data name="ld_to" type="Double" />
+      <data name="ld_step" type="Double" />
+    </state>
+
+
+
+    <!-- Calculation Mode: Salix Linie -->
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.calculation_mode" />
+      <to state="state.uinfo.distance_only" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.distance_only" />
+      <to state="state.uinfo.use_scenario" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+
+
+    <state id="state.uinfo.use_scenario" description="state.uinfo.use_scenario" state="org.dive4elements.river.artifacts.uinfo.salix.UseScenarioChoice" helpText="help.state.uinfo.use_scenario">
+      <data name="use_scenario" type="Boolean" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.use_scenario" />
+      <to state="state.uinfo.scenario_type" />
+      <condition data="use_scenario" value="true" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.use_scenario" />
+      <to state="state.uinfo.salix_line" />
+      <condition data="use_scenario" value="false" operator="equal" />
+    </transition>
+
+    <state id="state.uinfo.scenario_type" description="state.uinfo.scenario_type" state="org.dive4elements.river.artifacts.uinfo.salix.ScenarioTypeState" helpText="help.state.uinfo.scenario_type">
+      <data name="scenario_selection" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.scenario_type" />
+      <to state="state.uinfo.distance_only_part.from_regional" />
+      <condition data="scenario_selection" value="scenarioType.option1" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.scenario_type" />
+      <to state="state.uinfo.salix.supraregional" />
+      <condition data="scenario_selection" value="scenarioType.option2" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.salix.supraregional" />
+      <to state="state.uinfo.salix_line" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+    
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.scenario_type" />
+      <to state="state.uinfo.year_epoch" />
+      <condition data="scenario_selection" value="scenarioType.option3" operator="equal" />
+    </transition>
+
+    <state id="state.uinfo.year_epoch" description="state.uinfo.year_epoch" state="org.dive4elements.river.artifacts.uinfo.salix.YearChoice" helpText="help.state.uinfo.year">
+      <data name="ye_select" type="String" />
+    </state>
+    <state id="state.uinfo.salix.supraregional" description="state.uinfo.salix.supraregional" state="org.dive4elements.river.artifacts.uinfo.salix.SupraRegionalTableState" helpText="help.state.uinfo.salix">
+      <data name="supraregional_table" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.year_epoch" />
+      <to state="state.uinfo.load.year_with_soundings" />
+      <condition data="ye_select" value="state.uinfo.year" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.year_epoch" />
+      <to state="state.uinfo.load.epoch" />
+      <condition data="ye_select" value="state.uinfo.epoch" operator="equal" />
+    </transition>
+
+    <state id="state.uinfo.load.year_with_soundings" description="state.uinfo.load.year_with_soundings" state="org.dive4elements.river.artifacts.uinfo.salix.LoadSingleYearSelectState" helpText="help.state.uinfo.load.year">
+      <data name="singleyear" type="String" />
+    </state>
+
+    <state id="state.uinfo.load.epoch" description="state.uinfo.load.epoch" state="org.dive4elements.river.artifacts.uinfo.salix.LoadSingleEpochSelectState" helpText="help.state.uinfo.load.epoch">
+      <data name="singleepoch" type="Integer" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.load.epoch" />
+      <to state="state.uinfo.distance_only_part.historical" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.load.year_with_soundings" />
+      <to state="state.uinfo.distance_only_part.historical" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+
+    <state id="state.uinfo.distance_only_part.historical" description="state.uinfo.distance_only_part.historical" state="org.dive4elements.river.artifacts.uinfo.salix.DistanceOnlyPartHistoricalSelect" helpText="help.state.uinfo.distance_only">
+      <data name="ld_from_part" type="Double" />
+      <data name="ld_to_part" type="Double" />
+       <data name="bedheights_for_part" type="Double" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.distance_only_part.historical" />
+      <to state="state.uinfo.salix_line" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+
+    <state id="state.uinfo.inundation.scenario.regional" description="state.uinfo.inundation.scenario.regional" state="org.dive4elements.river.artifacts.uinfo.salix.LoadScenarioSelectLimit5" helpText="help.state.uinfo.use_scenario">
+      <data name="sedimentheight" type="String" /> <!-- mittelwasserlage in cm! -->
+    </state>
+
+    <state id="state.uinfo.distance_only_part.from_regional" description="state.uinfo.distance_only_part.from_regional" state="org.dive4elements.river.artifacts.states.DistanceOnlyPartSelect" helpText="help.state.uinfo.distance_only">
+      <data name="ld_from_part" type="Double" />
+      <data name="ld_to_part" type="Double" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.distance_only_part.from_regional" />
+      <to state="state.uinfo.inundation.scenario.regional" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.inundation.scenario.regional" />
+      <to state="state.uinfo.salix_line" />
+      <condition data="calculation_mode" value="uinfo_salix_line" operator="equal" />
+    </transition>
+
+
+    <state id="state.uinfo.salix_line" description="state.uinfo.salix_line" state="org.dive4elements.river.artifacts.uinfo.salix.SalixLineState" helpText="help.state.uinfo.salix_line">
+      <outputmodes>
+
+        <!-- FIXME: i01n name in FLYSConstants -->
+        <outputmode name="uinfo_salix_line_export" description="output.uinfo_salix_line_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.uinfo_salix_line_export.csv" />
+            <facet name="pdf" description="facet.uinfo_salix_line_export.pdf" />
+          </facets>
+        </outputmode>
+
+        <!-- FIXME: i01n name in FLYSConstants -->
+        <outputmode name="uinfo_salix_line_report" description="output.uinfo_salix_line_report" mime-type="text/xml" type="report">
+          <facets>
+            <facet name="report" description="facet.uinfo_salix_line_report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+
+
+
+
+    <!-- Calculation Mode: Inundation Duration -->
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.calculation_mode" />
+      <to state="state.uinfo.inundationduration.distance_only" />
+      <condition data="calculation_mode" value="uinfo_inundation_duration" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.inundationduration.distance_only" />
+      <to state="state.uinfo.year_totalepoch" />
+      <condition data="calculation_mode" value="uinfo_inundation_duration" operator="equal" />
+    </transition>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.year_totalepoch" />
+      <to state="state.uinfo.load.year" />
+      <condition data="ye_select" value="state.uinfo.year" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.year_totalepoch" />
+      <to state="state.uinfo.inundation.use_scenario" />
+      <condition data="ye_select" value="state.uinfo.totalepoch" operator="equal" />
+    </transition>
+
+
+    <state id="state.uinfo.year_totalepoch" description="state.uinfo.year_totalepoch" state="org.dive4elements.river.artifacts.uinfo.inundationduration.YearChoice" helpText="help.state.uinfo.year">
+      <data name="ye_select" type="String" />
+    </state>
+
+
+    <state id="state.uinfo.load.year" description="state.uinfo.load.year" state="org.dive4elements.river.artifacts.uinfo.inundationduration.LoadSingleYearSelectState" helpText="help.state.uinfo.load.year">
+      <data name="singleyear" type="String" />
+    </state>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.load.year" />
+      <to state="state.uinfo.inundation.use_scenario" />
+      <condition data="calculation_mode" value="uinfo_inundation_duration" operator="equal" />
+    </transition>
+
+    <!-- Doppelter State, andere ID, damit keine Mehrfach-Condition benötigt wird -->
+    <state id="state.uinfo.inundation.use_scenario" description="state.uinfo.inundation.use_scenario" state="org.dive4elements.river.artifacts.uinfo.salix.UseScenarioChoice" helpText="help.state.uinfo.use_scenario">
+      <data name="use_scenario" type="Boolean" />
+    </state>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.inundation.use_scenario" />
+      <to state="state.uinfo.inundation.scenario" />
+      <condition data="use_scenario" value="true" operator="equal" />
+    </transition>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.inundation.use_scenario" />
+      <to state="state.uinfo.inundation.vegetation" />
+      <condition data="use_scenario" value="false" operator="equal" />
+    </transition>
+
+
+    <state id="state.uinfo.inundation.scenario" description="state.uinfo.inundation.scenario" state="org.dive4elements.river.artifacts.uinfo.inundationduration.LoadScenarioSelect" helpText="help.state.uinfo.use_scenario">
+      <data name="sedimentheight" type="String" /> <!-- mittelwasserlage in cm! -->
+    </state>
+
+    <state id="state.uinfo.inundation.vegetation" description="state.uinfo.inundation.vegetation" state="org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZonesTableState" helpText="help.state.uinfo.use_scenario">
+      <data name="vegzones" type="String" />
+    </state>
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.inundation.scenario" />
+      <to state="state.uinfo.inundation.vegetation" />
+      <condition data="calculation_mode" value="uinfo_inundation_duration" operator="equal" />
+    </transition>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.inundation.vegetation" />
+      <to state="state.uinfo.inundation_duration" />
+      <condition data="calculation_mode" value="uinfo_inundation_duration" operator="equal" />
+    </transition>
+
+    <state id="state.uinfo.inundation_duration" description="state.uinfo.inundation_duration" state="org.dive4elements.river.artifacts.uinfo.inundationduration.InundationDurationState" helpText="help.state.uinfo.inundation_duration">
+      <outputmodes>
+
+        <outputmode name="map" description="output.uesk.map.description" type="map">
+          <facets>
+            <facet name="floodmap.wsplgen" />
+            <facet name="floodmap.barriers" />
+            <facet name="floodmap.riveraxis" />
+            <facet name="floodmap.wmsbackground" />
+            <facet name="floodmap.kms" />
+            <facet name="floodmap.qps" />
+            <facet name="floodmap.hws_lines" />
+            <facet name="floodmap.hws_points" />
+            <facet name="floodmap.hydr_boundaries" />
+            <facet name="floodmap.hydr_boundaries_poly" />
+            <facet name="floodmap.catchment" />
+            <facet name="floodmap.floodplain" />
+            <facet name="floodmap.floodmarks" />
+            <facet name="floodmap.lines" />
+            <facet name="floodmap.buildings" />
+            <facet name="floodmap.fixpoints" />
+            <facet name="floodmap.floodmaps" />
+            <facet name="floodmap.gauge_location" />
+            <facet name="floodmap.externalwms" />
+            <facet name="floodmap.externalwms_1" />
+            <facet name="floodmap.externalwms_2" />
+            <facet name="floodmap.externalwms_3" />
+            <facet name="floodmap.externalwms_4" />
+            <facet name="floodmap.jetties" />
+          </facets>
+        </outputmode>
+
+        <!-- FIXME: i01n name in FLYSConstants -->
+        <outputmode name="uinfo_inundation_duration_export" description="output.uinfo_inundation_duration_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="wms_url" description="XXXXXXXXXX _ no entry in generators necessary either" />
+          </facets>
+        </outputmode>
+
+        <outputmode name="uinfo_inundation_duration_report" description="output.uinfo_inundation_duration_report" mime-type="text/xml" type="report">
+          <facets>
+            <facet name="report" description="facet.uinfo_inundation_duration_report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    <!-- Calculation Mode: Vegetation Zones -->
+
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.calculation_mode" />
+      <to state="state.uinfo.distance_only" />
+      <condition data="calculation_mode" value="uinfo_vegetation_zones" operator="equal" />
+    </transition>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.distance_only" />
+      <to state="state.uinfo.vegetation_zones.table" />
+      <condition data="calculation_mode" value="uinfo_vegetation_zones" operator="equal" />
+    </transition>
+ 
+
+
+    <state id="state.uinfo.vegetation_zones.table" description="state.uinfo.vegetation_zones.table" state="org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZonesTableEditState" helpText="help.state.uinfo.vegetation_zones">
+      <data name="vegzones" type="String" />
+    </state>
+
+
+    <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+      <from state="state.uinfo.vegetation_zones.table" />
+      <to state="state.uinfo.vegetation_zones" />
+      <condition data="calculation_mode" value="uinfo_vegetation_zones" operator="equal" />
+    </transition>
+
+
+    <state id="state.uinfo.vegetation_zones" description="state.uinfo.vegetation_zones" state="org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZonesState" helpText="help.state.uinfo.vegetation_zones">
+      <outputmodes>
+
+        <!-- FIXME: i01n name in FLYSConstants -->
+        <outputmode name="uinfo_vegetation_zones_export" description="output.uinfo_vegetation_zones_export" mime-type="text/plain" type="export">
+          <facets>
+            <facet name="csv" description="facet.uinfo_vegetation_zones_export.csv" />
+            <facet name="pdf" description="facet.uinfo_vegetation_zones_export.pdf" />
+          </facets>
+        </outputmode>
+
+        <!-- FIXME: i01n name in FLYSConstants -->
+        <outputmode name="uinfo_vegetation_zones_report" description="output.uinfo_vegetation_zones_report" mime-type="text/xml" type="report">
+          <facets>
+            <facet name="report" description="facet.uinfo_vegetation_zones_report" />
+          </facets>
+        </outputmode>
+      </outputmodes>
+    </state>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  </states>
+</artifact>
\ No newline at end of file
--- a/artifacts/doc/conf/conf.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/conf.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -22,6 +22,10 @@
     <!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">    
+    <!ENTITY uinfo_artifact SYSTEM "artifacts/uinfo.xml">  
+    <!ENTITY bundu_artifact SYSTEM "artifacts/bundu.xml">     
 ]>
 <artifact-database>
     <export-secret>YOUR_SECRET</export-secret>
@@ -168,6 +172,40 @@
             <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>
+            <!-- UINFO specific Artifacts -->
+            <artifact-factory name="uinfo" description="Factory to create an artifact to be used in module uinfo."
+                ttl="3600000"
+                artifact="org.dive4elements.river.artifacts.uinfo.UINFOArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+                
+            <!-- BUNDU specific Artifacts -->
+            <artifact-factory name="bundu" description="Factory to create an artifact to be used in module bundu."
+                ttl="3600000"
+                artifact="org.dive4elements.river.artifacts.bundu.BUNDUArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+                
+            <artifact-factory name="channelf" description="Factory to create an artifact used in sinfo datacage."
+                ttl="3600000"
+               artifact="org.dive4elements.river.artifacts.sinfo.predefinedchannel.PredefinedChannelArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+            <artifact-factory name="tkhxf" description="Factory to create an artifact used in sinfo datacage."
+                ttl="3600000"
+                artifact="org.dive4elements.river.artifacts.sinfo.predefinedtkh.PredefinedTkhArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+            <artifact-factory name="depthevolxf" description="Factory to create an artifact used in sinfo datacage."
+                ttl="3600000"
+               artifact="org.dive4elements.river.artifacts.sinfo.predefineddepthevol.PredefinedDepthEvolArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+            <artifact-factory name="flowdepthxf" description="Factory to create an artifact used in sinfo datacage."
+                ttl="3600000"
+               artifact="org.dive4elements.river.artifacts.sinfo.predefinedflowdepth.PredefinedFlowDepthArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+            <artifact-factory name="infrastructuref" description="Factory to create an artifact used in sinfo datacage."
+                ttl="3600000"
+               artifact="org.dive4elements.river.artifacts.sinfo.flood_duration.InfrastructureArtifact">org.dive4elements.artifactdatabase.DefaultArtifactFactory</artifact-factory>
+            <artifact-factory name="collisionf" description="Factory to create an artifact used in sinfo datacage."
+                ttl="3600000"
+               artifact="org.dive4elements.river.artifacts.sinfo.collision.CollisionArtifact">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 +337,10 @@
         &gaugedischargecurve-artifact;
         &sedimentload-artifact;
         &sedimentload-ls-artifact;
+       
+        &sinfo_artifact;
+        &uinfo_artifact;
+        &bundu_artifact;
     </artifacts>
 
     &modules;
--- a/artifacts/doc/conf/floodmap.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/floodmap.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -12,9 +12,9 @@
         <logfile path="${artifacts.config.dir}/../velocity.log"/>
     </velocity>
 
-    <river name="Beispielfluss">
+  <river name="Beispielfluss">
         <srid value="31467"/>
         <river-wms url="http://localhost:8081/cgi-bin/river-wms" layers="Beispielfluss"/>
         <background-wms url="http://osm.intevation.de/bfg/service?" layers="OSM-WMS-Dienst"/>
-    </river>
+    </river> 
 </floodmap>
--- a/artifacts/doc/conf/generators/generators.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/generators/generators.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -3,60 +3,82 @@
     &longitudinal-diagrams;
     &discharge-diagrams;
 
-    <output-generator names="cross_section" class="org.dive4elements.river.exports.CrossSectionGenerator"/>
-    <output-generator names="cross_section_chartinfo" class="org.dive4elements.river.exports.CrossSectionInfoGenerator"/>
-    <output-generator names="duration_curve" class="org.dive4elements.river.exports.DurationCurveGenerator"/>
-    <output-generator names="duration_curve_chartinfo" class="org.dive4elements.river.exports.DurationCurveInfoGenerator"/>
-    <output-generator names="waterlevel_export" class="org.dive4elements.river.exports.WaterlevelExporter"/>
+  <output-generator names="cross_section" class="org.dive4elements.river.exports.CrossSectionGenerator" />
+  <output-generator names="cross_section_chartinfo" class="org.dive4elements.river.exports.CrossSectionInfoGenerator" />
+  <output-generator names="duration_curve" class="org.dive4elements.river.exports.DurationCurveGenerator" />
+  <output-generator names="duration_curve_chartinfo" class="org.dive4elements.river.exports.DurationCurveInfoGenerator" />
+  <output-generator names="waterlevel_export" class="org.dive4elements.river.exports.WaterlevelExporter" />
 
-    <output-generator names="historical_discharge_chartinfo" class="org.dive4elements.river.exports.HistoricalDischargeCurveInfoGenerator"/>
-    <output-generator names="historical_discharge" class="org.dive4elements.river.exports.HistoricalDischargeCurveGenerator"/>
+  <output-generator names="historical_discharge_chartinfo" class="org.dive4elements.river.exports.HistoricalDischargeCurveInfoGenerator" />
+  <output-generator names="historical_discharge" class="org.dive4elements.river.exports.HistoricalDischargeCurveGenerator" />
 
-    <!-- This is deactivated.
+  <!-- This is deactivated.
     <output-generator names="extreme_wq_curve" class="org.dive4elements.river.exports.extreme.ExtremeWQCurveGenerator"/>
     <output-generator names="extreme_curve_export" class="org.dive4elements.river.exports.WaterlevelExporter"/>
     <output-generator names="extreme_wq_curve_chartinfo" class="org.dive4elements.river.exports.extreme.ExtremeWQCurveInfoGenerator"/>
-    -->
+  -->
 
-    <output-generator names="durationcurve_export" class="org.dive4elements.river.exports.DurationCurveExporter"/>
-    <output-generator names="computed_dischargecurve_export" class="org.dive4elements.river.exports.ComputedDischargeCurveExporter"/>
-    <output-generator names="discharge_longitudinal_section_export" class="org.dive4elements.river.exports.DischargeLongitudinalSectionExporter"/>
-    <output-generator names="w_differences_export" class="org.dive4elements.river.exports.WDifferencesExporter"/>
-    <output-generator names="floodmap" class="org.dive4elements.river.exports.MapGenerator"/>
-    <output-generator names="map" class="org.dive4elements.river.exports.MapGenerator"/>
-    <output-generator names="reference_curve" class="org.dive4elements.river.exports.ReferenceCurveGenerator"/>
-    <output-generator names="reference_curve_normalized" class="org.dive4elements.river.exports.NormalizedReferenceCurveGenerator"/>
-    <output-generator names="reference_curve_normalized_chartinfo" class="org.dive4elements.river.exports.NormalizedReferenceCurveInfoGenerator"/>
-    <output-generator names="reference_curve_chartinfo" class="org.dive4elements.river.exports.ReferenceCurveInfoGenerator"/>
-    <output-generator names="reference_curve_export" class="org.dive4elements.river.exports.ReferenceCurveExporter"/>
-    <output-generator names="historical_discharge_export" class="org.dive4elements.river.exports.HistoricalDischargeCurveExporter"/>
-    <output-generator names="flow_velocity_export" class="org.dive4elements.river.exports.FlowVelocityExporter"/>
-    <output-generator names="bedheight_middle_export" class="org.dive4elements.river.exports.MiddleBedHeightExporter"/>
-    <output-generator names="bed_quality_export" class="org.dive4elements.river.exports.minfo.BedQualityExporter"/>
-    <output-generator names="bedheight_difference_export" class="org.dive4elements.river.exports.minfo.BedDifferenceExporter"/>
-    <output-generator names="sq_relation_export" class="org.dive4elements.river.exports.sq.SQRelationExporter"/>
-    <output-generator names="fix_parameters_export" class="org.dive4elements.river.exports.fixings.ParametersExporter"/>
-    <output-generator names="fix_deltawt_export" class="org.dive4elements.river.exports.fixings.DeltaWtExporter"/>
-    <output-generator names="fix_deltawt_curve" class="org.dive4elements.river.exports.fixings.FixDeltaWtGenerator"/>
-    <output-generator names="fix_deltawt_curve_chartinfo" class="org.dive4elements.river.exports.fixings.FixDeltaWtInfoGenerator"/>
-    <output-generator names="fix_waterlevel_export" class="org.dive4elements.river.exports.WaterlevelExporter"/>
-    <output-generator names="sedimentload_ls_export" class="org.dive4elements.river.exports.minfo.SedimentLoadExporter"/>
-    <!-- Error report generators. -->
-    <output-generator names="discharge_longitudinal_section_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="waterlevel_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="computed_dischargecurve_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="durationcurve_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="wsplgen_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="historical_discharge_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="reference_curve_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="fix_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="extreme_curve_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="sedimentload_ls_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <output-generator names="bed_quality_report" class="org.dive4elements.river.exports.ReportGenerator"/>
-    <!-- AT exporter. -->
-    <output-generator names="computed_dischargecurve_at_export" class="org.dive4elements.river.exports.ATExporter"/>
-    <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"/>
-</output-generators>
+  <output-generator names="durationcurve_export" class="org.dive4elements.river.exports.DurationCurveExporter" />
+  <output-generator names="computed_dischargecurve_export" class="org.dive4elements.river.exports.ComputedDischargeCurveExporter" />
+  <output-generator names="discharge_longitudinal_section_export" class="org.dive4elements.river.exports.DischargeLongitudinalSectionExporter" />
+  <output-generator names="w_differences_export" class="org.dive4elements.river.exports.WDifferencesExporter" />
+  <output-generator names="floodmap" class="org.dive4elements.river.exports.MapGenerator" />
+  <output-generator names="map" class="org.dive4elements.river.exports.MapGenerator" />
+  <output-generator names="reference_curve" class="org.dive4elements.river.exports.ReferenceCurveGenerator" />
+  <output-generator names="reference_curve_normalized" class="org.dive4elements.river.exports.NormalizedReferenceCurveGenerator" />
+  <output-generator names="reference_curve_normalized_chartinfo" class="org.dive4elements.river.exports.NormalizedReferenceCurveInfoGenerator" />
+  <output-generator names="reference_curve_chartinfo" class="org.dive4elements.river.exports.ReferenceCurveInfoGenerator" />
+  <output-generator names="reference_curve_export" class="org.dive4elements.river.exports.ReferenceCurveExporter" />
+  <output-generator names="historical_discharge_export" class="org.dive4elements.river.exports.HistoricalDischargeCurveExporter" />
+  <output-generator names="flow_velocity_export" class="org.dive4elements.river.exports.FlowVelocityExporter" />
+  <output-generator names="bedheight_middle_export" class="org.dive4elements.river.exports.MiddleBedHeightExporter" />
+  <output-generator names="bed_quality_export" class="org.dive4elements.river.exports.minfo.BedQualityExporter" />
+  <output-generator names="bedheight_difference_export" class="org.dive4elements.river.exports.minfo.BedDifferenceExporter" />
+  <output-generator names="sq_relation_export" class="org.dive4elements.river.exports.sq.SQRelationExporter" />
+  <output-generator names="fix_parameters_export" class="org.dive4elements.river.exports.fixings.ParametersExporter" />
+  <output-generator names="fix_deltawt_export" class="org.dive4elements.river.exports.fixings.DeltaWtExporter" />
+  <output-generator names="fix_deltawt_curve" class="org.dive4elements.river.exports.fixings.FixDeltaWtGenerator" />
+  <output-generator names="fix_deltawt_curve_chartinfo" class="org.dive4elements.river.exports.fixings.FixDeltaWtInfoGenerator" />
+  <output-generator names="fix_waterlevel_export" class="org.dive4elements.river.exports.WaterlevelExporter" />
+  <output-generator names="sedimentload_ls_export" class="org.dive4elements.river.exports.minfo.SedimentLoadExporter" />
+  <!-- Error report generators. -->
+  <output-generator names="discharge_longitudinal_section_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="waterlevel_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="computed_dischargecurve_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="durationcurve_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="wsplgen_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="historical_discharge_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="reference_curve_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="fix_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="extreme_curve_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="sedimentload_ls_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="bed_quality_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <!-- AT exporter. -->
+  <output-generator names="computed_dischargecurve_at_export" class="org.dive4elements.river.exports.ATExporter" />
+  <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_export" class="org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthExporter" />
+  <output-generator names="sinfo_flowdepth_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="sinfo_flowdepthminmax_export" class="org.dive4elements.river.artifacts.sinfo.flowdepthminmax.FlowDepthMinMaxExporter" />
+  <output-generator names="sinfo_flowdepthminmax_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="sinfo_flowdepthdevelopment_export" class="org.dive4elements.river.artifacts.sinfo.flowdepthdev.FlowDepthDevelopmentExporter" />
+  <output-generator names="sinfo_flowdepthdevelopment_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="sinfo_tkh_export" class="org.dive4elements.river.artifacts.sinfo.tkhstate.TkhExporter" />
+  <output-generator names="sinfo_tkh_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="sinfo_floodduration_export" class="org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationExporter" />
+  <output-generator names="sinfo_floodduration_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="sinfo_floodduration_curve" class="org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationCurveGenerator" />
+  <output-generator names="sinfo_floodduration_curve_chartinfo" class="org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationCurveInfoGenerator" />
+  <output-generator names="sinfo_collision_export" class="org.dive4elements.river.artifacts.sinfo.collision.CollisionExporter" />
+  <output-generator names="sinfo_collision_report" class="org.dive4elements.river.exports.ReportGenerator" />
+
+  <!-- UINFO -->
+  <output-generator names="uinfo_inundation_duration_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="uinfo_salix_line_export" class="org.dive4elements.river.artifacts.uinfo.salix.SalixLineExporter" />
+  <output-generator names="uinfo_salix_line_report" class="org.dive4elements.river.exports.ReportGenerator" />
+  <output-generator names="uinfo_vegetation_zones_export" class="org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZonesExporter" />
+  <output-generator names="uinfo_vegetation_zones_report" class="org.dive4elements.river.exports.ReportGenerator" />
+</output-generators>
\ No newline at end of file
--- a/artifacts/doc/conf/generators/longitudinal-diagram-defaults.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/generators/longitudinal-diagram-defaults.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -14,8 +14,14 @@
     <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="flowdepthAxis" include-zero="true"  />
+    <axis name="tkhAxis" include-zero="true" />
+    <axis name="flowdepthDevelopmentAxis"/>
+    <axis name="flowdepthDevelopmentPerYearAxis"/>
+    <axis name="countAxis" include-zero="true"/>
+    <axis name="durationAxis" include-zero="true"/>
+
+    <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 +48,27 @@
     <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.common.FlowDepthProcessor" axis="flowdepthAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.TkhProcessor" axis="tkhAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.TauProcessor" axis="Tau"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.D50Processor" axis="Diameter"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.VelocityProcessor" axis="Velocity"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.FlowDepthDevelopmentProcessor" axis="flowdepthDevelopmentAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.FlowDepthDevelopmentPerYearProcessor" axis="flowdepthDevelopmentPerYearAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.collision.CollisionCalcProcessor" axis="countAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationProcessor" axis="durationAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.flood_duration.FloodHeightProcessor" axis="W"/>
+    
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.PredefinedChannelWidthProcessor" axis="Width"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.PredefinedChannelDepthProcessor" axis="flowdepthAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.PredefinedTkhProcessor" axis="tkhAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.PredefinedDepthEvolProcessor" axis="flowdepthDevelopmentAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.PredefinedDepthEvolPerYearProcessor" axis="flowdepthDevelopmentPerYearAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.PredefinedFlowDepthProcessor" axis="flowdepthAxis"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.common.InfrastructureHeightProcessor" axis="W"/>
+    <processor class="org.dive4elements.river.artifacts.sinfo.collision.CollisionCountProcessor" axis="countAxis"/>
+
+    <chartextender class="org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthChartExtender" />
+</longitudinal-defaults>
\ No newline at end of file
--- a/artifacts/doc/conf/generators/longitudinal-diagrams.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/generators/longitudinal-diagrams.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -87,5 +87,109 @@
             <arg expr="artifact.river"/>
         </subtitle>
     </output-generator>
-</longitudinal-diagrams>
 
+    <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="flowdepthAxis"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>
+
+    <output-generator
+        names="sinfo_flow_depth_minmax,sinfo_flow_depth_minmax_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.flow_depth_minmax.section.title" default="min/max h-Längsschnitt (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="flowdepthAxis"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>
+
+    <output-generator
+        names="sinfo_tkk,sinfo_tkk_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.tkh.section.title" default="Transportkörperhöhen (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="tkhAxis"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>
+    
+    <output-generator
+        names="sinfo_flow_depth_development,sinfo_flow_depth_development_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.flow_depth_development.section.title" default="Fließtiefenentwicklung (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="flowdepthDevelopmentAxis"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>    
+    
+    <output-generator
+        names="sinfo_flow_depth_development_peryear,sinfo_flow_depth_development_peryear_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.flow_depth_development_perYear.section.title" default="Fließtiefenentwicklung pro Jahr (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="flowdepthDevelopmentPerYearAxis"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>    
+
+    <output-generator
+        names="sinfo_collision,sinfo_collision_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.collision.section.title" default="Grundberührungen (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="countAxis"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>
+
+    <output-generator
+        names="sinfo_flood_duration,sinfo_flood_duration_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.flood_duration.section.title" default="Ãœberflutungsdauer Infrastruktur BWaStr (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="durationAxis"/>
+        <subtitle key="chart.w_differences.subtitle" default="-">
+            <arg expr="artifact.river"/>
+        </subtitle>
+    </output-generator>
+
+    <output-generator
+        names="sinfo_flood_height,sinfo_flood_height_chartinfo"
+        class="org.dive4elements.river.exports.LongitudinalSectionGenerator2"
+        converter="org.dive4elements.river.exports.DiagramAttributes">
+        <title key="sinfo.chart.flood_duration.height.section.title" default="Ãœberflutung Infrastruktur BWaStr (DEFAULT)"/>
+        &longitudinal-defaults;
+        <processor class="org.dive4elements.river.exports.process.ManualPointsProcessor"
+            axis="W"/>
+        <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/templates/sinfo.collision.detail.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,259 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-28T15:32:43 -->
+<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"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto">
+		<paragraph lineSpacing="Single"/>
+	</style>
+	<field name="meta:totalpages" class="java.lang.Integer"/>
+	<field name="meta:startpageoffset" class="java.lang.Integer"/>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" class="java.lang.String"/>
+	<field name="meta:riverside_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_q_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_height_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_type_header" class="java.lang.String"/>
+	<field name="meta:w_1_header" class="java.lang.String"/>
+	<field name="meta:q_1_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_1_header" class="java.lang.String"/>
+	<field name="meta:duration_1_header" class="java.lang.String"/>
+	<field name="meta:w_2_header" class="java.lang.String"/>
+	<field name="meta:q_2_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_2_header" class="java.lang.String"/>
+	<field name="meta:duration_2_header" class="java.lang.String"/>
+	<field name="meta:w_3_header" class="java.lang.String"/>
+	<field name="meta:q_3_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_3_header" class="java.lang.String"/>
+	<field name="meta:duration_3_header" class="java.lang.String"/>
+	<field name="meta:gaugew_header" class="java.lang.String"/>
+	<field name="meta:dischargezone_header" 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"/>
+	<field name="data:12" class="java.lang.String"/>
+	<field name="data:13" class="java.lang.String"/>
+	<field name="data:14" class="java.lang.String"/>
+	<field name="data:15" class="java.lang.String"/>
+	<field name="data:16" class="java.lang.String"/>
+	<field name="data:17" class="java.lang.String"/>
+	<field name="data:18" class="java.lang.String"/>
+	<field name="data:19" class="java.lang.String"/>
+	<field name="data:20" class="java.lang.String"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band splitType="Stretch"/>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="515" height="1"/>
+			</line>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="60" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="60" y="0" width="90" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="150" y="0" width="60" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gaugew_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="210" y="0" width="140" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gauge_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="350" y="0" width="60" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:discharge_header}+" [m³/s]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="410" y="0" width="105" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:dischargezone_header}]]></textFieldExpression>
+			</textField>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="60" y="0" width="90" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="150" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="210" y="0" width="140" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="350" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="410" y="0" width="105" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="402" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER} +(($F{meta:startpageoffset} != null) ? $F{meta:startpageoffset} : 0 )]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="458" y="0" width="57" height="15"/>
+				<box topPadding="2" leftPadding="0" bottomPadding="0" rightPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + ( $V{PAGE_NUMBER}+( ($F{meta:totalpages} != null) ? $F{meta:totalpages} -$V{PAGE_NUMBER} : 0 ) )]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.collision.overview.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-22T12:00:53 -->
+<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"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto">
+		<paragraph lineSpacing="Single"/>
+	</style>
+	<field name="meta:totalpages" class="java.lang.Integer"/>
+	<field name="meta:startpageoffset" class="java.lang.Integer"/>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" class="java.lang.String"/>
+	<field name="meta:riverside_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_q_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_height_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_type_header" class="java.lang.String"/>
+	<field name="meta:w_1_header" class="java.lang.String"/>
+	<field name="meta:q_1_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_1_header" class="java.lang.String"/>
+	<field name="meta:duration_1_header" class="java.lang.String"/>
+	<field name="meta:w_2_header" class="java.lang.String"/>
+	<field name="meta:q_2_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_2_header" class="java.lang.String"/>
+	<field name="meta:duration_2_header" class="java.lang.String"/>
+	<field name="meta:w_3_header" class="java.lang.String"/>
+	<field name="meta:q_3_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_3_header" class="java.lang.String"/>
+	<field name="meta:duration_3_header" class="java.lang.String"/>
+	<field name="meta:collision_years_header" class="java.lang.String"/>
+	<field name="meta:collision_count_header" 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"/>
+	<field name="data:12" class="java.lang.String"/>
+	<field name="data:13" class="java.lang.String"/>
+	<field name="data:14" class="java.lang.String"/>
+	<field name="data:15" class="java.lang.String"/>
+	<field name="data:16" class="java.lang.String"/>
+	<field name="data:17" class="java.lang.String"/>
+	<field name="data:18" class="java.lang.String"/>
+	<field name="data:19" class="java.lang.String"/>
+	<field name="data:20" class="java.lang.String"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="169" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="39" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="69" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="69" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="89" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="89" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="109" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="109" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="129" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="129" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="149" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="149" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="515" height="1"/>
+			</line>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="90" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="90" y="0" width="90" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:collision_years_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="180" y="0" width="100" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:collision_count_header}]]></textFieldExpression>
+			</textField>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="90" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="90" y="0" width="90" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="180" y="0" width="100" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="402" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER} +(($F{meta:startpageoffset} != null) ? $F{meta:startpageoffset} : 0 )]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="458" y="0" width="57" height="15"/>
+				<box topPadding="2" leftPadding="0" bottomPadding="0" rightPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + ( $V{PAGE_NUMBER}+( ($F{meta:totalpages} != null) ? $F{meta:totalpages} -$V{PAGE_NUMBER} : 0 ) )]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.floodduration.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,389 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-12T09:58:57 -->
+<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="842" pageHeight="595" orientation="Landscape" columnWidth="762" 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"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto">
+		<paragraph lineSpacing="Single"/>
+	</style>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" class="java.lang.String"/>
+	<field name="meta:riverside_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_q_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_height_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_type_header" class="java.lang.String"/>
+	<field name="meta:w_1_header" class="java.lang.String"/>
+	<field name="meta:q_1_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_1_header" class="java.lang.String"/>
+	<field name="meta:duration_1_header" class="java.lang.String"/>
+	<field name="meta:w_2_header" class="java.lang.String"/>
+	<field name="meta:q_2_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_2_header" class="java.lang.String"/>
+	<field name="meta:duration_2_header" class="java.lang.String"/>
+	<field name="meta:w_3_header" class="java.lang.String"/>
+	<field name="meta:q_3_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_3_header" class="java.lang.String"/>
+	<field name="meta:duration_3_header" 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"/>
+	<field name="data:12" class="java.lang.String"/>
+	<field name="data:13" class="java.lang.String"/>
+	<field name="data:14" class="java.lang.String"/>
+	<field name="data:15" class="java.lang.String"/>
+	<field name="data:16" class="java.lang.String"/>
+	<field name="data:17" class="java.lang.String"/>
+	<field name="data:18" class="java.lang.String"/>
+	<field name="data:19" class="java.lang.String"/>
+	<field name="data:20" class="java.lang.String"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="169" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="39" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="69" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="69" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="89" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="89" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="109" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="109" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="129" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="129" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="149" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="149" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="762" height="1"/>
+			</line>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="60" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="60" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:riverside_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="120" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:inundationduration_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="180" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:inundationduration_q_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="240" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:infrastructure_height_header} +" ["+$F{meta:river_unit}+"]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="300" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:infrastructure_type_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="wOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="360" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:w_1_header} +" ["+$F{meta:river_unit}+"]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="durOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="420" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:duration_1_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="qOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="480" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:q_1_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="bezOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="540" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bezeichnung_1_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="600" y="0" width="70" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gauge_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="670" y="0" width="92" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:location_header}]]></textFieldExpression>
+			</textField>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="60" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="120" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="180" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="240" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="300" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="wOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="360" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:6}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="durOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="420" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:7}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="qOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="480" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:8}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="bezOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="540" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:9}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="600" y="0" width="70" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:10}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="670" y="0" width="92" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:11}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="634" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="690" y="0" width="57" height="15"/>
+				<box topPadding="2" leftPadding="0" bottomPadding="0" rightPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.floodduration2.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,525 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-12T10:06:52 -->
+<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="842" pageHeight="595" orientation="Landscape" columnWidth="762" 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"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto" fontSize="8">
+		<paragraph lineSpacing="Single"/>
+	</style>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" class="java.lang.String"/>
+	<field name="meta:riverside_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_header" class="java.lang.String"/>
+	<field name="meta:inundationduration_q_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_height_header" class="java.lang.String"/>
+	<field name="meta:infrastructure_type_header" class="java.lang.String"/>
+	<field name="meta:w_1_header" class="java.lang.String"/>
+	<field name="meta:q_1_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_1_header" class="java.lang.String"/>
+	<field name="meta:duration_1_header" class="java.lang.String"/>
+	<field name="meta:w_2_header" class="java.lang.String"/>
+	<field name="meta:q_2_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_2_header" class="java.lang.String"/>
+	<field name="meta:duration_2_header" class="java.lang.String"/>
+	<field name="meta:w_3_header" class="java.lang.String"/>
+	<field name="meta:q_3_header" class="java.lang.String"/>
+	<field name="meta:bezeichnung_3_header" class="java.lang.String"/>
+	<field name="meta:duration_3_header" 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"/>
+	<field name="data:12" class="java.lang.String"/>
+	<field name="data:13" class="java.lang.String"/>
+	<field name="data:14" class="java.lang.String"/>
+	<field name="data:15" class="java.lang.String"/>
+	<field name="data:16" class="java.lang.String"/>
+	<field name="data:17" class="java.lang.String"/>
+	<field name="data:18" class="java.lang.String"/>
+	<field name="data:19" class="java.lang.String"/>
+	<field name="data:20" class="java.lang.String"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="169" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="39" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="69" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="69" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="89" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="89" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="109" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="109" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="129" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="129" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="149" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="149" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="-36" y="24" width="805" height="1"/>
+			</line>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="-36" y="0" width="40" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="4" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:riverside_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="44" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:inundationduration_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="84" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:inundationduration_q_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="124" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:infrastructure_height_header} +" ["+$F{meta:river_unit}+"]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="164" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:infrastructure_type_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="204" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:w_1_header} +" ["+$F{meta:river_unit}+"]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="244" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:duration_1_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="284" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:q_1_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="324" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bezeichnung_1_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="364" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:w_2_header} +" ["+$F{meta:river_unit}+"]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="404" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:duration_2_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="444" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:q_2_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="484" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bezeichnung_2_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="wOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="524" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:w_3_header} +" ["+$F{meta:river_unit}+"]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="durOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="564" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:duration_3_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="qOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="604" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:q_3_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="bezOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="644" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bezeichnung_3_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="684" y="0" width="50" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gauge_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="734" y="0" width="40" height="24"/>
+				<box padding="2"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:location_header}]]></textFieldExpression>
+			</textField>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="-36" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="4" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="44" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="84" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="124" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="164" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="204" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:6}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="244" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:7}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="284" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:8}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="324" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:9}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="364" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:10}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="404" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:11}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="444" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:12}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="484" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:13}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="wOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="524" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:14}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="durOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="564" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:15}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="qOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="604" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:16}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="bezOpt" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="644" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:17}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="684" y="0" width="50" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:18}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="734" y="0" width="40" height="15"/>
+				<box padding="2">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:19}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="634" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="690" y="0" width="57" height="15"/>
+				<box topPadding="2" leftPadding="0" bottomPadding="0" rightPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.flowdepth.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-14T13:41:07 -->
+<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="842" pageHeight="595" 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"/>
+	<style name="htmlStyle" markup="html" fontName="Roboto">
+		<box topPadding="2" leftPadding="5" rightPadding="5"/>
+	</style>
+	<field name="meta:totalpagesoffset" class="java.lang.Integer"/>
+	<field name="meta:startpageoffset" class="java.lang.Integer"/>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" 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"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="170" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="1" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="40" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="70" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="70" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="90" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="90" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="110" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="110" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="130" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="130" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="150" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="150" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<line>
+				<reportElement positionType="FixRelativeToBottom" x="5" y="24" width="762" height="1"/>
+			</line>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="0" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" isPrintRepeatedValues="false" x="0" y="0" width="55" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="1" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="55" y="0" width="55" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepth_header} + "<br/>[m]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="flowdepthtkh" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="110" y="0" width="54" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepth_tkh_header} + " [m]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="tkh" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="164" y="0" width="36" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:tkh_header} + "<br/>[cm]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="4" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="200" y="0" width="60" height="24"/>
+				<box padding="5">
+					<pen lineStyle="Solid"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterlevel_header} + "<br/>["  + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="5" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="260" y="0" width="40" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:discharge_header} + "<br/>[m³/s]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="6" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="300" y="0" width="80" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterlevel_name_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="7" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="380" y="0" width="110" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gauge_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="8" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="490" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bedheight_header} +  "<br/>[" + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="9" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="550" y="0" width="95" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:sounding_name_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="10" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="645" y="0" width="122" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:location_header}]]></textFieldExpression>
+			</textField>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="0" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="55" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Top">
+					<font isBold="false"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="1" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="55" y="0" width="55" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="flowdepthtkh" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="110" y="0" width="54" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="tkh" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="164" y="0" width="36" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="4" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="200" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="5" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="260" y="0" width="40" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="6" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="300" y="0" width="80" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:6}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="7" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="380" y="0" width="110" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:7}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="8" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="490" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:8}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="9" style="htmlStyle" positionType="Float" x="550" y="0" width="95" height="15" isRemoveLineWhenBlank="true" isPrintWhenDetailOverflows="true">
+					<property name="net.sf.jasperreports.export.pdf.force.linebreak.policy" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="false"/>
+				</reportElement>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:9}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="10" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="645" y="0" width="122" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:10}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="705" y="0" width="57" height="15"/>
+				<box leftPadding="0"/>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA["/ " +( $V{PAGE_NUMBER} +(($F{meta:totalpagesoffset} != null) ? $F{meta:totalpagesoffset} : 0) )]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="650" y="0" width="55" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER} +(($F{meta:startpageoffset} != null) ? $F{meta:startpageoffset} : 0 )]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.flowdepthdevelopment.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-20T11:02:46 -->
+<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="842" pageHeight="595" 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"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto">
+		<box topPadding="2" leftPadding="5" rightPadding="5"/>
+	</style>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" 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="190" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="1" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="40" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="70" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="70" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="90" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="90" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="110" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="110" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="130" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="130" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="150" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="150" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="170" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthdevelopment_header_label}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="170" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthdevelopment}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="75" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="60" height="75"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="60" y="0" width="80" height="75"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthdevelopment_header} + "<br/>[cm]"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="" style="htmlStyle" x="140" y="0" width="80" height="75"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthdevelopmentperyear_header} + "<br/>[cm/a]"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="" style="htmlStyle" x="305" y="0" width="85" height="40"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bedheightdifference_header} + "<br/>[m³/s]"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="" style="htmlStyle" x="305" y="40" width="85" height="35"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bedheightdifference_header2}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="390" y="0" width="85" height="40"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthcurrent_header} + "<br/>[" + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="390" y="40" width="85" height="35"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthcurrent_header2}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="475" y="0" width="85" height="40"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthhistorical_header}+"<br/>[" + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="475" y="40" width="85" height="35"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthhistorical_header2}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="560" y="0" width="202" height="75"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:location_header}]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement style="htmlStyle" x="0" y="74" width="762" height="1"/>
+			</line>
+			<textField>
+				<reportElement key="" style="htmlStyle" x="220" y="40" width="85" height="35"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterleveldifference_header2}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="" style="htmlStyle" x="220" y="1" width="85" height="40"/>
+				<box padding="0"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom">
+					<font pdfEncoding=""/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:waterleveldifference_header}+"<br/>["+$F{meta:river_unit}+"]"]]></textFieldExpression>
+			</textField>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="0" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="60" y="0" width="80" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" stretchType="RelativeToBandHeight" x="140" y="0" width="80" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="TEST" style="htmlStyle" stretchType="RelativeToBandHeight" x="220" y="0" width="85" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" stretchType="RelativeToBandHeight" x="305" y="0" width="85" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="475" y="0" width="85" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:6}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="560" y="0" width="202" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textFieldExpression><![CDATA[$F{data:7}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="390" y="0" width="85" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="705" y="0" width="57" height="15"/>
+				<box leftPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="650" y="0" width="55" height="15"/>
+				<box rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.flowdepthminmax.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-06T13:12:53 -->
+<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="842" pageHeight="595" 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"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto">
+		<box topPadding="2" leftPadding="5" rightPadding="5"/>
+	</style>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" 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"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="170" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="1" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="40" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="70" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="70" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="90" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="90" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="110" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="110" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="130" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="130" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="150" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="150" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="-5" y="0" width="55" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="50" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthmin_header} + "<br/>[m]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="110" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:flowdepthmax_header} + "<br/>[m]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="170" y="0" width="70" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterlevel_header}+ "<br/>[" + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="240" y="0" width="50" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:discharge_header}+ "<br/>[m³/s]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="290" y="0" width="80" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterlevel_name_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="370" y="0" width="90" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gauge_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="641" y="0" width="120" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:location_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="541" y="0" width="100" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:sounding_name_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="460" y="0" width="81" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bedheight_header}+ "<br/>[" + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="762" height="1"/>
+			</line>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="370" y="0" width="90" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:6}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="460" y="0" width="81" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:7}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="290" y="0" width="80" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="-5" y="0" width="55" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="50" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" stretchType="RelativeToBandHeight" x="110" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" stretchType="RelativeToBandHeight" x="170" y="0" width="70" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" stretchType="RelativeToBandHeight" x="240" y="0" width="50" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="541" y="0" width="100" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textFieldExpression><![CDATA[$F{data:8}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" stretchType="RelativeToBandHeight" x="641" y="0" width="120" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5"/>
+				<textFieldExpression><![CDATA[$F{data:9}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="705" y="0" width="57" height="15"/>
+				<box leftPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="650" y="0" width="55" height="15"/>
+				<box rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/sinfo.tkh.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,309 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-13T15:46:02 -->
+<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="842" pageHeight="595" 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"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto"/>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" 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"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="189" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="39" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="69" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="69" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="89" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="89" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="109" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="109" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="129" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="129" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="149" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="149" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="169" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calculation_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="169" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calculation_name}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="-5" y="0" width="55" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="50" y="0" width="50" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:tkh_header} + "<br/>[cm]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="100" y="0" width="60" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:tkhkind_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="160" y="0" width="60" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterlevel_header}+  "<br/>["  + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="220" y="0" width="50" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:discharge_header}+ "<br/>[m³/s]"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="370" y="0" width="100" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:waterlevel_name_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="470" y="0" width="120" height="24"/>
+				<box topPadding="0" leftPadding="5" bottomPadding="5" rightPadding="5"/>
+				<textElement textAlignment="Left" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:gauge_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="590" y="0" width="160" height="24"/>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:location_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="270" y="0" width="100" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:bedheight_header}+  "<br/>["  + $F{meta:river_unit} + "]"]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="740" height="1"/>
+			</line>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="370" y="0" width="100" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:6}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="470" y="0" width="120" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textFieldExpression><![CDATA[$F{data:7}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="270" y="0" width="100" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:5}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="-5" y="0" width="55" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="50" y="0" width="50" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="100" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Left"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="160" y="0" width="60" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:3}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="220" y="0" width="50" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:4}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="590" y="0" width="160" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textFieldExpression><![CDATA[$F{data:8}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="615" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="671" y="0" width="57" height="15"/>
+				<box topPadding="2"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/uinfo.salixline.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-07-10T15:31:50 -->
+<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="flysreport" language="groovy" pageWidth="595" pageHeight="842" columnWidth="545" leftMargin="30" rightMargin="20" topMargin="20" bottomMargin="20">
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="0"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto"/>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" class="java.lang.String"/>
+	<field name="meta:salix_line" class="java.lang.String"/>
+	<field name="meta:salix_line_hist" class="java.lang.String"/>
+	<field name="meta:salix_line_scen" class="java.lang.String"/>
+	<field name="meta:salix_delta_mw" 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"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="169" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="39" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="69" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="69" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="89" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="89" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="109" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="109" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="129" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="129" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="149" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="149" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="80" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:station_header}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="80" y="0" width="90" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:salix_line}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="170" y="0" width="140" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:salix_delta_mw}]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="550" height="1"/>
+			</line>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="80" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right" verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="80" y="0" width="90" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="170" y="0" width="140" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="437" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="493" y="0" width="57" height="15"/>
+				<box topPadding="2"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/jasper/templates/uinfo.vegetationzones.jrxml	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 4.5.0  -->
+<!-- 2018-06-06T13:16:52 -->
+<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="flysreport" language="groovy" pageWidth="595" pageHeight="842" columnWidth="545" leftMargin="30" rightMargin="20" topMargin="20" bottomMargin="20">
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="0"/>
+	<style name="htmlStyle" isDefault="true" mode="Transparent" markup="html" fontName="Roboto">
+		<paragraph lineSpacing="Single"/>
+	</style>
+	<field name="meta:header" class="java.lang.String"/>
+	<field name="meta:calcMode" class="java.lang.String"/>
+	<field name="meta:version_label" class="java.lang.String"/>
+	<field name="meta:version" class="java.lang.String"/>
+	<field name="meta:user_label" class="java.lang.String"/>
+	<field name="meta:user" class="java.lang.String"/>
+	<field name="meta:date_label" class="java.lang.String"/>
+	<field name="meta:date" class="java.lang.String"/>
+	<field name="meta:river_label" class="java.lang.String"/>
+	<field name="meta:river" class="java.lang.String"/>
+	<field name="meta:range_label" class="java.lang.String"/>
+	<field name="meta:range" class="java.lang.String"/>
+	<field name="meta:calculation_label" class="java.lang.String"/>
+	<field name="meta:calculation_name" class="java.lang.String"/>
+	<field name="meta:station_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopmentperyear_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header2" class="java.lang.String"/>
+	<field name="meta:waterleveldifference_header_label" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header2" class="java.lang.String"/>
+	<field name="meta:bedheightdifference_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header2" class="java.lang.String"/>
+	<field name="meta:flowdepthcurrent_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepthhistorical_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment" class="java.lang.String"/>
+	<field name="meta:flowdepthmin_header" class="java.lang.String"/>
+	<field name="meta:flowdepthmax_header" class="java.lang.String"/>
+	<field name="meta:flowdepthdevelopment_header_label" class="java.lang.String"/>
+	<field name="meta:flowdepth_tkh_header" class="java.lang.String"/>
+	<field name="meta:tkh_header" class="java.lang.String"/>
+	<field name="meta:tkhkind_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_header" class="java.lang.String"/>
+	<field name="meta:discharge_header" class="java.lang.String"/>
+	<field name="meta:waterlevel_name_header" class="java.lang.String"/>
+	<field name="meta:gauge_header" class="java.lang.String"/>
+	<field name="meta:bedheight_header" class="java.lang.String"/>
+	<field name="meta:sounding_name_header" class="java.lang.String"/>
+	<field name="meta:location_header" class="java.lang.String"/>
+	<field name="meta:river_unit" class="java.lang.String"/>
+	<field name="meta:veg_name" class="java.lang.String"/>
+	<field name="meta:veg_dauervon" class="java.lang.String"/>
+	<field name="meta:veg_dauerbis" 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"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<title>
+		<band height="169" splitType="Stretch">
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="0" width="515" height="30"/>
+				<textElement>
+					<font size="18"/>
+				</textElement>
+				<textFieldExpression><![CDATA[$F{meta:header} + " " + $F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="39" width="165" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:calcMode}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="69" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="69" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:version}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="89" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="89" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:user}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="109" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="109" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:date}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="129" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="129" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:river}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="0" y="149" width="123" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range_label} + ":"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="htmlStyle" x="123" y="149" width="392" height="20"/>
+				<textFieldExpression><![CDATA[$F{meta:range}]]></textFieldExpression>
+			</textField>
+		</band>
+	</title>
+	<columnHeader>
+		<band height="25" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="267" height="24">
+					<property name="net.sf.jasperreports.text.hyphenation" value="true"/>
+					<property name="net.sf.jasperreports.text.save.line.breaks" value="true"/>
+					<property name="net.sf.jasperreports.export.xls.wrap.text" value="true"/>
+				</reportElement>
+				<box padding="5"/>
+				<textElement verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:veg_name}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="267" y="0" width="140" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:veg_dauervon}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="407" y="0" width="140" height="24"/>
+				<box padding="5"/>
+				<textElement textAlignment="Right" verticalAlignment="Bottom"/>
+				<textFieldExpression><![CDATA[$F{meta:veg_dauerbis}]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement style="htmlStyle" positionType="FixRelativeToBottom" x="0" y="24" width="550" height="1"/>
+			</line>
+		</band>
+	</columnHeader>
+	<detail>
+		<band height="15" splitType="Prevent">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="0" y="0" width="267" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement verticalAlignment="Top"/>
+				<textFieldExpression><![CDATA[$F{data:0}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="267" y="0" width="140" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:1}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement key="" style="htmlStyle" positionType="Float" stretchType="RelativeToBandHeight" x="407" y="0" width="140" height="15"/>
+				<box topPadding="2" leftPadding="5" bottomPadding="0" rightPadding="5">
+					<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
+				</box>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$F{data:2}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<pageFooter>
+		<band height="15" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement style="htmlStyle" x="437" y="0" width="55" height="15"/>
+				<box topPadding="2" rightPadding="3"/>
+				<textElement textAlignment="Right"/>
+				<textFieldExpression><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement style="htmlStyle" x="493" y="0" width="57" height="15"/>
+				<box topPadding="2" leftPadding="0" bottomPadding="0" rightPadding="0"/>
+				<textFieldExpression><![CDATA["/ " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<summary>
+		<band height="30" splitType="Stretch"/>
+	</summary>
+</jasperReport>
--- a/artifacts/doc/conf/log4j.properties	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/log4j.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -4,7 +4,7 @@
 log4j.category.org.hibernate=WARN
 log4j.category.net.sf.ehcache=WARN
 log4j.category.org.eclipse=WARN
-log4j.category.org.restlet=INFO
+log4j.category.org.restlet=WARN
 
 
 ########## APPENDER SETTINGS
@@ -12,10 +12,7 @@
 log4j.appender.FLYS.layout.ConversionPattern=%d{HH:mm:ss} [%t] %-5p %c{1} - %m%n
 
 
-log4j.appender.FLYS=org.apache.log4j.RollingFileAppender
-log4j.appender.FLYS.File=/var/log/d4e-river/d4e-server.log
-log4j.appender.FLYS.MaxFileSize=5000KB
-log4j.appender.FLYS.MaxBackupIndex=1
+log4j.appender.FLYS=org.apache.log4j.ConsoleAppender
 
 log4j.logger.org.dive4elements.artifactdatabase.rest.Standalone=INFO, START
 log4j.appender.START=org.apache.log4j.ConsoleAppender
--- a/artifacts/doc/conf/meta-data.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/meta-data.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -2,9 +2,9 @@
 <dc:template xmlns:dc="http://www.intevation.org/2011/Datacage">
   <datacage>
 
-    <dc:call-macro name="load-user"/>
+    <dc:call-macro name="load-user" />
 
-    <dc:call-macro name="load-system"/>
+    <dc:call-macro name="load-system" />
 
     <dc:macro name="load-system">
       <dc:context connection="system">
@@ -14,14 +14,14 @@
           WHERE lower(name) LIKE lower(${river})
         </dc:statement>
         <dc:for-each>
-          <dc:call-macro name="generate-system-content"/>
+          <dc:call-macro name="generate-system-content" />
         </dc:for-each>
       </dc:context>
     </dc:macro>
 
     <dc:macro name="load-user">
       <old_calculations>
-        <dc:call-macro name="generate-user-content"/>
+        <dc:call-macro name="generate-user-content" />
       </old_calculations>
     </dc:macro>
 
@@ -39,83 +39,108 @@
                 <dc:choose>
                   <dc:comment> Longitudinal sections </dc:comment>
                   <dc:when test="$out = 'w_differences'">
-                    <dc:call-macro name="annotations"/>
+                    <dc:call-macro name="annotations" />
                   </dc:when>
                   <dc:when test="$out = 'discharge_longitudinal_section'">
-                    <dc:call-macro name="annotations"/>
-                    <dc:call-macro name="officiallines_user"/>
+                    <dc:call-macro name="annotations" />
+                    <dc:call-macro name="officiallines_user" />
                   </dc:when>
                   <dc:when test="$out = 'longitudinal_section'">
-                    <dc:call-macro name="annotations"/>
-                    <dc:call-macro name="officiallines_user"/>
+                    <dc:call-macro name="annotations" />
+                    <dc:call-macro name="officiallines_user" />
                   </dc:when>
                   <dc:when test="$out = 'fix_longitudinal_section_curve'">
-                    <dc:call-macro name="annotations"/>
+                    <dc:call-macro name="annotations" />
                   </dc:when>
                   <dc:when test="$out = 'bedheight_middle'">
-                    <dc:call-macro name="annotations"/>
+                    <dc:call-macro name="annotations" />
                   </dc:when>
                   <dc:when test="$out = 'bed_difference_year'">
-                    <dc:call-macro name="annotations"/>
-                    <dc:call-macro name="basedata_6_delta_w"/>
-                    <dc:call-macro name="sounding-width-recommendations"/>
+                    <dc:call-macro name="annotations" />
+                    <dc:call-macro name="basedata_6_delta_w" />
+                    <dc:call-macro name="sounding-width-recommendations" />
                   </dc:when>
                   <dc:when test="$out = 'bed_difference_height_year'">
-                    <dc:call-macro name="annotations"/>
-                    <dc:call-macro name="basedata_6_delta_w"/>
+                    <dc:call-macro name="annotations" />
+                    <dc:call-macro name="basedata_6_delta_w" />
                   </dc:when>
                   <dc:when test="$out = 'sedimentload_ls'">
-                    <dc:call-macro name="annotations"/>
-                    <dc:call-macro name="sedimentload_off_epochs"/>
+                    <dc:call-macro name="annotations" />
+                    <dc:call-macro name="sedimentload_off_epochs" />
                   </dc:when>
                   <dc:when test="$out = 'bed_longitudinal_section'">
-                    <dc:call-macro name="annotations"/>
+                    <dc:call-macro name="annotations" />
                   </dc:when>
                   <dc:when test="$out = 'flow_velocity'">
-                    <dc:call-macro name="annotations"/>
+                    <dc:call-macro name="annotations" />
                   </dc:when>
                   <dc:comment> Discharge curves </dc:comment>
                   <dc:when test="$out = 'historical_discharge_wq'">
-                    <dc:call-macro name="hist_discharge_rec"/>
-                    <dc:call-macro name="mainvalues"/>
+                    <dc:call-macro name="hist_discharge_rec" />
+                    <dc:call-macro name="mainvalues" />
                   </dc:when>
                   <dc:when test="$out = 'discharge_curve'">
-                    <dc:call-macro name="mainvalues"/>
-                    <dc:call-macro name="basedata_3_officials_wq"/>
+                    <dc:call-macro name="mainvalues" />
+                    <dc:call-macro name="basedata_3_officials_wq" />
                   </dc:when>
                   <dc:when test="$out = 'computed_discharge_curve'">
-                    <dc:call-macro name="mainvalues"/>
-                    <dc:call-macro name="basedata_3_officials_wq"/>
-                    <dc:call-macro name="basedata_2_fixations_wq"/>
+                    <dc:call-macro name="mainvalues" />
+                    <dc:call-macro name="basedata_3_officials_wq" />
+                    <dc:call-macro name="basedata_2_fixations_wq" />
                   </dc:when>
                   <dc:when test="$out = 'fix_wq_curve'">
-                    <dc:call-macro name="mainvalues"/>
-                    <dc:call-macro name="qsectors"/>
+                    <dc:call-macro name="mainvalues" />
+                    <dc:call-macro name="qsectors" />
                   </dc:when>
                   <dc:when test="$out = 'fix_derivate_curve'">
-                    <dc:call-macro name="qmainvalues"/>
+                    <dc:call-macro name="qmainvalues" />
                   </dc:when>
                   <dc:when test="starts-with($out, 'sq_') and
                                  not($out = 'sq_relation_export')">
-                    <dc:call-macro name="qmainvalues"/>
+                    <dc:call-macro name="qmainvalues" />
                   </dc:when>
                   <dc:comment> Cross sections </dc:comment>
                   <dc:when test="$out = 'cross_section'">
-                    <dc:call-macro name="cross_sections"/>
-                    <dc:call-macro name="hyks"/>
-                    <dc:call-macro name="officiallines_user"/>
+                    <dc:call-macro name="cross_sections" />
+                    <dc:call-macro name="hyks" />
+                    <dc:call-macro name="officiallines_user" />
                   </dc:when>
                   <dc:comment> Duration curve </dc:comment>
                   <dc:when test="$out = 'duration_curve'">
-                    <dc:call-macro name="mainvalues"/>
+                    <dc:call-macro name="mainvalues" />
                   </dc:when>
                   <dc:comment> Reference curve </dc:comment>
                   <dc:when test="$out = 'reference_curve'">
-                    <dc:call-macro name="mainvalues"/>
+                    <dc:call-macro name="mainvalues" />
                   </dc:when>
                   <dc:comment> Maps </dc:comment>
                   <dc:when test="$out = 'floodmap'">
-                    <dc:call-macro name="flood-map-recommended"/>
+                    <dc:call-macro name="flood-map-recommended" />
+                  </dc:when>
+
+                  <dc:when test="$out = 'sinfo_flow_depth'">
+                    <dc:call-macro name="annotations" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flow_depth_minmax'">
+                    <dc:call-macro name="annotations" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flow_depth_development'">
+                    <dc:call-macro name="annotations" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flow_depth_development_peryear'">
+                    <dc:call-macro name="annotations" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_tkk'">
+                    <dc:call-macro name="annotations" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_collision'">
+                    <dc:call-macro name="annotations" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flood_duration'">
+                    <dc:call-macro name="annotations" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flood_height'">
+                    <dc:call-macro name="annotations" />
                   </dc:when>
                 </dc:choose>
               </dc:iterate>
@@ -129,118 +154,169 @@
                 <dc:choose>
                   <dc:comment> Inline datacage panels </dc:comment>
                   <dc:when test="$out = 'minfo_diff_panel'">
-                    <dc:call-macro name="minfo-heights-diff"/>
+                    <dc:call-macro name="minfo-heights-diff" />
                   </dc:when>
                   <dc:when test="$out = 'floodmap_dem_panel'">
-                    <dc:call-macro name="flood-map-dem"/>
+                    <dc:call-macro name="flood-map-dem" />
                   </dc:when>
                   <dc:when test="$out = 'floodmap_hws_panel'">
                     <hws>
-                      <dc:call-macro name="flood-map-hws-lines"/>
-                      <dc:call-macro name="flood-map-hws-points"/>
+                      <dc:call-macro name="flood-map-hws-lines" />
+                      <dc:call-macro name="flood-map-hws-points" />
                     </hws>
                   </dc:when>
                   <dc:when test="$out = 'winfo_diff_twin_panel'">
                     <dc:if test="$current-state-id != 'state.winfo.uesk.wsp'">
-                      <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: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:if>
                   </dc:when>
                   <dc:when test="$out = 'waterlevels_panel'">
-                    <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_3_officials"/>
-                    <dc:call-macro name="basedata_4_heightmarks-points"/>
-                    <dc:call-macro name="basedata_5_flood-protections"/>
+                    <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_3_officials" />
+                    <dc:call-macro name="basedata_4_heightmarks-points" />
+                    <dc:call-macro name="basedata_5_flood-protections" />
                   </dc:when>
                   <dc:comment> Longitudinal sections </dc:comment>
                   <dc:when test="$out = 'longitudinal_section'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'w_differences'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'discharge_longitudinal_section'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'fix_longitudinal_section_curve'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'flow_velocity'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'bed_longitudinal_section'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'sedimentload_ls'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'bedheight_middle'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'bed_difference_height_year'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'bed_difference_year'">
-                    <dc:call-macro name="longitudinal-section-prototype"/>
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                   <dc:comment> Discharge curves </dc:comment>
                   <dc:when test="$out = 'historical_discharge_wq'">
-                    <dc:call-macro name="discharge-curve-prototype"/>
+                    <dc:call-macro name="discharge-curve-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'discharge_curve'">
-                    <dc:call-macro name="discharge-curve-prototype"/>
+                    <dc:call-macro name="discharge-curve-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'fix_wq_curve'">
-                    <dc:call-macro name="discharge-curve-prototype"/>
+                    <dc:call-macro name="discharge-curve-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'fix_derivate_curve'">
-                    <dc:call-macro name="discharge-curve-prototype"/>
+                    <dc:call-macro name="discharge-curve-prototype" />
                   </dc:when>
                   <dc:when test="$out = 'computed_discharge_curve'">
-                    <dc:call-macro name="discharge-curve-prototype"/>
+                    <dc:call-macro name="discharge-curve-prototype" />
                   </dc:when>
                   <dc:when test="starts-with($out, 'sq_relation') or
                                  $out = 'sq_overview'">
-                    <dc:call-macro name="discharge-curve-prototype"/>
+                    <dc:call-macro name="discharge-curve-prototype" />
                   </dc:when>
                   <dc:comment> Cross sections </dc:comment>
                   <dc:when test="$out = 'cross_section'">
-                    <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_3_officials"/>
-                    <dc:call-macro name="basedata_4_heightmarks-points"/>
-                    <dc:call-macro name="cross_sections"/>
-                    <dc:call-macro name="basedata_5_flood-protections"/>
-                    <dc:call-macro name="hyks"/>
+                    <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_3_officials" />
+                    <dc:call-macro name="basedata_4_heightmarks-points" />
+                    <dc:call-macro name="cross_sections" />
+                    <dc:call-macro name="basedata_5_flood-protections" />
+                    <dc:call-macro name="hyks" />
                   </dc:when>
                   <dc:comment> Duration curve </dc:comment>
                   <dc:when test="$out = 'duration_curve'">
-                    <dc:call-macro name="mainvalues"/>
-                    <dc:call-macro name="basedata_2_fixations_relative_point"/>
-                    <dc:call-macro name="basedata_4_heightmarks-points-relative_points"/>
-                    <dc:call-macro name="basedata_5_flood-protections_relative_points"/>
+                    <dc:call-macro name="mainvalues" />
+                    <dc:call-macro name="basedata_2_fixations_relative_point" />
+                    <dc:call-macro name="basedata_4_heightmarks-points-relative_points" />
+                    <dc:call-macro name="basedata_5_flood-protections_relative_points" />
                   </dc:when>
                   <dc:comment> Reference curve </dc:comment>
                   <dc:when test="$out = 'reference_curve'">
-                    <dc:call-macro name="mainvalues"/>
-                    <dc:call-macro name="annotations"/>
-                    <dc:call-macro name="basedata_1_additionals-relative_point"/>
-                    <dc:call-macro name="basedata_2_fixations_relative_point"/>
-                    <dc:call-macro name="basedata_4_heightmarks-points-relative_points"/>
-                    <dc:call-macro name="basedata_5_flood-protections_relative_points"/>
+                    <dc:call-macro name="mainvalues" />
+                    <dc:call-macro name="annotations" />
+                    <dc:call-macro name="basedata_1_additionals-relative_point" />
+                    <dc:call-macro name="basedata_2_fixations_relative_point" />
+                    <dc:call-macro name="basedata_4_heightmarks-points-relative_points" />
+                    <dc:call-macro name="basedata_5_flood-protections_relative_points" />
                   </dc:when>
                   <dc:comment> Maps </dc:comment>
                   <dc:when test="$out = 'map'">
-                    <dc:call-macro name="flood-map-complete"/>
+                    <dc:call-macro name="flood-map-complete" />
                   </dc:when>
                   <dc:when test="$out = 'floodmap'">
-                    <dc:call-macro name="flood-map-complete"/>
+                    <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-MW" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flowdepthminmax_heights'">
+                    <dc:call-macro name="bed-heights-single-KL_TW" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flowdepth_waterlevels'">
+                    <minfo>
+                      <fixanalysis>
+                        <dc:call-macro name="basedata_7_waterlevels" />
+                      </fixanalysis>
+                    </minfo>
+                    <dc:call-macro name="basedata_3_officials" />
+                    <dc:call-macro name="basedata_2_fixations" />
+                    <sinfo>
+                      <sinfo_additional_ls>
+                        <dc:call-macro name="basedata_1_additionals-sinfo-with-q" />
+                        <dc:call-macro name="basedata_1_additionals-sinfo-without-q" />
+                      </sinfo_additional_ls>
+                    </sinfo>
+                  </dc:when>
+
+                  <dc:when test="$out = 'sinfo_flow_depth'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flow_depth_minmax'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flow_depth_development'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flow_depth_development_peryear'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_tkk'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_collision'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flood_duration'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flood_height'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
+                  </dc:when>
+                  <dc:when test="$out = 'sinfo_flood_duration_curve'">
+                    <dc:call-macro name="longitudinal-section-prototype" />
                   </dc:when>
                 </dc:choose>
               </dc:iterate>
@@ -263,7 +339,7 @@
                 <dc:iterate var="out" container="artifact-outs">
                   <dc:choose>
                     <dc:when test="$out = 'longitudinal_section'">
-                      <dc:call-macro name="officiallines_user"/>
+                      <dc:call-macro name="officiallines_user" />
                     </dc:when>
                   </dc:choose>
                 </dc:iterate>
@@ -276,94 +352,113 @@
                   <dc:choose>
                     <dc:comment> Inline datacage panels </dc:comment>
                     <dc:when test="$out = 'winfo_diff_twin_panel'">
-                      <dc:call-macro name="differences-fix"/>
-                      <dc:call-macro name="differences"/>
+                      <dc:call-macro name="differences-fix" />
+                      <dc:call-macro name="differences" />
                       <dc:comment comment="Candidate for:">
-                        <dc:call-macro name="longitudinal-section-user-prototype"/>
+                        <dc:call-macro name="longitudinal-section-user-prototype" />
                       </dc:comment>
                     </dc:when>
                     <dc:when test="$out = 'waterlevels_panel'">
-                      <dc:call-macro name="waterlevels-user"/>
+                      <dc:call-macro name="waterlevels-user" />
                       <dc:comment comment="Candidate for:">
-                        <dc:call-macro name="longitudinal-section-user-prototype"/>
+                        <dc:call-macro name="longitudinal-section-user-prototype" />
                       </dc:comment>
                     </dc:when>
                     <dc:when test="$out = 'floodmap_hws_panel'">
-                      <dc:call-macro name="floodmap-hws-user"/>
+                      <dc:call-macro name="floodmap-hws-user" />
                     </dc:when>
                     <dc:comment> Longitudinal sections </dc:comment>
                     <dc:when test="$out = 'longitudinal_section'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'discharge_longitudinal_section'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'w_differences'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'fix_longitudinal_section_curve'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'bedheight_middle'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'flow_velocity'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'bed_longitudinal_section'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'sedimentload_ls'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'bed_difference_year'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'bed_difference_height_year'">
-                      <dc:call-macro name="longitudinal-section-user-prototype"/>
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
+                    </dc:when>
+                    <dc:when test="$out = 'sinfo_flow_depth'">
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
+                    </dc:when>
+                    <dc:when test="$out = 'sinfo_flow_depth_minmax'">
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
+                    </dc:when>
+                    <dc:when test="$out = 'sinfo_flow_depth_development'">
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
+                    </dc:when>
+                    <dc:when test="$out = 'sinfo_flow_depth_development_peryear'">
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
+                    </dc:when>
+                    <dc:when test="$out = 'sinfo_tkk'">
+                      <dc:call-macro name="longitudinal-section-user-prototype" />
                     </dc:when>
                     <dc:comment> Discharge curves </dc:comment>
                     <dc:when test="$out = 'computed_discharge_curve'">
-                      <dc:call-macro name="discharge-curve-user-prototype"/>
+                      <dc:call-macro name="discharge-curve-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'fix_derivate_curve'">
-                      <dc:call-macro name="discharge-curve-user-prototype"/>
+                      <dc:call-macro name="discharge-curve-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'fix_wq_curve'">
-                      <dc:call-macro name="discharge-curve-user-prototype"/>
+                      <dc:call-macro name="discharge-curve-user-prototype" />
                     </dc:when>
                     <dc:when test="$out = 'historical_discharge_wq'">
-                      <dc:call-macro name="discharge-curve-user-prototype"/>
+                      <dc:call-macro name="discharge-curve-user-prototype" />
                     </dc:when>
-                    <dc:when test="starts-with($out, 'sq_relation') or
-                                 $out = 'sq_overview'">
-                      <dc:call-macro name="discharge-curve-user-prototype"/>
+                    <dc:when test="starts-with($out, 'sq_relation') or $out = 'sq_overview'">
+                      <dc:call-macro name="discharge-curve-user-prototype" />
                     </dc:when>
                     <dc:comment> Time series </dc:comment>
                     <dc:when test="$out = 'fix_deltawt_curve'">
-                      <dc:call-macro name="delta-wt"/>
+                      <dc:call-macro name="delta-wt" />
                     </dc:when>
                     <dc:when test="$out = 'historical_discharge'">
-                      <dc:call-macro name="historical-discharge-user"/>
+                      <dc:call-macro name="historical-discharge-user" />
                     </dc:when>
                     <dc:comment> Cross sections </dc:comment>
                     <dc:when test="$out = 'cross_section'">
-                      <dc:call-macro name="waterlevels"/>
+                      <dc:call-macro name="waterlevels" />
                     </dc:when>
                     <dc:comment> Duration curve </dc:comment>
                     <dc:when test="$out = 'duration_curve'">
-                      <dc:call-macro name="duration-curve"/>
+                      <dc:call-macro name="duration-curve" />
                     </dc:when>
                     <dc:comment> Reference curve </dc:comment>
                     <dc:when test="$out = 'reference_curve'">
-                      <dc:call-macro name="reference-curves"/>
+                      <dc:call-macro name="reference-curves" />
                     </dc:when>
                     <dc:comment> Maps </dc:comment>
                     <dc:when test="$out = 'floodmap'">
-                      <dc:call-macro name="flood-map"/>
+                      <dc:call-macro name="flood-map" />
                     </dc:when>
                     <dc:when test="$out = 'map'">
-                      <dc:call-macro name="flood-map"/>
+                      <dc:call-macro name="flood-map" />
+                    </dc:when>
+
+                    <dc:when test="$out = 'sinfo_flowdepth_waterlevels'">
+                      <dc:call-macro name="longitudinal-section-fix-vollmer_q" />
+                      <!-- TODO: 'Frühere Berechnungen//Bezugswasserstände' -->
                     </dc:when>
                   </dc:choose>
                 </dc:iterate>
@@ -384,12 +479,12 @@
               <discharges description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="out" value="historical_discharge"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="out" value="historical_discharge" />
                   </dc:element>
                 </dc:for-each>
               </discharges>
@@ -407,12 +502,12 @@
               <differences description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="out" value="${out_name}"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="out" value="${out_name}" />
                   </dc:element>
                 </dc:for-each>
               </differences>
@@ -430,12 +525,12 @@
               <ref_curve description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="out" value="reference_curve"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="out" value="reference_curve" />
                   </dc:element>
                 </dc:for-each>
               </ref_curve>
@@ -451,14 +546,14 @@
         <dc:if test="dc:has-result()">
           <floodmap>
             <dc:for-each>
-              <dc:variable name="combined_desc" expr="concat($facet_description, ' ', dc:date-format('dd.MM.yyyy - H:mm:ss', $a_creation), ' ', $collection_name)"/>
+              <dc:variable name="combined_desc" expr="concat($facet_description, ' ', dc:date-format('dd.MM.yyyy - H:mm:ss', $a_creation), ' ', $collection_name)" />
               <dc:element name="${facet_name}">
-                <dc:attribute name="description" value="${combined_desc}"/>
-                <dc:attribute name="factory" value="winfo"/>
-                <dc:attribute name="target_out" value="${out}"/>
-                <dc:attribute name="artifact-id" value="${a_id}"/>
-                <dc:attribute name="ids" value="${a_id}"/>
-                <dc:attribute name="out" value="floodmap"/>
+                <dc:attribute name="description" value="${combined_desc}" />
+                <dc:attribute name="factory" value="winfo" />
+                <dc:attribute name="target_out" value="${out}" />
+                <dc:attribute name="artifact-id" value="${a_id}" />
+                <dc:attribute name="ids" value="${a_id}" />
+                <dc:attribute name="out" value="floodmap" />
               </dc:element>
             </dc:for-each>
           </floodmap>
@@ -475,12 +570,12 @@
               <longitudinal_section_columns description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="cross_section"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="cross_section" />
                   </dc:element>
                 </dc:for-each>
               </longitudinal_section_columns>
@@ -492,7 +587,7 @@
 
     <dc:macro name="collection-group">
       <dc:group expr="concat($river, ' ', dc:date-format('dd.MM.yyyy - H:mm:ss', $a_creation), ' ', $collection_name)">
-        <dc:macro-body/>
+        <dc:macro-body />
       </dc:group>
     </dc:macro>
 
@@ -505,12 +600,12 @@
               <longitudinal_section_columns description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="longitudinal_section"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="longitudinal_section" />
                   </dc:element>
                 </dc:for-each>
               </longitudinal_section_columns>
@@ -525,27 +620,40 @@
           ($facet_name = 'longitudinal_section.w' or
            $facet_name = 'longitudinal_section.q')
         ">
-        <dc:if test="dc:has-result()">
-          <waterlevels_fix_vollmer>
-            <dc:call-macro name="collection-group">
-              <waterlevels description="{dc:group-key()}">
-                <dc:for-each>
-                  <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="fixanalysis"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="longitudinal_section"/>
-                  </dc:element>
-                </dc:for-each>
-              </waterlevels>
-            </dc:call-macro>
-          </waterlevels_fix_vollmer>
-        </dc:if>
+        <dc:call-macro name="longitudinal-section-fix-vollmer_macro" />
       </dc:filter>
     </dc:macro>
 
+    <dc:macro name="longitudinal-section-fix-vollmer_q">
+      <dc:filter expr="$a_state = 'state.fix.vollmer.compute' and $facet_name = 'longitudinal_section.q'">
+        <dc:call-macro name="longitudinal-section-fix-vollmer_macro" />
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="longitudinal-section-fix-vollmer_macro">
+      <dc:if test="dc:has-result()">
+        <waterlevels_fix_vollmer>
+          <dc:call-macro name="collection-group">
+            <waterlevels description="{dc:group-key()}">
+              <dc:for-each>
+                <dc:element name="${facet_name}">
+                  <dc:attribute name="description" value="${facet_description}" />
+                  <dc:attribute name="ids" value="${facet_num}" />
+                  <dc:attribute name="factory" value="fixanalysis" />
+                  <dc:attribute name="target_out" value="${out}" />
+                  <dc:attribute name="artifact-id" value="${a_gid}" />
+                  <dc:attribute name="out" value="longitudinal_section" />
+
+                  <dc:variable name="fixAnalysisYear" expr="dc:fix_analysis_year($a_gid)" />
+                  <dc:attribute name="year" value="${fixAnalysisYear}" />
+                </dc:element>
+              </dc:for-each>
+            </waterlevels>
+          </dc:call-macro>
+        </waterlevels_fix_vollmer>
+      </dc:if>
+    </dc:macro>
+
     <dc:macro name="longitudinal-section-fix">
       <dc:filter expr="$out_name = 'fix_longitudinal_section_curve' and
         (starts-with($facet_name, 'fix_deviation_ls') or
@@ -559,12 +667,12 @@
               <waterlevels description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="fixanalysis"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="fix_longitudinal_section_curve"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="factory" value="fixanalysis" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="fix_longitudinal_section_curve" />
                   </dc:element>
                 </dc:for-each>
               </waterlevels>
@@ -587,12 +695,12 @@
               <waterlevels description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="fixanalysis"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="fix_deltawt_curve"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="factory" value="fixanalysis" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="fix_deltawt_curve" />
                   </dc:element>
                 </dc:for-each>
               </waterlevels>
@@ -603,7 +711,8 @@
     </dc:macro>
 
     <dc:macro name="fix-wq-curve">
-      <dc:filter expr="($out_name = 'fix_wq_curve' and
+      <dc:filter
+        expr="($out_name = 'fix_wq_curve' and
                        (starts-with($facet_name, 'fix_analysis_events_wq') or
                        starts-with($facet_name, 'fix_reference_events_wq') or
                        starts-with($facet_name, 'fix_sector_average_wq') or
@@ -618,22 +727,22 @@
                   <dc:choose>
                     <dc:when test="$out_name = 'fix_wq_curve'">
                       <dc:element name="${facet_name}">
-                        <dc:attribute name="description" value="${facet_description}"/>
-                        <dc:attribute name="ids" value="${facet_num}"/>
-                        <dc:attribute name="factory" value="fixanalysis"/>
-                        <dc:attribute name="target_out" value="${out}"/>
-                        <dc:attribute name="artifact-id" value="${a_gid}"/>
-                        <dc:attribute name="out" value="fix_wq_curve"/>
+                        <dc:attribute name="description" value="${facet_description}" />
+                        <dc:attribute name="ids" value="${facet_num}" />
+                        <dc:attribute name="factory" value="fixanalysis" />
+                        <dc:attribute name="target_out" value="${out}" />
+                        <dc:attribute name="artifact-id" value="${a_gid}" />
+                        <dc:attribute name="out" value="fix_wq_curve" />
                       </dc:element>
                     </dc:when>
                     <dc:when test="$out_name = 'fix_derivate_curve'">
                       <dc:element name="${facet_name}">
-                        <dc:attribute name="description" value="${facet_description}"/>
-                        <dc:attribute name="ids" value="${facet_num}"/>
-                        <dc:attribute name="factory" value="fixanalysis"/>
-                        <dc:attribute name="target_out" value="${out}"/>
-                        <dc:attribute name="artifact-id" value="${a_gid}"/>
-                        <dc:attribute name="out" value="fix_derivate_curve"/>
+                        <dc:attribute name="description" value="${facet_description}" />
+                        <dc:attribute name="ids" value="${facet_num}" />
+                        <dc:attribute name="factory" value="fixanalysis" />
+                        <dc:attribute name="target_out" value="${out}" />
+                        <dc:attribute name="artifact-id" value="${a_gid}" />
+                        <dc:attribute name="out" value="fix_derivate_curve" />
                       </dc:element>
                     </dc:when>
                   </dc:choose>
@@ -651,12 +760,12 @@
           <computed_discharge_curves>
             <dc:for-each>
               <dc:element name="${facet_name}">
-                <dc:attribute name="description" value="${facet_description}"/>
-                <dc:attribute name="factory" value="fixanalysis"/>
-                <dc:attribute name="target_out" value="${out}"/>
-                <dc:attribute name="artifact-id" value="${a_gid}"/>
-                <dc:attribute name="ids" value="${a_gid}"/>
-                <dc:attribute name="out" value="computed_discharge_curve"/>
+                <dc:attribute name="description" value="${facet_description}" />
+                <dc:attribute name="factory" value="fixanalysis" />
+                <dc:attribute name="target_out" value="${out}" />
+                <dc:attribute name="artifact-id" value="${a_gid}" />
+                <dc:attribute name="ids" value="${a_gid}" />
+                <dc:attribute name="out" value="computed_discharge_curve" />
               </dc:element>
             </dc:for-each>
           </computed_discharge_curves>
@@ -672,12 +781,12 @@
               <projects description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="ids" value="${a_gid}"/>
-                    <dc:attribute name="out" value="computed_discharge_curve"/>
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="ids" value="${a_gid}" />
+                    <dc:attribute name="out" value="computed_discharge_curve" />
                   </dc:element>
                 </dc:for-each>
               </projects>
@@ -693,12 +802,12 @@
           <computed_discharge_curves>
             <dc:for-each>
               <dc:element name="${facet_name}">
-                <dc:attribute name="description" value="${facet_description}"/>
-                <dc:attribute name="factory" value="winfo"/>
-                <dc:attribute name="target_out" value="${out}"/>
-                <dc:attribute name="artifact-id" value="${a_id}"/>
-                <dc:attribute name="ids" value="${a_id}"/>
-                <dc:attribute name="out" value="duration_curve"/>
+                <dc:attribute name="description" value="${facet_description}" />
+                <dc:attribute name="factory" value="winfo" />
+                <dc:attribute name="target_out" value="${out}" />
+                <dc:attribute name="artifact-id" value="${a_id}" />
+                <dc:attribute name="ids" value="${a_id}" />
+                <dc:attribute name="out" value="duration_curve" />
               </dc:element>
             </dc:for-each>
           </computed_discharge_curves>
@@ -719,23 +828,21 @@
                 <dc:for-each>
                   <dc:choose>
                     <dc:when test="$ld_m = 'location'">
-                      <dc:variable name="combined_desc"
-                                   expr="concat($facet_description,
-                                         ' an KM ', $deffrom)"/>
+                      <dc:variable name="combined_desc" expr="concat($facet_description,
+                                         ' an KM ', $deffrom)" />
                     </dc:when>
                     <dc:otherwise>
-                      <dc:variable name="combined_desc"
-                                   expr="concat($facet_description, ' von KM ',
-                                         $deffrom, ' bis KM ', $defto)"/>
+                      <dc:variable name="combined_desc" expr="concat($facet_description, ' von KM ',
+                                         $deffrom, ' bis KM ', $defto)" />
                     </dc:otherwise>
                   </dc:choose>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${combined_desc}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="longitudinal_section"/>
+                    <dc:attribute name="description" value="${combined_desc}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="longitudinal_section" />
                   </dc:element>
                 </dc:for-each>
               </waterlevels>
@@ -747,7 +854,7 @@
 
     <dc:comment comment="For building differences." />
     <dc:macro name="differences-fix">
-      <dc:comment comment="Vollmer curves need own factory"/>
+      <dc:comment comment="Vollmer curves need own factory" />
       <dc:filter expr="$a_state = 'state.fix.vollmer.compute' and $facet_name = 'longitudinal_section.w'">
         <dc:if test="dc:has-result()">
           <vollmer_waterlevels>
@@ -756,20 +863,20 @@
                 <dc:for-each>
                   <dc:choose>
                     <dc:when test="$ld_m = 'location'">
-                      <dc:variable name="combined_desc" expr="concat($facet_description, ' an KM ', $deffrom)"/>
+                      <dc:variable name="combined_desc" expr="concat($facet_description, ' an KM ', $deffrom)" />
                     </dc:when>
                     <dc:otherwise>
                       <dc:variable name="combined_desc" expr="concat($facet_description, ' von KM ',
-                        $deffrom, ' bis KM ', $defto)"/>
+                        $deffrom, ' bis KM ', $defto)" />
                     </dc:otherwise>
-                 </dc:choose>
+                  </dc:choose>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${combined_desc}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="fixanalysis"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="longitudinal_section"/>
+                    <dc:attribute name="description" value="${combined_desc}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="factory" value="fixanalysis" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="longitudinal_section" />
                   </dc:element>
                 </dc:for-each>
               </waterlevels>
@@ -782,27 +889,27 @@
         <dc:if test="dc:has-result()">
           <waterlevels>
             <dc:call-macro name="collection-group">
-                <waterlevels description="{dc:group-key()}">
-                  <dc:for-each>
-                    <dc:choose>
-                      <dc:when test="$ld_m = 'location'">
-                        <dc:variable name="combined_desc" expr="concat($facet_description, ' an KM ', $deffrom)"/>
-                      </dc:when>
-                      <dc:otherwise>
-                        <dc:variable name="combined_desc" expr="concat($facet_description, ' von KM ',
-                          $deffrom, ' bis KM ', $defto)"/>
-                      </dc:otherwise>
-                    </dc:choose>
-                    <dc:element name="${facet_name}">
-                      <dc:attribute name="description" value="${combined_desc}"/>
-                      <dc:attribute name="ids" value="${facet_num}"/>
-                      <dc:attribute name="factory" value="winfo"/>
-                      <dc:attribute name="target_out" value="${out}"/>
-                      <dc:attribute name="artifact-id" value="${a_gid}"/>
-                      <dc:attribute name="out" value="longitudinal_section"/>
-                    </dc:element>
-                  </dc:for-each>
-                </waterlevels>
+              <waterlevels description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:choose>
+                    <dc:when test="$ld_m = 'location'">
+                      <dc:variable name="combined_desc" expr="concat($facet_description, ' an KM ', $deffrom)" />
+                    </dc:when>
+                    <dc:otherwise>
+                      <dc:variable name="combined_desc" expr="concat($facet_description, ' von KM ',
+                          $deffrom, ' bis KM ', $defto)" />
+                    </dc:otherwise>
+                  </dc:choose>
+                  <dc:element name="${facet_name}">
+                    <dc:attribute name="description" value="${combined_desc}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="longitudinal_section" />
+                  </dc:element>
+                </dc:for-each>
+              </waterlevels>
             </dc:call-macro>
           </waterlevels>
         </dc:if>
@@ -816,12 +923,12 @@
         <own-hws>
           <dc:for-each>
             <dc:element name="${facet_name}">
-              <dc:attribute name="description" value="${facet_description}"/>
-              <dc:attribute name="ids" value="${facet_num}"/>
-              <dc:attribute name="factory" value="winfo"/>
-              <dc:attribute name="target_out" value="${out}"/>
-              <dc:attribute name="artifact-id" value="${a_gid}"/>
-              <dc:attribute name="out" value="floodmap"/>
+              <dc:attribute name="description" value="${facet_description}" />
+              <dc:attribute name="ids" value="${facet_num}" />
+              <dc:attribute name="factory" value="winfo" />
+              <dc:attribute name="target_out" value="${out}" />
+              <dc:attribute name="artifact-id" value="${a_gid}" />
+              <dc:attribute name="out" value="floodmap" />
             </dc:element>
           </dc:for-each>
         </own-hws>
@@ -837,12 +944,12 @@
               <quality-bed description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="factory" value="minfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="bed_longitudinal_section"/>
+                    <dc:attribute name="factory" value="minfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="bed_longitudinal_section" />
                   </dc:element>
                 </dc:for-each>
               </quality-bed>
@@ -861,12 +968,12 @@
               <flow description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="factory" value="minfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="flow_velocity"/>
+                    <dc:attribute name="factory" value="minfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="flow_velocity" />
                   </dc:element>
                 </dc:for-each>
               </flow>
@@ -884,12 +991,12 @@
               <load description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="factory" value="minfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="${out_name}"/>
+                    <dc:attribute name="factory" value="minfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
                   </dc:element>
                 </dc:for-each>
               </load>
@@ -908,12 +1015,12 @@
               <middle_bedheight description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="factory" value="minfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="${out_name}"/>
+                    <dc:attribute name="factory" value="minfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
                   </dc:element>
                 </dc:for-each>
               </middle_bedheight>
@@ -932,12 +1039,12 @@
               <difference description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="factory" value="minfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="${out_name}"/>
+                    <dc:attribute name="factory" value="minfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
                   </dc:element>
                 </dc:for-each>
               </difference>
@@ -948,7 +1055,8 @@
     </dc:macro>
 
     <dc:macro name="sqrelations_user">
-      <dc:filter expr="not(dc:contains($facet_name, 'overview')) and (
+      <dc:filter
+        expr="not(dc:contains($facet_name, 'overview')) and (
         ($out = 'sq_relation_a' and starts-with($facet_name, 'sq_a_')) or
         ($out = 'sq_relation_b' and starts-with($facet_name, 'sq_b_')) or
         ($out = 'sq_relation_c' and starts-with($facet_name, 'sq_c_')) or
@@ -963,12 +1071,12 @@
               <sqrel description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="factory" value="minfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="${out_name}"/>
+                    <dc:attribute name="factory" value="minfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
                   </dc:element>
                 </dc:for-each>
               </sqrel>
@@ -986,12 +1094,12 @@
               <discharge description="{dc:group-key()}">
                 <dc:for-each>
                   <dc:element name="${facet_name}">
-                    <dc:attribute name="factory" value="winfo"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}-${facet_name}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="discharge_longitudinal_section"/>
+                    <dc:attribute name="factory" value="winfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}-${facet_name}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="discharge_longitudinal_section" />
                   </dc:element>
                 </dc:for-each>
               </discharge>
@@ -1005,37 +1113,31 @@
     <!-- Macros to load system data -->
 
     <dc:macro name="qmainvalues">
-      <qmainvalue factory="mainvalue" ids="{$river_id}:q" target_out="{$out}"/>
+      <qmainvalue factory="mainvalue" ids="{$river_id}:q" target_out="{$out}" />
     </dc:macro>
 
     <dc:macro name="mainvalues">
-      <wmainvalue factory="mainvalue" ids="{$river_id}:w" target_out="{$out}"/>
-      <dc:call-macro name="qmainvalues"/>
+      <wmainvalue factory="mainvalue" ids="{$river_id}:w" target_out="{$out}" />
+      <dc:call-macro name="qmainvalues" />
     </dc:macro>
 
     <!-- discharge curves -->
     <dc:macro name="hist_discharge_factory">
       <dc:for-each>
-        <dc:variable name="validity"
-                     expr="concat(
+        <dc:variable name="validity" expr="concat(
                            dc:date-format('dd.MM.yyyy', $start_time),
                            ' - ',
-                           dc:date-format('dd.MM.yyyy', $stop_time))"/>
-        <histdis name="{concat($bfg_id, ' ', $validity)}"
-                 description="{concat($bfg_id, ' ', $validity)}"
-                 factory="gaugedischarge" target_out="{$out}"
-                 ids="{$gauge_name};{$dt_id};{concat($bfg_id, ' ',
-                      $gauge_name, ' ', $validity)}"/>
+                           dc:date-format('dd.MM.yyyy', $stop_time))" />
+        <histdis name="{concat($bfg_id, ' ', $validity)}" description="{concat($bfg_id, ' ', $validity)}" factory="gaugedischarge" target_out="{$out}" ids="{$gauge_name};{$dt_id};{concat($bfg_id, ' ',
+                      $gauge_name, ' ', $validity)}" />
       </dc:for-each>
     </dc:macro>
 
     <dc:macro name="hist_discharge_rec">
-      <dc:variable name="start" type="number"
-                   expr="dc:date-format('yyyyMMdd',
-                           number(substring-before($year_range, ';')))"/>
-      <dc:variable name="stop" type="number"
-                   expr="dc:date-format('yyyyMMdd',
-                           number(substring-after($year_range, ';')))"/>
+      <dc:variable name="start" type="number" expr="dc:date-format('yyyyMMdd',
+                           number(substring-before($year_range, ';')))" />
+      <dc:variable name="stop" type="number" expr="dc:date-format('yyyyMMdd',
+                           number(substring-after($year_range, ';')))" />
       <dc:call-macro name="discharge_curve_choose_context">
         <dc:filter expr="$kind = 1 and
                          number(dc:date-format('yyyyMMdd', $start_time))
@@ -1044,7 +1146,7 @@
                              dc:date-format('yyyyMMdd', $stop_time),
                              '99999999'))
                            &gt; $start">
-          <dc:call-macro name="hist_discharge_factory"/>
+          <dc:call-macro name="hist_discharge_factory" />
         </dc:filter>
       </dc:call-macro>
     </dc:macro>
@@ -1055,8 +1157,7 @@
           <dc:group expr="$gauge_name">
             <gauge name="{dc:group-key()}">
               <dc:for-each>
-                <current_gauge factory="gaugedischarge" target_out="{$out}"
-                               ids="{$gauge_name}"/>
+                <current_gauge factory="gaugedischarge" target_out="{$out}" ids="{$gauge_name}" />
               </dc:for-each>
             </gauge>
           </dc:group>
@@ -1070,7 +1171,7 @@
           <historical_discharge_curves>
             <dc:group expr="$gauge_name">
               <gauge name="{dc:group-key()}">
-                <dc:call-macro name="hist_discharge_factory"/>
+                <dc:call-macro name="hist_discharge_factory" />
               </gauge>
             </dc:group>
           </historical_discharge_curves>
@@ -1082,16 +1183,15 @@
       <dc:choose>
         <dc:when test="$fromkm &gt; -99999 and $tokm &lt; 99999">
           <dc:context>
-            <dc:call-macro name="discharge_curves_km"/>
-            <dc:macro-body/>
+            <dc:call-macro name="discharge_curves_km" />
+            <dc:macro-body />
           </dc:context>
         </dc:when>
         <dc:otherwise>
-          <dc:variable name="refgauge" type="number"
-                       expr="dc:get('reference_gauge')"/>
+          <dc:variable name="refgauge" type="number" expr="dc:get('reference_gauge')" />
           <dc:context>
-            <dc:call-macro name="discharge_curves_refgauge"/>
-            <dc:macro-body/>
+            <dc:call-macro name="discharge_curves_refgauge" />
+            <dc:macro-body />
           </dc:context>
         </dc:otherwise>
       </dc:choose>
@@ -1099,35 +1199,35 @@
 
     <dc:macro name="discharge_curves_km">
       <dc:statement>
-          SELECT g.name AS gauge_name,
-                 dt.id  AS dt_id,
-                 t.start_time AS start_time,
-                 t.stop_time AS stop_time,
-                 dt.bfg_id AS bfg_id,
-                 dt.kind AS kind
-          FROM gauges g
-          JOIN discharge_tables dt ON g.id = dt.gauge_id
-          LEFT JOIN time_intervals t ON dt.time_interval_id = t.id
-          WHERE g.river_id = ${river_id}
-            AND g.station BETWEEN ${fromkm} AND ${tokm}
-          ORDER BY start_time
+        SELECT g.name AS gauge_name,
+        dt.id AS dt_id,
+        t.start_time AS start_time,
+        t.stop_time AS stop_time,
+        dt.bfg_id AS bfg_id,
+        dt.kind AS kind
+        FROM gauges g
+        JOIN discharge_tables dt ON g.id = dt.gauge_id
+        LEFT JOIN time_intervals t ON dt.time_interval_id = t.id
+        WHERE g.river_id = ${river_id}
+        AND g.station BETWEEN ${fromkm} AND ${tokm}
+        ORDER BY start_time
       </dc:statement>
     </dc:macro>
 
     <dc:macro name="discharge_curves_refgauge">
       <dc:statement>
-          SELECT g.name AS gauge_name,
-                 dt.id  AS dt_id,
-                 t.start_time AS start_time,
-                 t.stop_time AS stop_time,
-                 dt.bfg_id AS bfg_id,
-                 dt.kind AS kind
-          FROM gauges g
-          JOIN discharge_tables dt ON g.id = dt.gauge_id
-          LEFT JOIN time_intervals t ON dt.time_interval_id = t.id
-          WHERE g.river_id = ${river_id}
-            AND g.official_number = ${refgauge}
-          ORDER BY start_time
+        SELECT g.name AS gauge_name,
+        dt.id AS dt_id,
+        t.start_time AS start_time,
+        t.stop_time AS stop_time,
+        dt.bfg_id AS bfg_id,
+        dt.kind AS kind
+        FROM gauges g
+        JOIN discharge_tables dt ON g.id = dt.gauge_id
+        LEFT JOIN time_intervals t ON dt.time_interval_id = t.id
+        WHERE g.river_id = ${river_id}
+        AND g.official_number = ${refgauge}
+        ORDER BY start_time
       </dc:statement>
     </dc:macro>
 
@@ -1137,17 +1237,15 @@
         <dc:context connection="system">
           <dc:statement>
             SELECT DISTINCT
-                   cs.id          AS prot_id,
-                   cs.description AS prot_description
+            cs.id AS prot_id,
+            cs.description AS prot_description
             FROM cross_sections cs
-              JOIN cross_section_lines csl ON csl.cross_section_id = cs.id
+            JOIN cross_section_lines csl ON csl.cross_section_id = cs.id
             WHERE cs.river_id = ${river_id}
-              AND csl.km BETWEEN ${fromkm} AND ${tokm}
+            AND csl.km BETWEEN ${fromkm} AND ${tokm}
           </dc:statement>
           <dc:for-each>
-            <cross_section name="{$prot_description}"
-                           ids="{$prot_id}"
-                           factory="crosssections" target_out="{$out}" />
+            <cross_section name="{$prot_description}" ids="{$prot_id}" factory="crosssections" target_out="{$out}" />
           </dc:for-each>
         </dc:context>
       </cross_sections>
@@ -1158,17 +1256,15 @@
         <dc:context connection="system">
           <dc:statement>
             SELECT DISTINCT
-                   h.id          AS hyk_id,
-                   h.description AS hyk_description
+            h.id AS hyk_id,
+            h.description AS hyk_description
             FROM hyks h
-              JOIN hyk_entries he ON he.hyk_id = h.id
+            JOIN hyk_entries he ON he.hyk_id = h.id
             WHERE river_id = ${river_id}
-              AND he.km BETWEEN ${fromkm} AND ${tokm}
+            AND he.km BETWEEN ${fromkm} AND ${tokm}
           </dc:statement>
           <dc:for-each>
-            <hyk name="{$hyk_description}"
-                 ids="{$hyk_id}"
-                 factory="hyk" target_out="{$out}" />
+            <hyk name="{$hyk_description}" ids="{$hyk_id}" factory="hyk" target_out="{$out}" />
           </dc:for-each>
         </dc:context>
       </hyks>
@@ -1185,7 +1281,7 @@
             <dc:group expr="$wst_description">
               <basedata name="{dc:group-key()}">
                 <dc:for-each>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </basedata>
             </dc:group>
@@ -1196,19 +1292,13 @@
 
     <dc:macro name="basedata_0">
       <dc:call-macro name="basedata_0_macro">
-        <column name="{$wst_column_name}"
-                ids="base_data-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwqkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="base_data-wstv-{$wst_column_position}-{$wst_id}" factory="staticwqkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_0_wq">
       <dc:call-macro name="basedata_0_macro">
-        <column name="{$wst_column_name}"
-                ids="base_data-wstv-{$wst_column_position}-{$wst_id}"
-                factory="wqinterpol" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="base_data-wstv-{$wst_column_position}-{$wst_id}" factory="wqinterpol" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
@@ -1218,9 +1308,9 @@
         <dc:if test="dc:has-result()">
           <additionals>
             <dc:group expr="dc:replace($wst_description, 'Zus.Längsschnitte/', '')">
-              <additional name="{dc:group-key()}">
+              <additional name="{dc:group-key()}" description="{dc:group-key()}">
                 <dc:for-each>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </additional>
             </dc:group>
@@ -1231,28 +1321,64 @@
 
     <dc:macro name="basedata_1_additionals">
       <dc:call-macro name="basedata_1_additionals_macro">
-        <column name="{$wst_column_name}"
-                ids="additionals-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwqkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="additionals-wstv-{$wst_column_position}-{$wst_id}" factory="staticwqkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
+      </dc:call-macro>
+    </dc:macro>
+
+    <dc:macro name="basedata_1_additionals-sinfo-with-q_macro">
+      <dc:filter expr="$kind=1 and $sinfo_selection='Q'">
+        <dc:if test="dc:has-result()">
+          <sinfo_additional_ls_withQ>
+            <dc:group expr="dc:replace($wst_description, 'Zus.Längsschnitte/', '')">
+              <additional name="{dc:group-key()}" description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:macro-body />
+                </dc:for-each>
+              </additional>
+            </dc:group>
+          </sinfo_additional_ls_withQ>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="basedata_1_additionals-sinfo-with-q">
+      <dc:call-macro name="basedata_1_additionals-sinfo-with-q_macro">
+        <column name="{$wst_column_name}" ids="additionals-wstv-{$wst_column_position}-{$wst_id}" factory="staticwqkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" year="{dc:date-format('yyyy', $start_time)}" />
+      </dc:call-macro>
+    </dc:macro>
+
+    <dc:macro name="basedata_1_additionals-sinfo-without-q_macro">
+      <dc:filter expr="$kind=1 and $sinfo_selection='W'">
+        <dc:if test="dc:has-result()">
+          <sinfo_additional_ls_withoutQ>
+            <dc:group expr="dc:replace($wst_description, 'Zus.Längsschnitte/', '')">
+              <additional name="{dc:group-key()}" description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:macro-body />
+                </dc:for-each>
+              </additional>
+            </dc:group>
+          </sinfo_additional_ls_withoutQ>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="basedata_1_additionals-sinfo-without-q">
+      <dc:call-macro name="basedata_1_additionals-sinfo-without-q_macro">
+        <dc:variable name="start_year" expr="dc:date-format('yyyy', $start_time)" />
+        <column name="{$wst_column_name}" ids="additionals-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" year="{dc:date-format('yyyy', $start_time)}" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_1_additionals_wq">
       <dc:call-macro name="basedata_1_additionals_macro">
-        <column name="{$wst_column_name}"
-                ids="base_data-wstv-{$wst_column_position}-{$wst_id}"
-                factory="wqinterpol" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="base_data-wstv-{$wst_column_position}-{$wst_id}" factory="wqinterpol" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_1_additionals-relative_point">
       <dc:call-macro name="basedata_1_additionals_macro">
-        <column name="{$wst_column_name}"
-                ids="additionals-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="additionals-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
@@ -1264,7 +1390,7 @@
             <dc:group expr="dc:replace($wst_description, 'Fixierungen/', '')">
               <fixation name="{dc:group-key()}">
                 <dc:for-each>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </fixation>
             </dc:group>
@@ -1275,28 +1401,20 @@
 
     <dc:macro name="basedata_2_fixations">
       <dc:call-macro name="fixings-macro">
-        <column name="{$wst_column_name}"
-                ids="fixations-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwqkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <dc:variable name="start_year" expr="dc:date-format('yyyy', $start_time)" />
+        <column name="{$wst_column_name}" ids="fixations-wstv-{$wst_column_position}-{$wst_id}" factory="staticwqkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" year="{dc:date-format('yyyy', $start_time)}" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_2_fixations_wq">
       <dc:call-macro name="fixings-macro">
-        <column name="{$wst_column_name}"
-                ids="fixations-wstv-{$wst_column_position}-{$wst_id}"
-                factory="wqinterpol" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="fixations-wstv-{$wst_column_position}-{$wst_id}" factory="wqinterpol" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_2_fixations_relative_point">
       <dc:call-macro name="fixings-macro">
-        <column name="{$wst_column_name}"
-                ids="fixations-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="fixations-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
@@ -1308,7 +1426,7 @@
             <dc:group expr="$wst_description">
               <official name="{dc:group-key()}">
                 <dc:for-each>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </official>
             </dc:group>
@@ -1319,21 +1437,14 @@
 
     <dc:macro name="basedata_3_officials">
       <dc:call-macro name="basedata_3_macro">
-        <column name="{$wst_column_name}"
-                ids="additionals-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwqkms"
-                target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <dc:variable name="start_year" expr="dc:date-format('yyyy', $start_time)" />      
+        <column name="{$wst_column_name}" ids="additionals-wstv-{$wst_column_position}-{$wst_id}" factory="staticwqkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" year="{dc:date-format('yyyy', $start_time)}" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_3_officials_wq">
       <dc:call-macro name="basedata_3_macro">
-        <column name="{$wst_column_name}"
-                ids="officials_wq-wstv-{$wst_column_position}-{$wst_id}"
-                factory="wqinterpol"
-                target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="officials_wq-wstv-{$wst_column_position}-{$wst_id}" factory="wqinterpol" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
@@ -1345,7 +1456,7 @@
             <dc:group expr="dc:replace($wst_description, 'HW-Marken/', '')">
               <heightmark name="{dc:group-key()}">
                 <dc:for-each>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </heightmark>
             </dc:group>
@@ -1356,28 +1467,19 @@
 
     <dc:macro name="basedata_4_heightmarks-points">
       <dc:call-macro name="basedata_4_macro">
-        <column name="{$wst_column_name}"
-                ids="heightmarks_points-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="heightmarks_points-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_4_heightmarks-points_wq">
       <dc:call-macro name="basedata_4_macro">
-        <column name="{$wst_column_name}"
-                ids="heightmarks_points-wstv-{$wst_column_position}-{$wst_id}"
-                factory="wqinterpol" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="heightmarks_points-wstv-{$wst_column_position}-{$wst_id}" factory="wqinterpol" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_4_heightmarks-points-relative_points">
       <dc:call-macro name="basedata_4_macro">
-        <column name="{$wst_column_name}"
-                ids="heightmarks_points-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="heightmarks_points-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
@@ -1389,7 +1491,7 @@
             <dc:group expr="dc:replace($wst_description, 'HW-Schutzanlagen/', '')">
               <flood_protection name="{dc:group-key()}">
                 <dc:for-each>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </flood_protection>
             </dc:group>
@@ -1400,28 +1502,19 @@
 
     <dc:macro name="basedata_5_flood-protections">
       <dc:call-macro name="basedata_5_macro">
-        <column name="{$wst_column_name}"
-                ids="flood_protection-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="flood_protection-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_5_flood-protections_wq">
       <dc:call-macro name="basedata_5_macro">
-        <column name="{$wst_column_name}"
-                ids="flood_protection-wstv-{$wst_column_position}-{$wst_id}"
-                factory="wqinterpol" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="flood_protection-wstv-{$wst_column_position}-{$wst_id}" factory="wqinterpol" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_5_flood-protections_relative_points">
       <dc:call-macro name="basedata_5_macro">
-        <column name="{$wst_column_name}"
-                ids="flood_protection-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="flood_protection-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
@@ -1433,13 +1526,9 @@
             <delta_w_cm>
               <dc:filter expr="contains($wst_description, 'cm.csv')">
                 <dc:group expr="dc:replace($wst_description, 'CSV/', '')">
-                  <relativepoint name="{dc:group-key()}">
+                  <relativepoint name="{dc:group-key()}" description="{dc:group-key()}">
                     <dc:for-each>
-                      <column name="{$wst_column_name}"
-                              ids="delta_w-wstv-{$wst_column_position}-{$wst_id}"
-                              factory="staticwkms"
-                              target_out="{$out}"
-                              info="{$info} [km {$deffrom} - {$defto}]"/>
+                      <column name="{$wst_column_name}" ids="delta_w-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
                     </dc:for-each>
                   </relativepoint>
                 </dc:group>
@@ -1448,12 +1537,9 @@
             <delta_w_cma>
               <dc:filter expr="contains($wst_description, 'cm-a.csv')">
                 <dc:group expr="dc:replace($wst_description, 'CSV/', '')">
-                  <relativepoint name="{dc:group-key()}">
+                  <relativepoint name="{dc:group-key()}" description="{dc:group-key()}">
                     <dc:for-each>
-                      <column name="{$wst_column_name}"
-                              ids="delta_w_cma-wstv-{$wst_column_position}-{$wst_id}"
-                              factory="staticwkms" target_out="{$out}"
-                              info="{$info} [km {$deffrom} - {$defto}]"/>
+                      <column name="{$wst_column_name}" ids="delta_w_cma-wstv-{$wst_column_position}-{$wst_id}" factory="staticwkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
                     </dc:for-each>
                   </relativepoint>
                 </dc:group>
@@ -1470,9 +1556,9 @@
         <dc:if test="dc:has-result()">
           <wlevel>
             <dc:group expr="dc:replace($wst_description, 'CSV/', '')">
-              <relativepoint name="{dc:group-key()}">
+              <relativepoint name="{dc:group-key()}" description="{dc:group-key()}">
                 <dc:for-each>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </relativepoint>
             </dc:group>
@@ -1483,19 +1569,14 @@
 
     <dc:macro name="basedata_7_waterlevels">
       <dc:call-macro name="basedata_7_macro">
-        <column name="{$wst_column_name}"
-                ids="additionals-wstv-{$wst_column_position}-{$wst_id}"
-                factory="staticwqkms" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <dc:variable name="start_year" expr="dc:date-format('yyyy', $start_time)" />      
+        <column name="{$wst_column_name}" ids="additionals-wstv-{$wst_column_position}-{$wst_id}" factory="staticwqkms" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" year="{dc:date-format('yyyy', $start_time)}" />
       </dc:call-macro>
     </dc:macro>
 
     <dc:macro name="basedata_7_waterlevels_wq">
       <dc:call-macro name="basedata_7_macro">
-        <column name="{$wst_column_name}"
-                ids="additionals-wstv-{$wst_column_position}-{$wst_id}"
-                factory="wqinterpol" target_out="{$out}"
-                info="{$info} [km {$deffrom} - {$defto}]"/>
+        <column name="{$wst_column_name}" ids="additionals-wstv-{$wst_column_position}-{$wst_id}" factory="wqinterpol" target_out="{$out}" info="{$info} [km {$deffrom} - {$defto}]" />
       </dc:call-macro>
     </dc:macro>
 
@@ -1503,158 +1584,181 @@
     <!-- prototypes -->
 
     <dc:macro name="discharge-curve-prototype">
-        <computed_discharge_curve>
-          <dc:call-macro name="discharge_table_gauge"/>
-          <dc:call-macro name="mainvalues"/>
-        </computed_discharge_curve>
-        <dc:call-macro name="historical_discharge_curve"/>
-        <dc:call-macro name="basedata_0_wq"/>
-        <dc:call-macro name="basedata_1_additionals_wq"/>
-        <dc:call-macro name="basedata_2_fixations_wq"/>
-        <dc:call-macro name="basedata_3_officials_wq"/>
-        <dc:call-macro name="basedata_4_heightmarks-points_wq"/>
-        <dc:call-macro name="basedata_5_flood-protections_wq"/>
-        <minfo>
-          <dc:call-macro name="sqrelations"/>
-          <dc:call-macro name="basedata_7_waterlevels_wq"/>
-        </minfo>
+      <computed_discharge_curve>
+        <dc:call-macro name="discharge_table_gauge" />
+        <dc:call-macro name="mainvalues" />
+      </computed_discharge_curve>
+      <dc:call-macro name="historical_discharge_curve" />
+      <dc:call-macro name="basedata_0_wq" />
+      <dc:call-macro name="basedata_1_additionals_wq" />
+      <dc:call-macro name="basedata_2_fixations_wq" />
+      <dc:call-macro name="basedata_3_officials_wq" />
+      <dc:call-macro name="basedata_4_heightmarks-points_wq" />
+      <dc:call-macro name="basedata_5_flood-protections_wq" />
+      <minfo>
+        <dc:call-macro name="sqrelations" />
+        <dc:call-macro name="basedata_7_waterlevels_wq" />
+      </minfo>
     </dc:macro>
 
     <dc:macro name="discharge-curve-user-prototype">
-      <dc:call-macro name="waterlevels-user"/>
-      <dc:call-macro name="computed-discharge-curve"/>
+      <dc:call-macro name="waterlevels-user" />
+      <dc:call-macro name="computed-discharge-curve" />
       <!-- TODO: macro for discharge longitudinal section -->
-      <dc:call-macro name="fix-wq-curve"/>
+      <dc:call-macro name="fix-wq-curve" />
       <!-- TODO: own macro for Vollmer-curve (extract from fix-wq-curve and waterlevels-user) -->
-      <dc:call-macro name="extreme-wq-curve"/>
+      <dc:call-macro name="extreme-wq-curve" />
       <minfo>
-        <dc:call-macro name="sqrelations_user"/>
+        <dc:call-macro name="sqrelations_user" />
       </minfo>
     </dc:macro>
 
     <dc:macro name="longitudinal-section-prototype">
-      <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_3_officials"/>
-      <dc:call-macro name="basedata_4_heightmarks-points"/>
-      <dc:call-macro name="basedata_5_flood-protections"/>
-      <dc:call-macro name="annotations_per_type"/>
+      <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_3_officials" />
+      <dc:call-macro name="basedata_4_heightmarks-points" />
+      <dc:call-macro name="basedata_5_flood-protections" />
+      <dc:call-macro name="annotations_per_type" />
       <minfo>
-          <fixanalysis>
-            <dc:call-macro name="basedata_6_delta_w"/>
-            <dc:call-macro name="basedata_7_waterlevels"/>
-          </fixanalysis>
-          <dc:call-macro name="sedimentloads"/>
-          <dc:call-macro name="densities"/>
-          <dc:call-macro name="minfo-heights"/>
-          <dc:call-macro name="sounding-width"/>
-          <dc:call-macro name="morph_width"/>
-          <dc:call-macro name="porosities"/>
-          <flow_velocities>
-            <dc:call-macro name="flow_velocity_measurements"/>
-            <dc:call-macro name="flow_velocity_models"/>
-          </flow_velocities>
+        <fixanalysis>
+          <dc:call-macro name="basedata_6_delta_w" />
+          <dc:call-macro name="basedata_7_waterlevels" />
+        </fixanalysis>
+        <dc:call-macro name="sedimentloads" />
+        <dc:call-macro name="densities" />
+        <dc:call-macro name="minfo-heights" />
+        <dc:call-macro name="sounding-width" />
+        <dc:call-macro name="morph_width" />
+        <dc:call-macro name="porosities" />
+        <flow_velocities>
+          <dc:call-macro name="flow_velocity_measurements" />
+          <dc:call-macro name="flow_velocity_models" />
+        </flow_velocities>
       </minfo>
+
+      <sinfo>
+        <sinfo_predefined_flowdepths>
+          <dc:call-macro name="sinfo_predefined_flowdepth-m" />
+        </sinfo_predefined_flowdepths>
+
+        <sinfo_collisions>
+          <dc:call-macro name="sinfo_collisions" />
+        </sinfo_collisions>
+
+        <sinfo_predefined_channel>
+          <dc:call-macro name="sinfo_predefined_channel" />
+        </sinfo_predefined_channel>
+
+        <sinfo_infrastructure>
+          <dc:call-macro name="sinfo_infrastructure" />
+        </sinfo_infrastructure>
+
+        <sinfo_predefined_tkh>
+          <dc:call-macro name="sinfo_predefined_tkh-berechnung" />
+          <dc:call-macro name="sinfo_predefined_tkh-messung" />
+        </sinfo_predefined_tkh>
+
+        <sinfo_predefined_depthevol>
+          <dc:call-macro name="sinfo_predefined_depthevol-aktuell" />
+          <dc:call-macro name="sinfo_predefined_depthevol-etappe" />
+        </sinfo_predefined_depthevol>
+
+      </sinfo>
     </dc:macro>
 
     <dc:macro name="longitudinal-section-user-prototype">
+      <dc:comment> SINFO </dc:comment>
+      <dc:call-macro name="sinfo_flowdepths" />
+      <dc:call-macro name="sinfo_flowdepths_minmax" />
+      <dc:call-macro name="sinfo_flow_depth_development" />
+      <dc:call-macro name="sinfo_tkh" />
+      <dc:call-macro name="sinfo_collision" />
+      <dc:call-macro name="sinfo_flood_duration" />
+
       <dc:comment> WINFO/DIFF/FIX </dc:comment>
-      <dc:call-macro name="longitudinal"/>
-      <dc:call-macro name="differences"/>
-      <dc:call-macro name="waterlevels-discharge"/>
-      <dc:call-macro name="longitudinal-section-fix"/>
-      <dc:call-macro name="longitudinal-section-fix-vollmer"/>
+      <dc:call-macro name="longitudinal" />
+      <dc:call-macro name="differences" />
+      <dc:call-macro name="waterlevels-discharge" />
+      <dc:call-macro name="longitudinal-section-fix" />
+      <dc:call-macro name="longitudinal-section-fix-vollmer" />
+
       <dc:comment> MINFO </dc:comment>
-      <dc:call-macro name="middle_bedheights"/>
-      <dc:call-macro name="bedheight_differences"/>
-      <dc:call-macro name="bedquality"/>
-      <dc:call-macro name="flow-velocity"/>
-      <dc:call-macro name="sediment-load"/>
+      <dc:call-macro name="middle_bedheights" />
+      <dc:call-macro name="bedheight_differences" />
+      <dc:call-macro name="bedquality" />
+      <dc:call-macro name="flow-velocity" />
+      <dc:call-macro name="sediment-load" />
     </dc:macro>
 
-
     <!-- porosities -->
     <dc:macro name="porosities">
       <porosities>
-      <dc:context>
-        <dc:statement>
+        <dc:context>
+          <dc:statement>
             SELECT DISTINCT
-                p.id          AS pid,
-                p.description AS description,
-                d.lower        AS depth_lower,
-                d.upper        AS depth_upper,
-                p.description  || '&lt;BR&gt;' ||
-                'Tiefe: ' || d.lower || ' - ' || d.upper
-                    || ' cm &lt;BR&gt;' ||
-                'Zeitraum: ' AS info,
-                t.start_time AS syear,
-                t.stop_time AS eyear
-            FROM     porosity p
-                JOIN depths d ON p.depth_id = d.id
-                JOIN time_intervals t ON p.time_interval_id=t.id
-            WHERE   p.river_id = ${river_id}
+            p.id AS pid,
+            p.description AS description,
+            d.lower AS depth_lower,
+            d.upper AS depth_upper,
+            p.description || '&lt;BR&gt;' ||
+            'Tiefe: ' || d.lower || ' - ' || d.upper
+            || ' cm &lt;BR&gt;' ||
+            'Zeitraum: ' AS info,
+            t.start_time AS syear,
+            t.stop_time AS eyear
+            FROM porosity p
+            JOIN depths d ON p.depth_id = d.id
+            JOIN time_intervals t ON p.time_interval_id=t.id
+            WHERE p.river_id =
+            ${river_id}
             ORDER BY depth_lower, depth_upper
-        </dc:statement>
-        <dc:if test="dc:has-result()">
-          <dc:for-each>
-                  <porosity description="{$depth_lower}-{$depth_upper} cm"
-                   factory="porosity"
-                   target_out="{$out}"
-                   info="{concat($info, dc:date-format('yyyy', $syear),
-                             ' - ', dc:date-format('yyyy', $eyear))}"
-                   ids="{$pid};{$description}" />
-          </dc:for-each>
-        </dc:if>
-      </dc:context>
+          </dc:statement>
+          <dc:if test="dc:has-result()">
+            <dc:for-each>
+              <porosity description="{$depth_lower}-{$depth_upper} cm" factory="porosity" target_out="{$out}" info="{concat($info, dc:date-format('yyyy', $syear),
+                             ' - ', dc:date-format('yyyy', $eyear))}" ids="{$pid};{$description}" />
+            </dc:for-each>
+          </dc:if>
+        </dc:context>
       </porosities>
     </dc:macro>
 
     <dc:macro name="densities">
       <densities>
-      <dc:context>
-        <dc:statement>
+        <dc:context>
+          <dc:statement>
             SELECT DISTINCT
-                sd.id          AS sdid,
-                d.lower        AS depth_lower,
-                d.upper        AS depth_upper,
-                min(sdv.year)  AS year,
-                sd.description || '&lt;BR&gt;Jahr: ' || min(sdv.year) AS info
-            FROM     sediment_density sd
-                JOIN depths d ON sd.depth_id = d.id
-                JOIN sediment_density_values sdv on sdv.sediment_density_id = sd.id
-            WHERE   sd.river_id = ${river_id}
+            sd.id AS sdid,
+            d.lower AS depth_lower,
+            d.upper AS depth_upper,
+            min(sdv.year) AS year,
+            sd.description || '&lt;BR&gt;Jahr: ' || min(sdv.year) AS info
+            FROM sediment_density sd
+            JOIN depths d ON sd.depth_id = d.id
+            JOIN sediment_density_values sdv on sdv.sediment_density_id = sd.id
+            WHERE sd.river_id = ${river_id}
             GROUP BY sd.id, sd.description, d.upper, d.lower
-            ORDER BY year, depth_lower, depth_upper
-        </dc:statement>
-        <dc:if test="dc:has-result()">
-          <dc:for-each>
-                  <density description="{$depth_lower}-{$depth_upper} cm"
-                   factory="sedimentdensity"
-                   target_out="{$out}"
-                   info="{$info}"
-                   ids="{$sdid}" />
-          </dc:for-each>
-        </dc:if>
-      </dc:context>
+            ORDER BY
+            year, depth_lower, depth_upper
+          </dc:statement>
+          <dc:if test="dc:has-result()">
+            <dc:for-each>
+              <density description="{$depth_lower}-{$depth_upper} cm" factory="sedimentdensity" target_out="{$out}" info="{$info}" ids="{$sdid}" />
+            </dc:for-each>
+          </dc:if>
+        </dc:context>
       </densities>
     </dc:macro>
 
     <!-- sediment load -->
     <dc:macro name="load">
-      <year description="{$timespan}"
-            factory="sedimentload"
-            target_out="{$out}"
-            info="{$info}"
-            ids="{$slid};{$fraction};{$timespan};{$kind}" />
+      <year description="{$timespan}" factory="sedimentload" target_out="{$out}" info="{$info}" ids="{$slid};{$fraction};{$timespan};{$kind}" />
     </dc:macro>
 
     <dc:macro name="load_ls">
-      <year description="{$timespan}"
-            factory="sedimentload_ls"
-            target_out="{$out}"
-            info="{$info}"
-            ids="{$slid};{$timespan};{$kind}" />
+      <year description="{$timespan}" factory="sedimentload_ls" target_out="{$out}" info="{$info}" ids="{$slid};{$timespan};{$kind}" />
     </dc:macro>
 
     <dc:macro name="loads">
@@ -1663,28 +1767,24 @@
                         dc:date-format('yyyy', $sqstop))">
           <sq_time description="{dc:group-key()}">
             <dc:group expr="$fraction">
-              <dc:variable name="fraction_name"
-                           expr="concat('${', dc:group-key(), '}')"/>
+              <dc:variable name="fraction_name" expr="concat('${', dc:group-key(), '}')" />
               <fraction description="{$fraction_name}">
                 <dc:for-each>
                   <dc:choose>
                     <dc:when test="string-length(dc:get('endyear')) = 0">
-                      <dc:variable name="timespan" type="string"
-                                   expr="dc:date-format('yyyy', $startyear)"/>
+                      <dc:variable name="timespan" type="string" expr="dc:date-format('yyyy', $startyear)" />
                     </dc:when>
                     <dc:otherwise>
-                      <dc:variable name="timespan" type="string"
-                                   expr="concat(dc:date-format('yyyy',
+                      <dc:variable name="timespan" type="string" expr="concat(dc:date-format('yyyy',
                                          $startyear), '-',
-                                         dc:date-format('yyyy', $endyear))"/>
+                                         dc:date-format('yyyy', $endyear))" />
                     </dc:otherwise>
                   </dc:choose>
                   <dc:if test="$kind = 'official'">
-                    <dc:variable name="info" type="string"
-                                 expr="concat('Amtliche Epoche&lt;BR&gt;',
-                                       dc:get('info'))"/>
+                    <dc:variable name="info" type="string" expr="concat('Amtliche Epoche&lt;BR&gt;',
+                                       dc:get('info'))" />
                   </dc:if>
-                  <dc:macro-body/>
+                  <dc:macro-body />
                 </dc:for-each>
               </fraction>
             </dc:group>
@@ -1696,42 +1796,42 @@
     <dc:macro name="sedimentloads-filter">
       <years>
         <dc:filter expr="string-length(dc:get('endyear')) = 0 and
-                         $kind != 'official'" >
-          <dc:macro-body/>
+                         $kind != 'official'">
+          <dc:macro-body />
         </dc:filter>
       </years>
       <epochs>
         <dc:filter expr="string-length(dc:get('endyear')) &gt; 0 and
-                         $kind != 'official'" >
-          <dc:macro-body/>
+                         $kind != 'official'">
+          <dc:macro-body />
         </dc:filter>
       </epochs>
       <off_epochs>
-        <dc:filter expr="$kind = 'official'" >
-          <dc:macro-body/>
+        <dc:filter expr="$kind = 'official'">
+          <dc:macro-body />
         </dc:filter>
       </off_epochs>
     </dc:macro>
 
     <dc:macro name="sedimentloads">
       <sedimentloads>
-        <dc:call-macro name="annotations_sediment_load_ls"/>
+        <dc:call-macro name="annotations_sediment_load_ls" />
         <measurement_stations>
           <dc:context>
-            <dc:call-macro name="sedimentload_stations_statement"/>
+            <dc:call-macro name="sedimentload_stations_statement" />
             <dc:call-macro name="sedimentloads-filter">
               <dc:call-macro name="loads">
-                <dc:call-macro name="load"/>
+                <dc:call-macro name="load" />
               </dc:call-macro>
             </dc:call-macro>
           </dc:context>
         </measurement_stations>
         <sediment_load_ls>
           <dc:context>
-            <dc:call-macro name="sedimentload_ls_statement"/>
+            <dc:call-macro name="sedimentload_ls_statement" />
             <dc:call-macro name="sedimentloads-filter">
               <dc:call-macro name="loads">
-                <dc:call-macro name="load_ls"/>
+                <dc:call-macro name="load_ls" />
               </dc:call-macro>
             </dc:call-macro>
           </dc:context>
@@ -1742,69 +1842,73 @@
     <dc:macro name="sedimentload_stations_statement">
       <dc:statement>
         SELECT DISTINCT
-            sl.id          AS slid,
-            slk.kind       AS kind,
-            ti.start_time  AS startyear,
-            ti.stop_time   AS endyear,
-            sq.start_time  AS sqstart,
-            sq.stop_time   AS sqstop,
-            sq.id          AS sqid,
-            gf.name        AS fraction,
-            sl.description  || '&lt;BR&gt;' ||
-                'Fraktion: ' || gf.lower || ' bis ' || gf.upper ||
-                ' mm&lt;BR&gt;Einheit: t/a' AS info
-        FROM     sediment_load sl
-            JOIN sediment_load_kinds slk ON slk.id = sl.kind
-            JOIN sediment_load_values slv
-                ON sl.id = slv.sediment_load_id
-            JOIN measurement_station ms
-                ON ms.id = slv.measurement_station_id
-            JOIN ranges ra ON ms.range_id = ra.id
-            JOIN rivers r ON ra.river_id = r.id
-            JOIN time_intervals ti ON sl.time_interval_id = ti.id
-            LEFT JOIN time_intervals sq ON sl.sq_time_interval_id = sq.id
-            JOIN grain_fraction gf ON gf.id = sl.grain_fraction_id
+        sl.id AS slid,
+        slk.kind AS kind,
+        ti.start_time AS startyear,
+        ti.stop_time AS endyear,
+        sq.start_time AS sqstart,
+        sq.stop_time AS sqstop,
+        sq.id AS sqid,
+        gf.name AS fraction,
+        sl.description || '&lt;BR&gt;' ||
+        'Fraktion: ' || gf.lower || ' bis ' || gf.upper ||
+        ' mm&lt;BR&gt;Einheit: t/a' AS info
+        FROM sediment_load sl
+        JOIN sediment_load_kinds slk ON slk.id = sl.kind
+        JOIN
+        sediment_load_values slv
+        ON sl.id = slv.sediment_load_id
+        JOIN measurement_station ms
+        ON ms.id =
+        slv.measurement_station_id
+        JOIN ranges ra ON ms.range_id = ra.id
+        JOIN rivers r ON ra.river_id = r.id
+        JOIN time_intervals ti ON sl.time_interval_id = ti.id
+        LEFT JOIN time_intervals sq ON sl.sq_time_interval_id = sq.id
+        JOIN grain_fraction gf ON gf.id = sl.grain_fraction_id
         WHERE r.id = ${river_id}
-            AND CASE WHEN r.km_up = 1 AND ra.b IS NOT NULL
-            THEN ra.b ELSE ra.a END BETWEEN ${fromkm} AND ${tokm}
-            ORDER BY sqstart DESC, sqstop DESC,
-                fraction, startyear DESC, endyear DESC
+        AND CASE
+        WHEN r.km_up = 1 AND ra.b IS NOT NULL
+        THEN ra.b ELSE ra.a END BETWEEN ${fromkm} AND ${tokm}
+        ORDER BY sqstart DESC, sqstop DESC,
+        fraction, startyear DESC, endyear DESC
       </dc:statement>
     </dc:macro>
 
     <dc:macro name="sedimentload_ls_statement">
       <dc:statement>
         SELECT DISTINCT
-            sl.id          AS slid,
-            slk.kind       AS kind,
-            ti.start_time  AS startyear,
-            ti.stop_time   AS endyear,
-            sq.start_time  AS sqstart,
-            sq.stop_time   AS sqstop,
-            sq.id          AS sqid,
-            gf.name        AS fraction,
-            sl.description  || '&lt;BR&gt;' ||
-                'Fraktion: ' || gf.lower || ' bis ' || gf.upper ||
-                ' mm&lt;BR&gt;Einheit: ' || u.name AS info
-        FROM     sediment_load_ls sl
-            JOIN sediment_load_kinds slk ON slk.id = sl.kind
-            JOIN rivers r ON sl.river_id = r.id
-            JOIN sediment_load_ls_values slv
-                ON sl.id = slv.sediment_load_ls_id
-            JOIN time_intervals ti ON sl.time_interval_id = ti.id
-            LEFT JOIN time_intervals sq ON sl.sq_time_interval_id = sq.id
-            JOIN grain_fraction gf ON gf.id = sl.grain_fraction_id
-            JOIN units u ON sl.unit_id = u.id
-        WHERE   r.id = ${river_id}
-            AND slv.station BETWEEN ${fromkm} AND ${tokm}
-        ORDER BY sqstart DESC, sqstop DESC,
-            fraction, startyear DESC, endyear DESC
+        sl.id AS slid,
+        slk.kind AS kind,
+        ti.start_time AS startyear,
+        ti.stop_time AS endyear,
+        sq.start_time AS sqstart,
+        sq.stop_time AS sqstop,
+        sq.id AS sqid,
+        gf.name AS fraction,
+        sl.description || '&lt;BR&gt;' ||
+        'Fraktion: ' || gf.lower || ' bis ' || gf.upper ||
+        ' mm&lt;BR&gt;Einheit: ' || u.name AS info
+        FROM sediment_load_ls sl
+        JOIN sediment_load_kinds slk ON slk.id = sl.kind
+        JOIN rivers r ON sl.river_id = r.id
+        JOIN sediment_load_ls_values slv
+        ON sl.id = slv.sediment_load_ls_id
+        JOIN time_intervals ti ON sl.time_interval_id = ti.id
+        LEFT JOIN time_intervals sq ON sl.sq_time_interval_id = sq.id
+        JOIN grain_fraction gf ON gf.id = sl.grain_fraction_id
+        JOIN units u ON sl.unit_id = u.id
+        WHERE r.id = ${river_id}
+        AND slv.station BETWEEN ${fromkm} AND ${tokm}
+        ORDER BY sqstart
+        DESC, sqstop DESC,
+        fraction, startyear DESC, endyear DESC
       </dc:statement>
     </dc:macro>
 
     <!-- annotations -->
     <dc:macro name="annotations">
-      <annotation factory="annotations" ids="{$river_id}" target_out="{$out}"/>
+      <annotation factory="annotations" ids="{$river_id}" target_out="{$out}" />
     </dc:macro>
 
     <dc:macro name="annotations_per_type">
@@ -1812,14 +1916,12 @@
         <dc:context>
           <all_annotations factory="annotations" ids="{$river_id}" target_out="{$out}" />
           <dc:statement>
-            SELECT id   AS anno_id,
-                   name AS anno_description
+            SELECT id AS anno_id,
+            name AS anno_description
             FROM annotation_types
           </dc:statement>
           <dc:for-each>
-            <annotation name="{$anno_description}"
-                        factory="annotations" target_out="{$out}"
-                        ids="{$river_id}:{$anno_description}"/>
+            <annotation name="{$anno_description}" factory="annotations" target_out="{$out}" ids="{$river_id}:{$anno_description}" />
           </dc:for-each>
         </dc:context>
       </annotations>
@@ -1829,15 +1931,13 @@
       <sources_sinks>
         <dc:context>
           <dc:statement>
-            SELECT id   AS anno_id,
-                   name AS anno_description
+            SELECT id AS anno_id,
+            name AS anno_description
             FROM annotation_types
-	    WHERE name LIKE 'Quelle %' OR name LIKE 'Senke %'
+            WHERE name LIKE 'Quelle %' OR name LIKE 'Senke %'
           </dc:statement>
           <dc:for-each>
-            <annotation name="{$anno_description}"
-                        factory="annotations" target_out="{$out}"
-                        ids="{$river_id}:{$anno_description}"/>
+            <annotation name="{$anno_description}" factory="annotations" target_out="{$out}" ids="{$river_id}:{$anno_description}" />
           </dc:for-each>
         </dc:context>
       </sources_sinks>
@@ -1860,37 +1960,39 @@
     <dc:macro name="minfo-heights-diff">
       <dc:context>
         <dc:statement>
-            WITH sta
-                 AS (SELECT bhs.id,
-                            bhs.description,
-                            bhsv.station,
-                            bhs.year
-                     FROM   bed_height bhs
-                            JOIN bed_height_values bhsv
-                                ON bhsv.bed_height_id = bhs.id
-                     WHERE  bhs.river_id = ${river_id}
-                     AND bhsv.station BETWEEN ${fromkm} AND ${tokm}),
-                 csta
-                 AS (SELECT b1.id          AS b1id,
-                            b1.description AS b1desc,
-                            b1.year        AS b1year,
-                            b2.id          AS b2id,
-                            b2.description AS b2desc,
-                            b2.year        AS b2year
-                     FROM   sta b1
-                            JOIN sta b2
-                              ON b1.station = b2.station
-                              AND b1.id &lt;&gt; b2.id
-                              AND (b1.year &gt; b2.year OR b1.year IS NULL))
-            SELECT DISTINCT b1id, b1desc, b1year,
-                   b2id, b2desc, b2year
-            FROM   csta
-            ORDER BY b1desc, b2desc
+          WITH sta
+          AS (SELECT bhs.id,
+          bhs.description,
+          bhsv.station,
+          bhs.year
+          FROM bed_height bhs
+          JOIN bed_height_values bhsv
+          ON bhsv.bed_height_id = bhs.id
+          WHERE bhs.river_id = ${river_id}
+          AND bhsv.station BETWEEN ${fromkm} AND ${tokm}),
+          csta
+          AS (SELECT b1.id AS b1id,
+          b1.description AS b1desc,
+          b1.year AS b1year,
+          b2.id AS b2id,
+          b2.description AS b2desc,
+          b2.year AS b2year
+          FROM sta b1
+          JOIN sta b2
+          ON
+          b1.station = b2.station
+          AND b1.id &lt;&gt; b2.id
+          AND (b1.year &gt; b2.year OR b1.year IS NULL))
+          SELECT
+          DISTINCT b1id, b1desc, b1year,
+          b2id, b2desc, b2year
+          FROM csta
+          ORDER BY b1desc, b2desc
         </dc:statement>
         <dc:if test="dc:has-result()">
           <bedheights>
-            <dc:call-macro name="bed-heights-single-diff"/>
-            <dc:call-macro name="bed-heights-epoch-diff"/>
+            <dc:call-macro name="bed-heights-single-diff" />
+            <dc:call-macro name="bed-heights-epoch-diff" />
           </bedheights>
         </dc:if>
       </dc:context>
@@ -1899,7 +2001,7 @@
     <dc:macro name="bed-heights-single-diff">
       <dc:filter expr="not(contains(dc:lowercase($b1desc), 'epoche'))">
         <years>
-          <dc:call-macro name="minfo-heights-diff-tree"/>
+          <dc:call-macro name="minfo-heights-diff-tree" />
         </years>
       </dc:filter>
     </dc:macro>
@@ -1907,7 +2009,7 @@
     <dc:macro name="bed-heights-epoch-diff">
       <dc:filter expr="contains(dc:lowercase($b1desc), 'epoche')">
         <epochs>
-          <dc:call-macro name="minfo-heights-diff-tree"/>
+          <dc:call-macro name="minfo-heights-diff-tree" />
         </epochs>
       </dc:filter>
     </dc:macro>
@@ -1918,23 +2020,11 @@
           <dc:for-each>
             <dc:choose>
               <dc:when test="dc:group-key() = $b1year">
-                <height factory="bedheight"
-                        target_out="{$out}"
-                        ids="bedheight-single-{$b1id}#bedheight-single-{$b2id}"
-                        info="{$b1desc}#{$b2desc}"
-                        description="{$b1desc} - {$b2desc}"/>
+                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b1id}-{$b1desc}#bedheight-single-{$b2id}-{$b2desc}" info="{$b1desc}#{$b2desc}" description="{$b1desc} - {$b2desc}" />
               </dc:when>
               <dc:when test="dc:group-key() = 'sonstige'">
-                <height factory="bedheight"
-                        target_out="{$out}"
-                        ids="bedheight-single-{$b1id}#bedheight-single-{$b2id}"
-                        info="{$b1desc}#{$b2desc}"
-                        description="{$b1desc} - {$b2desc}"/>
-                <height factory="bedheight"
-                        target_out="{$out}"
-                        ids="bedheight-single-{$b2id}#bedheight-single-{$b1id}"
-                        info="{$b2desc}#{$b1desc}"
-                        description="{$b2desc} - {$b1desc}"/>
+                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b1id}-{$b1desc}#bedheight-single-{$b2id}-{$b2desc}" info="{$b1desc}#{$b2desc}" description="{$b1desc} - {$b2desc}" />
+                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b2id}-{$b1desc}#bedheight-single-{$b1id}-{$b2desc}" info="{$b2desc}#{$b1desc}" description="{$b2desc} - {$b1desc}" />
               </dc:when>
             </dc:choose>
           </dc:for-each>
@@ -1944,30 +2034,79 @@
 
     <dc:macro name="minfo-heights">
       <bedheights>
-        <dc:call-macro name="bed-heights-single"/>
-        <dc:call-macro name="bed-heights-epoch"/>
+        <dc:call-macro name="bed-heights-single" />
+        <dc:call-macro name="bed-heights-epoch" />
       </bedheights>
     </dc:macro>
 
-    <dc:macro name="bed-heights-factory">
+    <!-- Show all three MW, TL, and KL bedheights -->
+    <dc:macro name="bed-heights-factory_MW_TW_KL">
       <dc:for-each>
-        <height factory="bedheight"
-                target_out="{$out}"
-                ids="bedheight-single-{$bedh_id}-{$bedh_year}"
-                info="{$info}"
-                description="{$bedh_descr}"/>
+        <dc:if test="$bedh_height_count > 0">
+          <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$bedh_id}-{$bedh_year}-MW-{$bedh_descr}" info="{$info}" description="MW-{$bedh_descr}" />
+        </dc:if>
+        <dc:if test="$bedh_min_count > 0">
+          <height factory="bedheight" target_out="{$out}" ids="bedheight-singleMin-{$bedh_id}-{$bedh_year}-TW-{$bedh_descr}" info="{$info}" description="TW-{$bedh_descr}" />
+        </dc:if>
+        <dc:if test="$bedh_max_count > 0">
+          <height factory="bedheight" target_out="{$out}" ids="bedheight-singleMax-{$bedh_id}-{$bedh_year}-KL-{$bedh_descr}" info="{$info}" description="KL-{$bedh_descr}" />
+        </dc:if>
+      </dc:for-each>
+    </dc:macro>
+
+    <!-- Show only MW bed height and name it in a neutral way -->
+    <dc:macro name="bed-heights-factory_MW">
+      <dc:for-each>
+        <dc:if test="$bedh_height_count > 0">
+          <!-- REMARK: addition 'yaer' attribute is used by intelligent datacage filter of SINFO -->
+          <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$bedh_id}-{$bedh_year}-{$bedh_descr}" info="{$info}" description="{$bedh_descr}" year="{$bedh_year}" />
+        </dc:if>
       </dc:for-each>
     </dc:macro>
 
     <dc:macro name="bed-heights-single">
       <single>
         <dc:context>
-          <dc:call-macro name="bed-heights-statement"/>
-          <dc:filter expr="not(contains($bedh_descr, 'Epoche'))">
+          <dc:call-macro name="bed-heights-statement" />  
+          <dc:if test="dc:has-result()">
+            <dc:group expr="dc:coalesce($bedh_year, 'sonstige')">
+              <heights name="{dc:group-key()}" description="{dc:group-key()}">
+                <dc:call-macro name="bed-heights-factory_MW_TW_KL" />
+              </heights>
+            </dc:group>
+          </dc:if>
+        </dc:context>
+      </single>
+    </dc:macro>
+
+    <!-- Show bed heights that have MW values with a neutral name -->
+    <dc:macro name="bed-heights-single-MW">
+      <single>
+        <dc:context>
+          <dc:call-macro name="bed-heights-statement" />
+          <dc:filter expr="$bedh_height_count">
             <dc:if test="dc:has-result()">
               <dc:group expr="dc:coalesce($bedh_year, 'sonstige')">
-                <heights name="{dc:group-key()}">
-                  <dc:call-macro name="bed-heights-factory"/>
+                <heights name="{dc:group-key()}" description="{dc:group-key()}">
+                  <dc:call-macro name="bed-heights-factory_MW" />
+                </heights>
+              </dc:group>
+            </dc:if>
+          </dc:filter>
+        </dc:context>
+      </single>
+    </dc:macro>
+
+    <!-- Show bed heights that have KL and TW values with a neutral name -->
+    <dc:macro name="bed-heights-single-KL_TW">
+      <single>
+        <dc:context>
+          <dc:call-macro name="bed-heights-statement" />
+          <dc:filter expr="$bedh_max_count > 0 and $bedh_min_count > 0">
+            <dc:if test="dc:has-result()">
+              <dc:group expr="dc:coalesce($bedh_year, 'sonstige')">
+                <heights name="{dc:group-key()}" description="{dc:group-key()}">
+                  <dc:call-macro name="bed-heights-factory_MW" />
                 </heights>
               </dc:group>
             </dc:if>
@@ -1979,9 +2118,9 @@
     <dc:macro name="bed-heights-epoch">
       <epoch>
         <dc:context>
-          <dc:call-macro name="bed-heights-statement"/>
+          <dc:call-macro name="bed-heights-statement" />
           <dc:filter expr="contains($bedh_descr, 'Epoche')">
-            <dc:call-macro name="bed-heights-factory"/>
+            <dc:call-macro name="bed-heights-factory_MW_TW_KL" />
           </dc:filter>
         </dc:context>
       </epoch>
@@ -1989,20 +2128,16 @@
 
     <dc:macro name="sounding-width-factory">
       <dc:for-each>
-        <height factory="bedheight"
-                target_out="{$out}"
-                ids="bedheight-soundings-{$bedh_id}-{$bedh_year}"
-                info="{$info}"
-                description="{$bedh_descr}"/>
+        <height factory="bedheight" target_out="{$out}" ids="bedheight-soundings-{$bedh_id}-{$bedh_year}-{$bedh_descr}" info="{$info}" description="{$bedh_descr}" />
       </dc:for-each>
     </dc:macro>
 
     <dc:macro name="sounding-width">
       <dc:context>
-        <dc:call-macro name="bed-heights-statement"/>
+        <dc:call-macro name="bed-heights-statement" />
         <dc:if test="dc:has-result()">
           <soundings_width>
-            <dc:call-macro name="sounding-width-factory"/>
+            <dc:call-macro name="sounding-width-factory" />
           </soundings_width>
         </dc:if>
       </dc:context>
@@ -2010,33 +2145,43 @@
 
     <dc:macro name="sounding-width-recommendations">
       <dc:context>
-        <dc:call-macro name="bed-heights-statement"/>
+        <dc:call-macro name="bed-heights-statement" />
         <dc:filter expr="dc:contains($diffids, concat(';', $bedh_descr, ']'))">
-          <dc:call-macro name="sounding-width-factory"/>
+          <dc:call-macro name="sounding-width-factory" />
         </dc:filter>
       </dc:context>
     </dc:macro>
 
     <dc:macro name="bed-heights-statement">
       <dc:statement>
-        SELECT bhs.id       AS bedh_id,
-            bhs.year        AS bedh_year,
-            bhs.description AS bedh_descr,
-            bhs.description || '&lt;BR&gt;Jahr: ' || bhs.year ||
-            '&lt;BR&gt;Aufnahmeart: ' || bht.name ||
-            '&lt;BR&gt;Lagesystem: ' || ls.name ||
-            '&lt;BR&gt;Höhensystem: ' || cur_em.name ||
-            '&lt;BR&gt;ursprüngliches Höhensystem: ' || old_em.name ||
-            '&lt;BR&gt;Strecke: ' || round(r.a, 1) || '-' || round(r.b, 1) ||
-            '&lt;BR&gt;Auswerter: ' || bhs.evaluation_by AS info
+        SELECT bhs.id AS bedh_id,
+        bhs.year AS bedh_year,
+        bhs.description AS bedh_descr,
+        bhs.description || '&lt;BR&gt;Jahr: ' || bhs.year ||
+        '&lt;BR&gt;Aufnahmeart: ' || bht.name ||
+        '&lt;BR&gt;Lagesystem: ' || ls.name ||
+        '&lt;BR&gt;Höhensystem: ' || cur_em.name ||
+        '&lt;BR&gt;ursprüngliches Höhensystem: ' || old_em.name ||
+        '&lt;BR&gt;Strecke: ' || round(r.a, 1) || '-' || round(r.b, 1) ||
+        '&lt;BR&gt;Auswerter: ' || bhs.evaluation_by AS info,
+        COALESCE(bhv.height_count,0) AS bedh_height_count,
+        COALESCE(bhv.min_count,0) AS bedh_min_count,
+        COALESCE(bhv.max_count,0) AS bedh_max_count
         FROM bed_height bhs
-            JOIN bed_height_type bht ON bht.id = bhs.type_id
-            JOIN location_system ls ON ls.id = location_system_id
-            JOIN elevation_model cur_em ON cur_em.id = cur_elevation_model_id
-            LEFT JOIN elevation_model old_em
-                ON old_em.id = old_elevation_model_id
-            LEFT JOIN ranges r ON r.id = range_id
-        WHERE bhs.river_id = ${river_id}
+        JOIN bed_height_type bht ON bht.id = bhs.type_id
+        JOIN location_system ls ON ls.id = location_system_id
+        JOIN elevation_model cur_em ON cur_em.id = cur_elevation_model_id
+        LEFT JOIN
+        elevation_model old_em
+        ON old_em.id = old_elevation_model_id
+        LEFT JOIN ranges r ON r.id = range_id
+        LEFT JOIN (SELECT bed_height_id, COUNT(height) AS height_count, COUNT(min_height) AS min_count, COUNT(max_height) AS max_count
+        FROM bed_height_values
+        WHERE (station BETWEEN (${fromkm}-0.0001) AND (${tokm}+0.0001))
+        GROUP BY bed_height_id
+        ) bhv ON bhs.id = bhv.bed_height_id
+        WHERE bhs.river_id =
+        ${river_id}
       </dc:statement>
     </dc:macro>
 
@@ -2044,12 +2189,12 @@
     <dc:macro name="flow_velocity_models">
       <dc:context>
         <dc:statement>
-          SELECT fvm.id             AS fvmid,
-                 fvm.description    AS fvmd,
-                 dz.gauge_name      AS gauge,
-                 dz.value           AS q,
-                 dz.upper_discharge AS upperQ,
-                 dz.lower_discharge AS lowerQ
+          SELECT fvm.id AS fvmid,
+          fvm.description AS fvmd,
+          dz.gauge_name AS gauge,
+          dz.value AS q,
+          dz.upper_discharge AS upperQ,
+          dz.lower_discharge AS lowerQ
           FROM flow_velocity_model fvm
           JOIN discharge_zone dz ON dz.id = fvm.discharge_zone_id
           WHERE dz.river_id = ${river_id}
@@ -2058,13 +2203,9 @@
         <dc:if test="dc:has-result()">
           <flowvelocitymodel>
             <dc:for-each>
-              <measurement_value name="{$fvmd}"
-                                 ids="{$fvmid}"
-                                 factory="flowvelocitymodel"
-                                 info="{$lowerQ} - {$upperQ}&lt;BR&gt;
+              <measurement_value name="{$fvmd}" ids="{$fvmid}" factory="flowvelocitymodel" info="{$lowerQ} - {$upperQ}&lt;BR&gt;
                                        Pegel {$gauge}&lt;BR&gt;
-                                       Q = {$q} m3/s"
-                                 target_out="{$out}" />
+                                       Q = {$q} m3/s" target_out="{$out}" />
             </dc:for-each>
           </flowvelocitymodel>
         </dc:if>
@@ -2075,8 +2216,8 @@
     <dc:macro name="flow_velocity_measurements">
       <dc:context>
         <dc:statement>
-          SELECT id          AS fvmid,
-                 description AS fvmd
+          SELECT id AS fvmid,
+          description AS fvmd
           FROM flow_velocity_measurements WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
@@ -2088,12 +2229,10 @@
                     SELECT id, description, station, datetime, v, w, q
                     FROM flow_velocity_measure_values
                     WHERE measurements_id = ${fvmid}
-                      AND station BETWEEN ${fromkm} AND ${tokm}
+                    AND station BETWEEN ${fromkm} AND ${tokm}
                   </dc:statement>
                   <dc:for-each>
-                    <measurement_value name="{$description} - {$station} - {$datetime}"
-                                       ids="{$id}"
-                                       factory="flowvelocity" target_out="{$out}" />
+                    <measurement_value name="{$description} - {$station} - {$datetime}" ids="{$id}" factory="flowvelocity" target_out="{$out}" />
                   </dc:for-each>
                 </dc:context>
               </flow_velocity_measurement>
@@ -2106,7 +2245,7 @@
     <dc:macro name="morph_width">
       <dc:context>
         <dc:statement>
-          SELECT id   AS width_id
+          SELECT id AS width_id
           FROM morphologic_width
           WHERE river_id = ${river_id}
         </dc:statement>
@@ -2116,14 +2255,12 @@
               <dc:context>
                 <dc:statement>
                   SELECT min(station) AS from_station,
-                         max(station) AS to_station
+                  max(station) AS to_station
                   FROM morphologic_width_values
                   WHERE morphologic_width_id = ${width_id}
                 </dc:statement>
                 <dc:for-each>
-                  <morphologic-width name="{$from_station} - {$to_station}"
-                                     ids="{$width_id}"
-                                     factory="morph-width" target_out="{$out}" />
+                  <morphologic-width name="{$from_station} - {$to_station}" ids="{$width_id}" factory="morph-width" target_out="{$out}" />
                 </dc:for-each>
               </dc:context>
             </dc:for-each>
@@ -2136,17 +2273,18 @@
       <dc:context>
         <dc:statement>
           SELECT
-            ti.start_time        AS start_time,
-            ti.stop_time         AS stop_time,
-            ms.name              AS station_name,
-            lower(sqv.parameter) AS parameter,
-            sqv.id               AS sqvid,
-            ra.a                 AS station_km
+          ti.start_time AS start_time,
+          ti.stop_time AS stop_time,
+          ms.name AS station_name,
+          lower(sqv.parameter) AS parameter,
+          sqv.id AS sqvid,
+          ra.a AS station_km
           FROM sq_relation sq
           JOIN time_intervals ti ON ti.id = sq.time_interval_id
           JOIN sq_relation_value sqv ON sqv.sq_relation_id = sq.id
           JOIN measurement_station ms ON sqv.measurement_station_id = ms.id
-          JOIN ranges ra ON ms.range_id = ra.id
+          JOIN ranges ra ON ms.range_id =
+          ra.id
           JOIN rivers r ON r.id = ra.river_id
           WHERE r.id = ${river_id}
           ORDER BY start_time, stop_time
@@ -2160,15 +2298,11 @@
                                   $station_name)">
                     <station description="{dc:group-key()}">
                       <dc:for-each>
-                        <dc:variable name="combined_desc"
-                                     expr="concat(dc:date-format('yyyy',
+                        <dc:variable name="combined_desc" expr="concat(dc:date-format('yyyy',
                                            $start_time), ' bis ',
                                            dc:date-format('yyyy',
-                                           $stop_time))"/>
-                        <sqvalue factory="sqrelationdatacage"
-                                 target_out="{$out}"
-                                 ids="{$sqvid};{dc:uppercase($parameter)} - {$station_name}: {$combined_desc}"
-                                 description="{$combined_desc}"/>
+                                           $stop_time))" />
+                        <sqvalue factory="sqrelationdatacage" target_out="{$out}" ids="{$sqvid};{dc:uppercase($parameter)} - {$station_name}: {$combined_desc}" description="{$combined_desc}" />
                       </dc:for-each>
                     </station>
                   </dc:group>
@@ -2182,64 +2316,62 @@
 
     <!-- Floodmap part -->
     <dc:macro name="flood-map-complete">
-      <dc:call-macro name="flood-map-buildings"/>
-      <dc:call-macro name="flood-map-gaugelocations"/>
-      <dc:call-macro name="floodmarks"/>
+      <dc:call-macro name="flood-map-buildings" />
+      <dc:call-macro name="flood-map-gaugelocations" />
+      <dc:call-macro name="floodmarks" />
       <hws>
-        <dc:call-macro name="hwslines"/>
-        <dc:call-macro name="hwspoints"/>
+        <dc:call-macro name="hwslines" />
+        <dc:call-macro name="hwspoints" />
       </hws>
-      <dc:call-macro name="flood-map-routing"/>
+      <dc:call-macro name="flood-map-routing" />
       <hydrboundaries>
-        <dc:call-macro name="flood-map-floodplain"/>
-        <dc:call-macro name="flood-map-hydr-boundaries"/>
+        <dc:call-macro name="flood-map-floodplain" />
+        <dc:call-macro name="flood-map-hydr-boundaries" />
       </hydrboundaries>
-      <dc:call-macro name="flood-map-uesk"/>
+      <dc:call-macro name="flood-map-uesk" />
     </dc:macro>
 
     <dc:macro name="flood-map-routing">
       <route_data>
-        <dc:call-macro name="flood-map-qps"/>
-        <dc:call-macro name="flood-map-fixpoints"/>
-        <dc:call-macro name="flood-map-km"/>
-        <dc:call-macro name="flood-map-riveraxis"/>
+        <dc:call-macro name="flood-map-qps" />
+        <dc:call-macro name="flood-map-fixpoints" />
+        <dc:call-macro name="flood-map-km" />
+        <dc:call-macro name="flood-map-riveraxis" />
       </route_data>
     </dc:macro>
 
     <dc:macro name="flood-map-hydr-boundaries">
       <bfg_model>
-        <dc:call-macro name="flood-map-hydr-boundaries-poly"/>
-        <dc:call-macro name="flood-map-hydr-boundaries-lines"/>
+        <dc:call-macro name="flood-map-hydr-boundaries-poly" />
+        <dc:call-macro name="flood-map-hydr-boundaries-lines" />
       </bfg_model>
-      <dc:call-macro name="flood-map-hydr-boundaries-state"/>
+      <dc:call-macro name="flood-map-hydr-boundaries-state" />
     </dc:macro>
 
     <dc:macro name="flood-map-dem">
       <dems>
         <dc:context>
           <dc:statement>
-            SELECT d.id    AS dem_id,
-                   r.a     AS dem_lower,
-                   r.b     AS dem_upper,
-                   d.name  AS name,
-                   t.start_time AS start_time,
-                   t.stop_time AS stop_time,
-                   'Projektion: ' || d.projection || '&lt;BR&gt;' ||
-                   'Rasterweite: '   || d.resolution || 'm&lt;BR&gt;' ||
-                   'Format: '  || d.format || '&lt;BR&gt;' ||
-                   'Zeitraum: '
-                   AS info
+            SELECT d.id AS dem_id,
+            r.a AS dem_lower,
+            r.b AS dem_upper,
+            d.name AS name,
+            t.start_time AS start_time,
+            t.stop_time AS stop_time,
+            'Projektion: ' || d.projection || '&lt;BR&gt;' ||
+            'Rasterweite: ' || d.resolution || 'm&lt;BR&gt;' ||
+            'Format: ' || d.format || '&lt;BR&gt;' ||
+            'Zeitraum: '
+            AS info
             FROM dem d
-              JOIN ranges r ON d.range_id = r.id
-              LEFT JOIN time_intervals t ON d.time_interval_id = t.id
-              WHERE d.river_id = ${river_id}
-              AND NOT((${tokm} &lt; r.a) or (${fromkm} &gt; r.b))
-            </dc:statement>
-            <dc:for-each>
-            <dem factory="demfactory" target_out="{$out}"
-              ids="{$dem_id}"
-              name="{$name}"
-              info="{$info}{dc:date-format('yyyy', $start_time)} - {dc:date-format('yyyy', $stop_time)}"/>
+            JOIN ranges r ON d.range_id = r.id
+            LEFT JOIN time_intervals t ON d.time_interval_id
+            = t.id
+            WHERE d.river_id = ${river_id}
+            AND NOT((${tokm} &lt; r.a) or (${fromkm} &gt; r.b))
+          </dc:statement>
+          <dc:for-each>
+            <dem factory="demfactory" target_out="{$out}" ids="{$dem_id}" name="{$name}" info="{$info}{dc:date-format('yyyy', $start_time)} - {dc:date-format('yyyy', $stop_time)}" />
           </dc:for-each>
         </dc:context>
       </dems>
@@ -2255,19 +2387,25 @@
 
         <dc:filter expr="$hws_kind=1">
           <dc:if test="dc:has-result()">
-            <Durchlass><dc:call-macro name="ddg_factory"/></Durchlass>
+            <Durchlass>
+              <dc:call-macro name="ddg_factory" />
+            </Durchlass>
           </dc:if>
         </dc:filter>
 
         <dc:filter expr="$hws_kind=2">
           <dc:if test="dc:has-result()">
-            <Damm><dc:call-macro name="ddg_factory"/></Damm>
+            <Damm>
+              <dc:call-macro name="ddg_factory" />
+            </Damm>
           </dc:if>
         </dc:filter>
 
         <dc:filter expr="$hws_kind=3">
           <dc:if test="dc:has-result()">
-            <Graben><dc:call-macro name="ddg_factory"/></Graben>
+            <Graben>
+              <dc:call-macro name="ddg_factory" />
+            </Graben>
           </dc:if>
         </dc:filter>
       </dc:macro>
@@ -2275,7 +2413,7 @@
       <dc:filter expr="$hws_official=1">
         <dc:if test="dc:has-result()">
           <official>
-            <dc:call-macro name="durchlass_damm_graben"/>
+            <dc:call-macro name="durchlass_damm_graben" />
           </official>
         </dc:if>
       </dc:filter>
@@ -2283,7 +2421,7 @@
       <dc:filter expr="$hws_official=0">
         <dc:if test="dc:has-result()">
           <inofficial>
-            <dc:call-macro name="durchlass_damm_graben"/>
+            <dc:call-macro name="durchlass_damm_graben" />
           </inofficial>
         </dc:if>
       </dc:filter>
@@ -2293,15 +2431,15 @@
       <dc:context>
         <dc:statement>
           SELECT DISTINCT
-          name     AS hws_name,
+          name AS hws_name,
           official AS hws_official,
-          kind_id  AS hws_kind
+          kind_id AS hws_kind
           FROM hws_lines
           WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
           <lines>
-            <dc:call-macro name="filter_hws_ddg"/>
+            <dc:call-macro name="filter_hws_ddg" />
           </lines>
         </dc:if>
       </dc:context>
@@ -2311,15 +2449,15 @@
       <dc:context>
         <dc:statement>
           SELECT DISTINCT
-          name     AS hws_name,
+          name AS hws_name,
           official AS hws_official,
-          kind_id  AS hws_kind
+          kind_id AS hws_kind
           FROM hws_points
           WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
           <points>
-            <dc:call-macro name="filter_hws_ddg"/>
+            <dc:call-macro name="filter_hws_ddg" />
           </points>
         </dc:if>
       </dc:context>
@@ -2330,29 +2468,25 @@
         <dc:context>
           <dc:statement>
             SELECT DISTINCT
-              name
+            name
             FROM hydr_boundaries
             WHERE river_id = ${river_id}
-              AND kind = 2
+            AND kind = 2
           </dc:statement>
           <dc:for-each>
-            <line factory="wmshydrboundariesfactory" target_out="{$out}"
-                  ids="{$river_id};{$name};2"
-                  name="{$name}"/>
+            <line factory="wmshydrboundariesfactory" target_out="{$out}" ids="{$river_id};{$name};2" name="{$name}" />
           </dc:for-each>
         </dc:context>
         <dc:context>
           <dc:statement>
             SELECT DISTINCT
-              name
+            name
             FROM hydr_boundaries_poly
             WHERE river_id = ${river_id}
-              AND kind = 2
+            AND kind = 2
           </dc:statement>
           <dc:for-each>
-            <line factory="wmshydrboundariespolyfactory" target_out="{$out}"
-                  ids="{$river_id};{$name};2"
-                  name="{$name}"/>
+            <line factory="wmshydrboundariespolyfactory" target_out="{$out}" ids="{$river_id};{$name};2" name="{$name}" />
           </dc:for-each>
         </dc:context>
       </federal>
@@ -2362,18 +2496,16 @@
       <dc:context>
         <dc:statement>
           SELECT DISTINCT
-            name
+          name
           FROM hydr_boundaries
           WHERE river_id = ${river_id}
-            AND kind = 1
+          AND kind = 1
         </dc:statement>
         <dc:comment> What about all other line kinds?</dc:comment>
         <dc:if test="dc:has-result()">
           <lines>
             <dc:for-each>
-              <line factory="wmshydrboundariesfactory" target_out="{$out}"
-                    ids="{$river_id};{$name};1"
-                    name="{$name}"/>
+              <line factory="wmshydrboundariesfactory" target_out="{$out}" ids="{$river_id};{$name};1" name="{$name}" />
             </dc:for-each>
           </lines>
         </dc:if>
@@ -2385,19 +2517,17 @@
         <dc:context>
           <dc:statement>
             SELECT DISTINCT
-              b.sectie AS sectie_id,
-              sk.name AS sectie
+            b.sectie AS sectie_id,
+            sk.name AS sectie
             FROM hydr_boundaries_poly b
-              JOIN sectie_kinds sk ON b.sectie = sk.id
+            JOIN sectie_kinds sk ON b.sectie = sk.id
             WHERE b.river_id = ${river_id}
-              AND b.kind = 1
+            AND b.kind = 1
           </dc:statement>
           <dc:if test="dc:has-result()">
             <sobek_areas>
               <dc:for-each>
-                <boundary name="{$sectie}"
-                          factory="wmshydrboundariespolyfactory" target_out="{$out}"
-                          ids="{$river_id};{$sectie};1;{$sectie_id};-1"/>
+                <boundary name="{$sectie}" factory="wmshydrboundariespolyfactory" target_out="{$out}" ids="{$river_id};{$sectie};1;{$sectie_id};-1" />
               </dc:for-each>
             </sobek_areas>
           </dc:if>
@@ -2405,19 +2535,17 @@
         <dc:context>
           <dc:statement>
             SELECT DISTINCT
-              b.sobek AS sobek_id,
-              sk.name AS sobek
+            b.sobek AS sobek_id,
+            sk.name AS sobek
             FROM hydr_boundaries_poly b
-              JOIN sobek_kinds sk ON b.sobek = sk.id
+            JOIN sobek_kinds sk ON b.sobek = sk.id
             WHERE b.river_id = ${river_id}
-              AND b.kind = 1
+            AND b.kind = 1
           </dc:statement>
           <dc:if test="dc:has-result()">
             <sobek_flooded>
               <dc:for-each>
-                <boundary name="{$sobek}"
-                          factory="wmshydrboundariespolyfactory" target_out="{$out}"
-                          ids="{$river_id};{$sobek};1;-1;{$sobek_id}"/>
+                <boundary name="{$sobek}" factory="wmshydrboundariespolyfactory" target_out="{$out}" ids="{$river_id};{$sobek};1;-1;{$sobek_id}" />
               </dc:for-each>
             </sobek_flooded>
           </dc:if>
@@ -2425,17 +2553,15 @@
         <dc:context>
           <dc:statement>
             SELECT DISTINCT
-              b.name AS name
+            b.name AS name
             FROM hydr_boundaries_poly b
             WHERE b.river_id = ${river_id}
-              AND b.kind = 1
-              AND b.sobek IS NULL
-              AND b.sectie is NULL
+            AND b.kind = 1
+            AND b.sobek IS NULL
+            AND b.sectie is NULL
           </dc:statement>
           <dc:for-each>
-            <boundary name="{$name}"
-                      factory="wmshydrboundariespolyfactory" target_out="{$out}"
-                      ids="{$river_id};{$name}"/>
+            <boundary name="{$name}" factory="wmshydrboundariespolyfactory" target_out="{$out}" ids="{$river_id};{$name}" />
           </dc:for-each>
         </dc:context>
       </areas>
@@ -2447,126 +2573,116 @@
           SELECT DISTINCT 1 FROM floodmaps WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
-        <uesk>
-          <calculations>
-            <dc:context>
-              <dc:statement>
-                SELECT DISTINCT 1 FROM floodmaps WHERE river_id = ${river_id}
-                AND (kind = 112 OR kind = 111)
-              </dc:statement>
-              <dc:if test="dc:has-result()">
-                <current>
-                  <dc:context>
-                    <dc:statement>
-                      SELECT DISTINCT name AS name
-                      FROM floodmaps
-                      WHERE river_id = ${river_id} AND kind = 111
-                    </dc:statement>
-                    <dc:if test="dc:has-result()">
-                      <bfg>
-                        <dc:for-each>
-                          <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}"
-                            ids="{$river_id};{$name}"
-                            name="{$name}"/>
-                        </dc:for-each>
-                      </bfg>
-                    </dc:if>
-                  </dc:context>
-                  <dc:context>
-                    <dc:statement>
-                      SELECT DISTINCT name AS name
-                      FROM floodmaps
-                      WHERE river_id = ${river_id} AND kind = 112
-                    </dc:statement>
-                    <dc:if test="dc:has-result()">
-                      <federal>
-                        <dc:for-each>
-                          <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}"
-                            ids="{$river_id};{$name}"
-                            name="{$name}"/>
-                        </dc:for-each>
-                      </federal>
-                    </dc:if>
-                  </dc:context>
-                </current>
-              </dc:if>
-            </dc:context>
-            <dc:context>
-              <dc:statement>
-                SELECT DISTINCT 1 from floodmaps where river_id = ${river_id}
-                AND (kind = 122 OR kind = 121)
-              </dc:statement>
-              <dc:if test="dc:has-result()">
-                <potential>
-                  <dc:context>
-                    <dc:statement>
-                      SELECT DISTINCT name AS name
-                      FROM floodmaps
-                      WHERE river_id = ${river_id} AND kind = 121
-                    </dc:statement>
-                    <dc:if test="dc:has-result()">
-                      <bfg>
-                        <dc:for-each>
-                          <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}"
-                            ids="{$river_id};{$name}"
-                            name="{$name}"/>
-                        </dc:for-each>
-                      </bfg>
-                    </dc:if>
-                  </dc:context>
-                  <dc:context>
-                    <dc:statement>
-                      SELECT DISTINCT
-                        name AS name
-                      FROM floodmaps
-                      WHERE river_id = ${river_id} AND kind = 122
-                    </dc:statement>
-                    <dc:if test="dc:has-result()">
-                      <federal>
-                        <dc:for-each>
-                          <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}"
-                            ids="{$river_id};{$name}"
-                            name="{$name}"/>
-                        </dc:for-each>
-                      </federal>
-                    </dc:if>
-                  </dc:context>
-                </potential>
-              </dc:if>
-            </dc:context>
-          </calculations>
-          <dc:context>
-            <dc:statement>
-              SELECT DISTINCT
-                source AS source
-              FROM floodmaps
-              WHERE river_id = ${river_id} AND kind = 200
-            </dc:statement>
-            <dc:if test="dc:has-result()">
-              <measurements>
-                <dc:for-each>
-                  <year name="{$source}">
+          <uesk>
+            <calculations>
+              <dc:context>
+                <dc:statement>
+                  SELECT DISTINCT 1 FROM floodmaps WHERE river_id = ${river_id}
+                  AND (kind = 112 OR kind = 111)
+                </dc:statement>
+                <dc:if test="dc:has-result()">
+                  <current>
+                    <dc:context>
+                      <dc:statement>
+                        SELECT DISTINCT name AS name
+                        FROM floodmaps
+                        WHERE river_id = ${river_id} AND kind = 111
+                      </dc:statement>
+                      <dc:if test="dc:has-result()">
+                        <bfg>
+                          <dc:for-each>
+                            <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}" ids="{$river_id};{$name}" name="{$name}" />
+                          </dc:for-each>
+                        </bfg>
+                      </dc:if>
+                    </dc:context>
+                    <dc:context>
+                      <dc:statement>
+                        SELECT DISTINCT name AS name
+                        FROM floodmaps
+                        WHERE river_id = ${river_id} AND kind = 112
+                      </dc:statement>
+                      <dc:if test="dc:has-result()">
+                        <federal>
+                          <dc:for-each>
+                            <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}" ids="{$river_id};{$name}" name="{$name}" />
+                          </dc:for-each>
+                        </federal>
+                      </dc:if>
+                    </dc:context>
+                  </current>
+                </dc:if>
+              </dc:context>
+              <dc:context>
+                <dc:statement>
+                  SELECT DISTINCT 1 from floodmaps where river_id = ${river_id}
+                  AND (kind = 122 OR kind = 121)
+                </dc:statement>
+                <dc:if test="dc:has-result()">
+                  <potential>
+                    <dc:context>
+                      <dc:statement>
+                        SELECT DISTINCT name AS name
+                        FROM floodmaps
+                        WHERE river_id = ${river_id} AND kind = 121
+                      </dc:statement>
+                      <dc:if test="dc:has-result()">
+                        <bfg>
+                          <dc:for-each>
+                            <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}" ids="{$river_id};{$name}" name="{$name}" />
+                          </dc:for-each>
+                        </bfg>
+                      </dc:if>
+                    </dc:context>
                     <dc:context>
                       <dc:statement>
                         SELECT DISTINCT
-                          name AS name
+                        name AS name
                         FROM floodmaps
-                        WHERE river_id = ${river_id} AND kind = 200 AND source =
-                        ${source}
+                        WHERE river_id = ${river_id} AND kind = 122
                       </dc:statement>
-                      <dc:for-each>
-                        <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}"
-                          ids="{$river_id};{$name}"
-                          name="{$name}"/>
-                      </dc:for-each>
+                      <dc:if test="dc:has-result()">
+                        <federal>
+                          <dc:for-each>
+                            <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}" ids="{$river_id};{$name}" name="{$name}" />
+                          </dc:for-each>
+                        </federal>
+                      </dc:if>
                     </dc:context>
-                  </year>
-                </dc:for-each>
-              </measurements>
-            </dc:if>
-          </dc:context>
-        </uesk>
-      </dc:if>
+                  </potential>
+                </dc:if>
+              </dc:context>
+            </calculations>
+            <dc:context>
+              <dc:statement>
+                SELECT DISTINCT
+                source AS source
+                FROM floodmaps
+                WHERE river_id = ${river_id} AND kind = 200
+              </dc:statement>
+              <dc:if test="dc:has-result()">
+                <measurements>
+                  <dc:for-each>
+                    <year name="{$source}">
+                      <dc:context>
+                        <dc:statement>
+                          SELECT DISTINCT
+                          name AS name
+                          FROM floodmaps
+                          WHERE river_id = ${river_id} AND kind = 200 AND source =
+                          ${source}
+                        </dc:statement>
+                        <dc:for-each>
+                          <floodmaps factory="wmsfloodmapsfactory" target_out="{$out}" ids="{$river_id};{$name}" name="{$name}" />
+                        </dc:for-each>
+                      </dc:context>
+                    </year>
+                  </dc:for-each>
+                </measurements>
+              </dc:if>
+            </dc:context>
+          </uesk>
+        </dc:if>
       </dc:context>
     </dc:macro>
 
@@ -2574,28 +2690,24 @@
       <dc:context>
         <dc:statement>
           SELECT DISTINCT
-            fp.kind_id AS kind_id,
-            flk.name AS kind_name
+          fp.kind_id AS kind_id,
+          flk.name AS kind_name
           FROM floodplain fp
-            JOIN floodplain_kinds flk on fp.kind_id = flk.id
+          JOIN floodplain_kinds flk on fp.kind_id = flk.id
           WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
           <floodplain>
             <dc:filter expr="$kind_id=1">
               <dc:for-each>
-                <floody factory="wmsfloodplainfactory" target_out="{$out}"
-                        description="{$kind_name}"
-                        ids="{$river_id};{$kind_name};{$kind_id}"/>
+                <floody factory="wmsfloodplainfactory" target_out="{$out}" description="{$kind_name}" ids="{$river_id};{$kind_name};{$kind_id}" />
               </dc:for-each>
             </dc:filter>
             <dc:filter expr="$kind_id != 1">
               <dc:if test="dc:has-result()">
                 <other>
                   <dc:for-each>
-                    <floody factory="wmsfloodplainfactory" target_out="{$out}"
-                            description="{$layer_name}"
-                            ids="{$river_id};{$layer_name};{$kind_id}"/>
+                    <floody factory="wmsfloodplainfactory" target_out="{$out}" description="{$layer_name}" ids="{$river_id};{$layer_name};{$kind_id}" />
                   </dc:for-each>
                 </other>
               </dc:if>
@@ -2613,16 +2725,14 @@
 
       <dc:macro name="hwspoints_by_kind_factory">
         <dc:for-each>
-          <hws factory="wmshwspointsfactory" target_out="{$out}"
-               ids="{$river_id};{$hws_name}"
-               name="{$hws_name}"/>
+          <hws factory="wmshwspointsfactory" target_out="{$out}" ids="{$river_id};{$hws_name}" name="{$hws_name}" />
         </dc:for-each>
       </dc:macro>
 
       <dc:filter expr="$hws_kind=1">
         <dc:if test="dc:has-result()">
           <Durchlass>
-            <dc:call-macro name="hwspoints_by_kind_factory"/>
+            <dc:call-macro name="hwspoints_by_kind_factory" />
           </Durchlass>
         </dc:if>
       </dc:filter>
@@ -2630,7 +2740,7 @@
       <dc:filter expr="$hws_kind=2">
         <dc:if test="dc:has-result()">
           <Damm>
-            <dc:call-macro name="hwspoints_by_kind_factory"/>
+            <dc:call-macro name="hwspoints_by_kind_factory" />
           </Damm>
         </dc:if>
       </dc:filter>
@@ -2638,7 +2748,7 @@
       <dc:filter expr="$hws_kind=3">
         <dc:if test="dc:has-result()">
           <Graben>
-            <dc:call-macro name="hwspoints_by_kind_factory"/>
+            <dc:call-macro name="hwspoints_by_kind_factory" />
           </Graben>
         </dc:if>
       </dc:filter>
@@ -2650,26 +2760,26 @@
           <dc:context>
             <dc:statement>
               SELECT DISTINCT
-                fs.name AS fed_name,
-                fs.id AS fed_id
+              fs.name AS fed_name,
+              fs.id AS fed_id
               FROM hws_points hws
-                JOIN fed_states fs ON hws.fed_state_id = fs.id
+              JOIN fed_states fs ON hws.fed_state_id = fs.id
               WHERE river_id = ${river_id}
-                AND hws.official=1
+              AND hws.official=1
             </dc:statement>
             <dc:for-each>
               <dc:context>
                 <dc:statement>
                   SELECT DISTINCT
-                    name AS hws_name,
-                    kind_id AS hws_kind
+                  name AS hws_name,
+                  kind_id AS hws_kind
                   FROM hws_points
                   WHERE river_id = ${river_id}
-                    AND official=1
-                    AND fed_state_id = ${fed_id} ORDER BY name
+                  AND official=1
+                  AND fed_state_id = ${fed_id} ORDER BY name
                 </dc:statement>
                 <fedstate description="{$fed_name}">
-                  <dc:call-macro name="hwspoints_by_kind"/>
+                  <dc:call-macro name="hwspoints_by_kind" />
                 </fedstate>
               </dc:context>
             </dc:for-each>
@@ -2677,16 +2787,16 @@
           <dc:context>
             <dc:statement>
               SELECT distinct
-                name AS hws_name,
-                kind_id AS hws_kind
+              name AS hws_name,
+              kind_id AS hws_kind
               FROM hws_points
               WHERE river_id = ${river_id}
-                AND official=1
-                AND fed_state_id IS NULL
-                ORDER BY name
+              AND official=1
+              AND fed_state_id IS NULL
+              ORDER BY name
             </dc:statement>
             <hws_fed_unknown>
-              <dc:call-macro name="hwspoints_by_kind"/>
+              <dc:call-macro name="hwspoints_by_kind" />
             </hws_fed_unknown>
           </dc:context>
         </official>
@@ -2694,26 +2804,26 @@
           <dc:context>
             <dc:statement>
               SELECT DISTINCT
-                fs.name AS fed_name,
-                fs.id AS fed_id
+              fs.name AS fed_name,
+              fs.id AS fed_id
               FROM hws_points hws
-                JOIN fed_states fs ON hws.fed_state_id = fs.id
+              JOIN fed_states fs ON hws.fed_state_id = fs.id
               WHERE river_id = ${river_id}
-                AND hws.official=0
+              AND hws.official=0
             </dc:statement>
             <dc:for-each>
               <dc:context>
                 <dc:statement>
                   SELECT DISTINCT
-                    name AS hws_name,
-                    kind_id AS hws_kind
+                  name AS hws_name,
+                  kind_id AS hws_kind
                   FROM hws_points
                   WHERE river_id = ${river_id}
-                    AND official=0
-                    AND fed_state_id = ${fed_id} ORDER BY name
+                  AND official=0
+                  AND fed_state_id = ${fed_id} ORDER BY name
                 </dc:statement>
                 <fedstate description="{$fed_name}">
-                  <dc:call-macro name="hwspoints_by_kind"/>
+                  <dc:call-macro name="hwspoints_by_kind" />
                 </fedstate>
               </dc:context>
             </dc:for-each>
@@ -2721,15 +2831,15 @@
           <dc:context>
             <dc:statement>
               SELECT distinct
-                name AS hws_name,
-                kind_id AS hws_kind
+              name AS hws_name,
+              kind_id AS hws_kind
               FROM hws_points
               WHERE river_id = ${river_id}
-                AND official=0
-                AND fed_state_id IS NULL ORDER BY name
+              AND official=0
+              AND fed_state_id IS NULL ORDER BY name
             </dc:statement>
             <hws_fed_unknown>
-              <dc:call-macro name="hwspoints_by_kind"/>
+              <dc:call-macro name="hwspoints_by_kind" />
             </hws_fed_unknown>
           </dc:context>
         </inofficial>
@@ -2744,16 +2854,14 @@
 
       <dc:macro name="hwslines_by_kind_factory">
         <dc:for-each>
-          <hws factory="wmshwslinesfactory" target_out="{$out}"
-               ids="{$river_id};{$hws_name}"
-               name="{$hws_name}"/>
+          <hws factory="wmshwslinesfactory" target_out="{$out}" ids="{$river_id};{$hws_name}" name="{$hws_name}" />
         </dc:for-each>
       </dc:macro>
 
       <dc:filter expr="$hws_kind=1">
         <dc:if test="dc:has-result()">
           <Durchlass>
-            <dc:call-macro name="hwslines_by_kind_factory"/>
+            <dc:call-macro name="hwslines_by_kind_factory" />
           </Durchlass>
         </dc:if>
       </dc:filter>
@@ -2761,7 +2869,7 @@
       <dc:filter expr="$hws_kind=2">
         <dc:if test="dc:has-result()">
           <Damm>
-            <dc:call-macro name="hwslines_by_kind_factory"/>
+            <dc:call-macro name="hwslines_by_kind_factory" />
           </Damm>
         </dc:if>
       </dc:filter>
@@ -2769,7 +2877,7 @@
       <dc:filter expr="$hws_kind=3">
         <dc:if test="dc:has-result()">
           <Graben>
-            <dc:call-macro name="hwslines_by_kind_factory"/>
+            <dc:call-macro name="hwslines_by_kind_factory" />
           </Graben>
         </dc:if>
       </dc:filter>
@@ -2781,26 +2889,26 @@
           <dc:context>
             <dc:statement>
               SELECT DISTINCT
-                fs.name AS fed_name,
-                fs.id AS fed_id
+              fs.name AS fed_name,
+              fs.id AS fed_id
               FROM hws_lines hws
-                JOIN fed_states fs ON hws.fed_state_id = fs.id
+              JOIN fed_states fs ON hws.fed_state_id = fs.id
               WHERE river_id = ${river_id}
-                AND hws.official=1
+              AND hws.official=1
             </dc:statement>
             <dc:for-each>
               <dc:context>
                 <dc:statement>
                   SELECT DISTINCT
-                    name AS hws_name,
-                    kind_id AS hws_kind
+                  name AS hws_name,
+                  kind_id AS hws_kind
                   FROM hws_lines
                   WHERE river_id = ${river_id}
-                    AND official=1
-                    AND fed_state_id = ${fed_id} ORDER BY name
+                  AND official=1
+                  AND fed_state_id = ${fed_id} ORDER BY name
                 </dc:statement>
                 <fedstate description="{$fed_name}">
-                  <dc:call-macro name="hwslines_by_kind"/>
+                  <dc:call-macro name="hwslines_by_kind" />
                 </fedstate>
               </dc:context>
             </dc:for-each>
@@ -2808,16 +2916,16 @@
           <dc:context>
             <dc:statement>
               SELECT distinct
-                name AS hws_name,
-                kind_id AS hws_kind
+              name AS hws_name,
+              kind_id AS hws_kind
               FROM hws_lines
               WHERE river_id = ${river_id}
-                AND official=1
-                AND fed_state_id IS NULL
-                ORDER BY name
+              AND official=1
+              AND fed_state_id IS NULL
+              ORDER BY name
             </dc:statement>
             <hws_fed_unknown>
-              <dc:call-macro name="hwslines_by_kind"/>
+              <dc:call-macro name="hwslines_by_kind" />
             </hws_fed_unknown>
           </dc:context>
         </official>
@@ -2825,26 +2933,26 @@
           <dc:context>
             <dc:statement>
               SELECT DISTINCT
-                fs.name AS fed_name,
-                fs.id AS fed_id
+              fs.name AS fed_name,
+              fs.id AS fed_id
               FROM hws_lines hws
-                JOIN fed_states fs ON hws.fed_state_id = fs.id
+              JOIN fed_states fs ON hws.fed_state_id = fs.id
               WHERE river_id = ${river_id}
-                AND hws.official=0
+              AND hws.official=0
             </dc:statement>
             <dc:for-each>
               <dc:context>
                 <dc:statement>
                   SELECT DISTINCT
-                    name AS hws_name,
-                    kind_id AS hws_kind
+                  name AS hws_name,
+                  kind_id AS hws_kind
                   FROM hws_lines
                   WHERE river_id = ${river_id}
-                    AND official=0
-                    AND fed_state_id = ${fed_id} ORDER BY name
+                  AND official=0
+                  AND fed_state_id = ${fed_id} ORDER BY name
                 </dc:statement>
                 <fedstate description="{$fed_name}">
-                  <dc:call-macro name="hwslines_by_kind"/>
+                  <dc:call-macro name="hwslines_by_kind" />
                 </fedstate>
               </dc:context>
             </dc:for-each>
@@ -2852,15 +2960,15 @@
           <dc:context>
             <dc:statement>
               SELECT distinct
-                name AS hws_name,
-                kind_id AS hws_kind
+              name AS hws_name,
+              kind_id AS hws_kind
               FROM hws_lines
               WHERE river_id = ${river_id}
-                AND official=0
-                AND fed_state_id IS NULL ORDER BY name
+              AND official=0
+              AND fed_state_id IS NULL ORDER BY name
             </dc:statement>
             <hws_fed_unknown>
-              <dc:call-macro name="hwslines_by_kind"/>
+              <dc:call-macro name="hwslines_by_kind" />
             </hws_fed_unknown>
           </dc:context>
         </inofficial>
@@ -2871,16 +2979,14 @@
       <dc:context>
         <dc:statement>
           SELECT DISTINCT
-            COALESCE(CAST (year AS VARCHAR(64)), 'Unbekanntes Jahr') AS year
+          COALESCE(CAST (year AS VARCHAR(64)), 'Unbekanntes Jahr') AS year
           FROM flood_marks
           WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
           <floodmarks>
             <dc:for-each>
-              <floodmark name="{$year}"
-                factory="wmsfloodmarkfactory" target_out="{$out}"
-                ids="{$river_id};{$year};{$year}"/>
+              <floodmark name="{$year}" factory="wmsfloodmarkfactory" target_out="{$out}" ids="{$river_id};{$year};{$year}" />
             </dc:for-each>
           </floodmarks>
         </dc:if>
@@ -2900,28 +3006,24 @@
       <dc:context>
         <dc:statement>
           SELECT DISTINCT
-            ak.name    AS kind_name,
-            ax.kind_id AS kind_id,
-            ax.name    AS layer_name
+          ak.name AS kind_name,
+          ax.kind_id AS kind_id,
+          ax.name AS layer_name
           FROM river_axes ax
-            JOIN axis_kinds ak on ax.kind_id = ak.id
+          JOIN axis_kinds ak on ax.kind_id = ak.id
           WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
           <axis>
             <dc:filter expr="$kind_id=1">
               <dc:for-each>
-                <actual description="{$kind_name}"
-                        ids="{$river_id};{$kind_name};{$kind_id}"
-                        factory="riveraxis" target_out="{$out}" />
+                <actual description="{$kind_name}" ids="{$river_id};{$kind_name};{$kind_id}" factory="riveraxis" target_out="{$out}" />
               </dc:for-each>
             </dc:filter>
             <dc:filter expr="$kind_id!=1">
               <other>
                 <dc:for-each>
-                  <misc-axis description="{$layer_name}"
-                             ids="{$river_id};{$layer_name};{$kind_id}"
-                             factory="riveraxis" target_out="{$out}" />
+                  <misc-axis description="{$layer_name}" ids="{$river_id};{$layer_name};{$kind_id}" factory="riveraxis" target_out="{$out}" />
                 </dc:for-each>
               </other>
             </dc:filter>
@@ -2935,8 +3037,8 @@
         <dc:statement>
           SELECT DISTINCT 1 FROM river_axes_km WHERE river_id = ${river_id}
         </dc:statement>
-         <dc:for-each>
-            <kilometrage factory="wmskmfactory" ids="{$river_id}" target_out="{$out}" />
+        <dc:for-each>
+          <kilometrage factory="wmskmfactory" ids="{$river_id}" target_out="{$out}" />
         </dc:for-each>
       </dc:context>
     </dc:macro>
@@ -2947,11 +3049,10 @@
           SELECT name AS name
           FROM fixpoints
           WHERE river_id = ${river_id}
-            GROUP BY name
+          GROUP BY name
         </dc:statement>
         <dc:for-each>
-          <fixpoints factory="wmsfixpointsfactory" target_out="{$out}"
-            ids="{$river_id};{$name}"/>
+          <fixpoints factory="wmsfixpointsfactory" target_out="{$out}" ids="{$river_id};{$name}" />
         </dc:for-each>
       </dc:context>
     </dc:macro>
@@ -2960,29 +3061,25 @@
       <dc:context>
         <dc:statement>
           SELECT DISTINCT
-            cs.kind_id AS kind_id,
-            cs.name    AS layer_name,
-            ck.name    AS kind_name
+          cs.kind_id AS kind_id,
+          cs.name AS layer_name,
+          ck.name AS kind_name
           FROM cross_section_tracks cs
-            JOIN cross_section_track_kinds ck ON cs.kind_id = ck.id
+          JOIN cross_section_track_kinds ck ON cs.kind_id = ck.id
           WHERE river_id = ${river_id}
         </dc:statement>
         <dc:if test="dc:has-result()">
           <qps>
             <dc:filter expr="$kind_id=1">
               <dc:for-each>
-                <actual description="{$kind_name}"
-                        factory="wmsqpsfactory" target_out="{$out}"
-                        ids="{$river_id};{$kind_name};{$kind_id}"/>
+                <actual description="{$kind_name}" factory="wmsqpsfactory" target_out="{$out}" ids="{$river_id};{$kind_name};{$kind_id}" />
               </dc:for-each>
             </dc:filter>
             <dc:filter expr="$kind_id = 0">
               <dc:if test="dc:has-result()">
                 <other>
                   <dc:for-each>
-                    <misc-qps description="{$layer_name}"
-                              factory="wmsqpsfactory" target_out="{$out}"
-                              ids="{$river_id};{$layer_name};{$kind_id}"/>
+                    <misc-qps description="{$layer_name}" factory="wmsqpsfactory" target_out="{$out}" ids="{$river_id};{$layer_name};{$kind_id}" />
                   </dc:for-each>
                 </other>
               </dc:if>
@@ -2997,27 +3094,23 @@
         <dc:context>
           <dc:statement>
             SELECT DISTINCT
-              b.name AS building_name,
-              bk.name AS building_kind,
-              b.kind_id AS building_kind_id
+            b.name AS building_name,
+            bk.name AS building_kind,
+            b.kind_id AS building_kind_id
             FROM buildings b
-              JOIN building_kinds bk ON b.kind_id = bk.id
+            JOIN building_kinds bk ON b.kind_id = bk.id
             WHERE river_id = ${river_id}
           </dc:statement>
           <dc:if test="dc:has-result()">
             <dc:filter expr="$building_kind_id!=0">
               <dc:for-each>
-                <buildings description="{$building_kind}"
-                           factory="wmsbuildingsfactory" target_out="{$out}"
-                           ids="{$river_id};{$building_kind};{$building_kind_id}"/>
+                <buildings description="{$building_kind}" factory="wmsbuildingsfactory" target_out="{$out}" ids="{$river_id};{$building_kind};{$building_kind_id}" />
               </dc:for-each>
             </dc:filter>
             <dc:filter expr="$building_kind_id=0">
               <other>
                 <dc:for-each>
-                  <buildings description="{$building_name}"
-                             factory="wmsbuildingsfactory" target_out="{$out}"
-                             ids="{$river_id};{$building_name}"/>
+                  <buildings description="{$building_name}" factory="wmsbuildingsfactory" target_out="{$out}" ids="{$river_id};{$building_name}" />
                 </dc:for-each>
               </other>
             </dc:filter>
@@ -3026,18 +3119,16 @@
         <dc:context>
           <dc:statement>
             SELECT DISTINCT
-              j.kind_id AS jetty_kind_id,
-              jk.name AS jetty_kind
+            j.kind_id AS jetty_kind_id,
+            jk.name AS jetty_kind
             FROM jetties j
-              JOIN jetty_kinds jk ON j.kind_id = jk.id
+            JOIN jetty_kinds jk ON j.kind_id = jk.id
             WHERE river_id = ${river_id}
           </dc:statement>
           <dc:if test="dc:has-result()">
             <jetties>
               <dc:for-each>
-                <jetty description="{$jetty_kind}"
-                       factory="wmsjettiesfactory" target_out="{$out}"
-                       ids="{$river_id};{$jetty_kind};{$jetty_kind_id}"/>
+                <jetty description="{$jetty_kind}" factory="wmsjettiesfactory" target_out="{$out}" ids="{$river_id};{$jetty_kind};{$jetty_kind_id}" />
               </dc:for-each>
             </jetties>
           </dc:if>
@@ -3049,16 +3140,14 @@
       <dc:if test="dc:contains($parameters, 'official-lines')">
         <dc:container-context container="official-lines">
           <dc:properties>
-            <dc:property name="name" alias="olname"/>
-            <dc:property name="wstId" alias="wstid"/>
-            <dc:property name="columnPos" alias="wstcolpos"/>
+            <dc:property name="name" alias="olname" />
+            <dc:property name="wstId" alias="wstid" />
+            <dc:property name="columnPos" alias="wstcolpos" />
           </dc:properties>
           <dc:if test="dc:has-result()">
             <officiallines>
               <dc:for-each>
-                <column name="{$olname}"
-                  ids="official-wstv-{$wstcolpos}-{$wstid}"
-                  factory="staticwqkms" target_out="{$out}"/>
+                <column name="{$olname}" ids="official-wstv-{$wstcolpos}-{$wstid}" factory="staticwqkms" target_out="{$out}" />
               </dc:for-each>
             </officiallines>
           </dc:if>
@@ -3069,19 +3158,14 @@
     <!-- sediment loads -->
     <dc:macro name="sedimentload_off_epoch_filter">
       <dc:if test="dc:has-result()">
-        <dc:variable name="sq_time_id" type="number"
-                     expr="number($sq_ti_id)"/>
+        <dc:variable name="sq_time_id" type="number" expr="number($sq_ti_id)" />
         <dc:if test="string-length(dc:get('epochs')) &gt; 0">
-          <dc:variable name="start" type="number"
-                       expr="dc:min-number(dc:find-all('\d{4}', $epochs))"/>
-          <dc:variable name="end" type="number"
-                       expr="dc:max-number(dc:find-all('\d{4}', $epochs))"/>
+          <dc:variable name="start" type="number" expr="dc:min-number(dc:find-all('\d{4}', $epochs))" />
+          <dc:variable name="end" type="number" expr="dc:max-number(dc:find-all('\d{4}', $epochs))" />
         </dc:if>
         <dc:if test="string-length(dc:get('years')) &gt; 0">
-          <dc:variable name="start" type="number"
-                       expr="dc:min-number(dc:find-all('\d{4}', $years))"/>
-          <dc:variable name="end" type="number"
-                       expr="dc:max-number(dc:find-all('\d{4}', $years))"/>
+          <dc:variable name="start" type="number" expr="dc:min-number(dc:find-all('\d{4}', $years))" />
+          <dc:variable name="end" type="number" expr="dc:max-number(dc:find-all('\d{4}', $years))" />
         </dc:if>
         <dc:filter expr="$kind = 'official' and
                          $sqid = $sq_time_id and
@@ -3089,25 +3173,25 @@
                              number(dc:date-format('yyyy', $startyear))
                            or number($start) &gt;
                              number(dc:date-format('yyyy', $endyear)))">
-          <dc:macro-body/>
+          <dc:macro-body />
         </dc:filter>
       </dc:if>
     </dc:macro>
 
     <dc:macro name="sedimentload_off_epochs">
       <dc:context>
-        <dc:call-macro name="sedimentload_stations_statement"/>
+        <dc:call-macro name="sedimentload_stations_statement" />
         <dc:call-macro name="sedimentload_off_epoch_filter">
           <dc:call-macro name="loads">
-            <dc:call-macro name="load"/>
+            <dc:call-macro name="load" />
           </dc:call-macro>
         </dc:call-macro>
       </dc:context>
       <dc:context>
-        <dc:call-macro name="sedimentload_ls_statement"/>
+        <dc:call-macro name="sedimentload_ls_statement" />
         <dc:call-macro name="sedimentload_off_epoch_filter">
           <dc:call-macro name="loads">
-            <dc:call-macro name="load_ls"/>
+            <dc:call-macro name="load_ls" />
           </dc:call-macro>
         </dc:call-macro>
       </dc:context>
@@ -3115,71 +3199,77 @@
 
 
     <!-- Common stuff -->
-
     <dc:macro name="km-filtered-wsts">
       <dc:context connection="system">
         <dc:statement>
-          SELECT w.kind         AS kind,
-                 w.id           AS wst_id,
-                 wc.id          AS wst_column_id,
-                 wc.position    AS wst_column_position,
-                 wc.description AS info,
-                 w.description  AS wst_description,
-                 COALESCE(wc.name, '')        AS wst_column_name,
-                 wr.a           AS deffrom,
-                 wr.b           AS defto
+          SELECT w.kind AS kind,
+          w.id AS wst_id,
+          wc.id AS wst_column_id,
+          wc.position AS wst_column_position,
+          wc.description AS info,
+          w.description AS wst_description,
+          ti.start_time AS start_time,
+          ti.stop_time AS stop_time,
+          COALESCE(wc.name, '') AS wst_column_name,
+          wr.a AS deffrom,
+          wr.b AS defto,
+          w.sinfo_selection
           FROM wst_columns wc
-            JOIN wsts w        ON wc.wst_id = w.id
-            JOIN wst_ranges wr ON wc.id = wr.wst_column_id
+          JOIN wsts w ON wc.wst_id = w.id
+          JOIN wst_ranges wr ON wc.id = wr.wst_column_id
+          LEFT JOIN time_intervals ti ON wc.time_interval_id = ti.id          
           WHERE w.river_id = ${river_id} AND
-            NOT((${tokm} &lt; wr.a) or (${fromkm} &gt; wr.b))
-            ORDER BY wst_column_position
+          NOT((${tokm} &lt; wr.a) or (${fromkm} &gt; wr.b))
+          ORDER BY wst_column_position
         </dc:statement>
-        <dc:macro-body/>
+        <dc:macro-body />
       </dc:context>
     </dc:macro>
 
     <dc:macro name="all-user-artifacts">
-        <dc:context connection="user">
-          <dc:comment>Select collections and masterartifacts.
-            XXX: The cast is a quick hack because the ld_* values are
-            now TEXT fields. To properly fix / asses the problems here
-            an SLT evaluation is needed.
-          </dc:comment>
+      <dc:context connection="user">
+        <dc:comment>Select collections and masterartifacts.
+          XXX: The cast is a quick hack because the ld_* values are
+          now TEXT fields. To properly fix / asses the problems here
+          an SLT evaluation is needed.
+        </dc:comment>
         <dc:statement>
-          SELECT c.name                     AS collection_name,
-                 ma.id                      AS a_id,
-                 ma.state                   AS a_state,
-                 ma.gid                     AS a_gid,
-                 ma.creation                AS a_creation,
-                 CAST(COALESCE(ma.ld_mode, '') AS VARCHAR(255)) AS ld_m,
-                 CAST(COALESCE(ma.ld_locations, '') AS VARCHAR(255)) AS ld_l,
-                 CAST(COALESCE(ma.ld_from, '') AS VARCHAR(255)) AS ld_f,
-                 CAST(COALESCE(ma.ld_to, '') AS VARCHAR(255)) AS ld_t,
-                 o.name                        AS out_name,
-                 o.id                          AS out_id,
-                 f.name                        AS facet_name,
-                 f.num                         AS facet_num,
-                 f.description                 AS facet_description,
-                 f.id                          AS fid
+          SELECT c.name AS collection_name,
+          ma.id AS a_id,
+          ma.state AS a_state,
+          ma.gid AS a_gid,
+          ma.creation AS a_creation,
+          CAST(COALESCE(ma.ld_mode, '') AS VARCHAR(255)) AS ld_m,
+          CAST(COALESCE(ma.ld_locations, '') AS VARCHAR(255)) AS ld_l,
+          CAST(COALESCE(ma.ld_from, '') AS VARCHAR(255)) AS ld_f,
+          CAST(COALESCE(ma.ld_to, '') AS VARCHAR(255)) AS ld_t,
+          o.name AS out_name,
+          o.id AS out_id,
+          f.name AS
+          facet_name,
+          f.num AS facet_num,
+          f.description AS facet_description,
+          f.id AS fid
           FROM users u
-            JOIN collections c             ON c.user_id = u.id
-            JOIN master_artifacts_range ma ON ma.collection_id = c.id
-            JOIN outs o                    ON o.artifact_id = ma.id
-            JOIN facets f                  ON f.out_id = o.id
-          WHERE  u.gid = CAST(${user-id} AS UUID)
-            AND ma.gid &lt;&gt; CAST(${artifact-id} AS uuid)
-            AND f.name NOT LIKE '%empty.facet%'
-            AND EXISTS (
-              SELECT id
-              FROM artifact_data ad
-              WHERE ad.artifact_id = ma.id
-                AND k = 'river'
-                AND v = ${river})
+          JOIN
+          collections c ON c.user_id = u.id
+          JOIN master_artifacts_range ma ON ma.collection_id = c.id
+          JOIN outs o ON o.artifact_id = ma.id
+          JOIN facets f ON f.out_id = o.id
+          WHERE u.gid = CAST(${user-id} AS UUID)
+          AND ma.gid &lt;&gt; CAST(${artifact-id} AS uuid)
+          AND f.name NOT LIKE '%empty.facet%'
+          AND EXISTS (
+          SELECT
+          id
+          FROM artifact_data ad
+          WHERE ad.artifact_id = ma.id
+          AND k = 'river'
+          AND v = ${river})
         </dc:statement>
         <dc:virtual-column name="deffrom" type="number" expr="dc:fromValue($ld_m, $ld_l, $ld_f)">
           <dc:virtual-column name="defto" type="number" expr="dc:toValue($ld_m, $ld_l, $ld_t)">
-            <dc:macro-body/>
+            <dc:macro-body />
           </dc:virtual-column>
         </dc:virtual-column>
       </dc:context>
@@ -3192,40 +3282,371 @@
       </dc:comment>
       <dc:filter expr="not($deffrom &gt; $tokm or $defto &lt; $fromkm) or
         starts-with($facet_name, 'sq_')">
-        <dc:macro-body/>
+        <dc:macro-body />
       </dc:filter>
     </dc:macro>
 
     <dc:macro name="artifact-range">
       <dc:choose>
         <dc:when test="dc:coalesce(dc:get('ld_locations'), ' ') != ' '">
-          <dc:variable name="fromkm" type="number"
-                       expr="dc:min-number(dc:find-all('\d*\.?\d*',
-                             dc:get('ld_locations')))"/>
-          <dc:variable name="tokm" type="number"
-                       expr="dc:max-number(dc:find-all('\d*\.?\d*',
-                             dc:get('ld_locations')))"/>
+          <dc:variable name="fromkm" type="number" expr="dc:min-number(dc:find-all('\d*\.?\d*',
+                             dc:get('ld_locations')))" />
+          <dc:variable name="tokm" type="number" expr="dc:max-number(dc:find-all('\d*\.?\d*',
+                             dc:get('ld_locations')))" />
         </dc:when>
         <dc:otherwise>
-          <dc:variable name="fromkm" type="number"
-                       expr="dc:fromValue(dc:get('ld_mode'),
-                             dc:get('ld_locations'), dc:get('ld_from'))"/>
-          <dc:variable name="tokm" type="number"
-                       expr="dc:toValue(dc:get('ld_mode'),
-                             dc:get('ld_locations'), dc:get('ld_to'))"/>
+          <dc:variable name="fromkm" type="number" expr="dc:fromValue(dc:get('ld_mode'),
+                             dc:get('ld_locations'), dc:get('ld_from'))" />
+          <dc:variable name="tokm" type="number" expr="dc:toValue(dc:get('ld_mode'),
+                             dc:get('ld_locations'), dc:get('ld_to'))" />
           <dc:if test="$fromkm > $tokm">
             <dc:message>Inverting KM filter.</dc:message>
-            <dc:variable name="fromkm" type="number"
-                         expr="dc:toValue(dc:get('ld_mode'),
-                               dc:get('ld_locations'), dc:get('ld_to'))"/>
-            <dc:variable name="tokm" type="number"
-                         expr="dc:fromValue(dc:get('ld_mode'),
-                               dc:get('ld_locations'), dc:get('ld_from'))"/>
+            <dc:variable name="fromkm" type="number" expr="dc:toValue(dc:get('ld_mode'),
+                               dc:get('ld_locations'), dc:get('ld_to'))" />
+            <dc:variable name="tokm" type="number" expr="dc:fromValue(dc:get('ld_mode'),
+                               dc:get('ld_locations'), dc:get('ld_from'))" />
           </dc:if>
         </dc:otherwise>
       </dc:choose>
-      <dc:macro-body/>
+      <dc:macro-body />
+    </dc:macro>
+
+    <dc:macro name="sinfo_flowdepths">
+      <dc:filter expr="$a_state = 'state.sinfo.flow_depth' and 
+                       ( $facet_name = 'sinfo_facet_flow_depth' or $facet_name = 'sinfo_facet_flow_depth.filtered' or 
+                         $facet_name = 'sinfo_facet_flow_depth_with_tkh' or $facet_name = 'sinfo_facet_flow_depth_with_tkh.filtered' or 
+                         $facet_name = 'sinfo_facet_tkh' )">
+        <dc:if test="dc:has-result()">
+          <sinfo_flow_depths>
+            <dc:call-macro name="collection-group">
+              <sinfo_flow_depth description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:element name="${facet_name}">
+                    <dc:attribute name="factory" value="sinfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
+                  </dc:element>
+                </dc:for-each>
+              </sinfo_flow_depth>
+            </dc:call-macro>
+          </sinfo_flow_depths>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="sinfo_flowdepths_minmax">
+      <dc:filter expr="$a_state = 'state.sinfo.flow_depth_minmax' and 
+                     ( $facet_name = 'sinfo_facet_flow_depth_min' or $facet_name = 'sinfo_facet_flow_depth_min.filtered' or 
+                       $facet_name = 'sinfo_facet_flow_depth_max' or $facet_name = 'sinfo_facet_flow_depth_max.filtered' )">
+        <dc:if test="dc:has-result()">
+          <sinfo_flow_depths_minmax>
+            <dc:call-macro name="collection-group">
+              <sinfo_flow_depth_minmax description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:element name="${facet_name}">
+                    <dc:attribute name="factory" value="sinfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
+                  </dc:element>
+                </dc:for-each>
+              </sinfo_flow_depth_minmax>
+            </dc:call-macro>
+          </sinfo_flow_depths_minmax>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="sinfo_flow_depth_development">
+      <dc:filter
+        expr="$a_state = 'state.sinfo.flow_depth_development' and
+                     ( $facet_name = 'sinfo_facet_flow_depth_development' or $facet_name = 'sinfo_facet_flow_depth_development.filtered' or
+                       $facet_name = 'sinfo_facet_flow_depth_development_per_year' or $facet_name = 'sinfo_facet_flow_depth_development_per_year.filtered' or
+                       $facet_name = 'sinfo_facet_flow_depth_current' or $facet_name = 'sinfo_facet_flow_depth_current.filtered' or 
+                       $facet_name = 'sinfo_facet_flow_depth_historical' or $facet_name = 'sinfo_facet_flow_depth_historical.filtered' or                       
+                       $facet_name = 'sinfo_facet_waterlevel_difference' or $facet_name = 'sinfo_facet_waterlevel_difference.filtered' or
+                       $facet_name = 'sinfo_facet_bedheight_difference' or $facet_name = 'sinfo_facet_bedheight_difference.filtered' )">
+        <dc:if test="dc:has-result()">
+          <sinfo_flow_depth_developments>
+            <dc:call-macro name="collection-group">
+              <sinfo_flow_depth_development description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:element name="${facet_name}">
+                    <dc:attribute name="factory" value="sinfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
+                  </dc:element>
+                </dc:for-each>
+              </sinfo_flow_depth_development>
+            </dc:call-macro>
+          </sinfo_flow_depth_developments>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="sinfo_tkh">
+      <dc:filter
+        expr="$a_state = 'state.sinfo.transport_bodies_heights' and
+                    ( $facet_name = 'sinfo_facet_tkh' or
+                      $facet_name = 'sinfo_facet_flow_depth' or $facet_name = 'sinfo_facet_flow_depth.filtered' or
+                      $facet_name = 'sinfo_facet_velocity' or $facet_name = 'sinfo_facet_velocity.filtered' or
+                      $facet_name = 'sinfo_facet_tau' or $facet_name = 'sinfo_facet_tau.filtered' or
+                      $facet_name = 'sinfo_facet_d50' or $facet_name = 'sinfo_facet_d50.filtered' )">
+        <dc:if test="dc:has-result()">
+          <sinfo_tkhs>
+            <dc:call-macro name="collection-group">
+              <sinfo_tkh description="{dc:group-key()}">
+                <dc:for-each>
+                  <dc:element name="${facet_name}">
+                    <dc:attribute name="factory" value="sinfo" />
+                    <dc:attribute name="target_out" value="${out}" />
+                    <dc:attribute name="description" value="${facet_description}" />
+                    <dc:attribute name="ids" value="${facet_num}" />
+                    <dc:attribute name="artifact-id" value="${a_gid}" />
+                    <dc:attribute name="out" value="${out_name}" />
+                  </dc:element>
+                </dc:for-each>
+              </sinfo_tkh>
+            </dc:call-macro>
+          </sinfo_tkhs>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="sinfo_collision">
+      <dc:filter expr="$a_state = 'state.sinfo.collision'">
+        <dc:if test="dc:has-result()">
+          <sinfo_collision>
+            <dc:for-each>
+              <dc:element name="${facet_name}">
+                <dc:attribute name="factory" value="sinfo" />
+                <dc:attribute name="target_out" value="${out}" />
+                <dc:attribute name="description" value="${facet_description}" />
+                <dc:attribute name="ids" value="${facet_num}" />
+                <dc:attribute name="artifact-id" value="${a_gid}" />
+                <dc:attribute name="out" value="${out_name}" />
+              </dc:element>
+            </dc:for-each>
+          </sinfo_collision>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+
+    <dc:macro name="sinfo_flood_duration">
+      <dc:filter expr="$a_state = 'state.sinfo.flood_duration'">
+        <dc:if test="dc:has-result()">
+          <sinfo_flood_duration>
+            <dc:for-each>
+              <dc:element name="${facet_name}">
+                <dc:attribute name="factory" value="sinfo" />
+                <dc:attribute name="target_out" value="${out}" />
+                <dc:attribute name="description" value="${facet_description}" />
+                <dc:attribute name="ids" value="${facet_num}" />
+                <dc:attribute name="artifact-id" value="${a_gid}" />
+                <dc:attribute name="out" value="${out_name}" />
+              </dc:element>
+            </dc:for-each>
+          </sinfo_flood_duration>
+        </dc:if>
+      </dc:filter>
+    </dc:macro>
+    <!-- channel size imported from CSV-files for S-INFO -->
+    <dc:macro name="sinfo_predefined_channel">
+      <dc:context>
+        <dc:statement>
+          SELECT s.id AS id, MIN(s.filename) AS seriesname, MIN(v.station) AS km_min, MAX(v.station) AS km_max,
+          MIN(s.filename) || '&lt;br /&gt;'
+          || MIN(s.kmrange_info) || ']&lt;br /&gt;'
+          || MIN(s.year_from) || ' - ' || MIN(s.year_to) || '&lt;br /&gt;' AS info
+          FROM channel s
+          INNER JOIN channel_values v ON s.id=v.channel_id
+          WHERE (s.river_id=${river_id})
+          AND (v.station BETWEEN ${fromkm}-0.0001 AND ${tokm}+0.0001)
+          GROUP BY s.id
+          ORDER BY MIN(s.year_to) DESC
+        </dc:statement>
+        <dc:if test="dc:has-result()">
+          <dc:for-each>
+            <channelseries name="{$seriesname}" ids="channelx-{$id}-{$seriesname}" factory="channelf" target_out="{$out}" info="{$info}" />
+          </dc:for-each>
+        </dc:if>
+      </dc:context>
+    </dc:macro>
+
+    <!-- tkh imported from CSV-files for S-INFO -->
+    <dc:macro name="sinfo_predefined_tkh-berechnung">
+      <predefined_tkh_berechnung>
+        <dc:variable name="tkh_groupname" expr="'berechnung'" />
+        <dc:call-macro name="sinfo_predefined_tkh" />
+      </predefined_tkh_berechnung>
+    </dc:macro>
+
+    <dc:macro name="sinfo_predefined_tkh-messung">
+      <predefined_tkh_messung>
+        <dc:variable name="tkh_groupname" expr="'messung'" />
+        <dc:call-macro name="sinfo_predefined_tkh" />
+      </predefined_tkh_messung>
+    </dc:macro>
+
+    <dc:macro name="sinfo_predefined_tkh">
+      <dc:context>
+        <dc:statement>
+          SELECT sc.tkh_id AS tkh_id, sc.id AS tkh_col_id, MIN(sc.name) AS tkh_col_name,
+          MIN(s.filename) AS tkh_name, MIN(v.station) AS km_min, MAX(v.station) AS km_max,
+          MIN(s.filename) || '&lt;br /&gt;'
+          || MIN(s.kmrange_info) || ']&lt;br /&gt;'
+          || MIN(s.sounding_info) || '&lt;br /&gt;'
+          || MIN(s.evaluation_by) AS info
+          FROM tkh_column sc
+          INNER JOIN tkh s ON sc.tkh_id=s.id
+          INNER JOIN tkh_values v ON sc.id=v.tkh_column_id
+          WHERE (s.river_id=${river_id})
+          AND (lower(s.groupname)=${tkh_groupname})
+          AND (v.station BETWEEN ${fromkm}-0.0001 AND ${tokm}+0.0001)
+          GROUP BY sc.tkh_id, sc.id
+          ORDER BY sc.id
+        </dc:statement>
+        <dc:if test="dc:has-result()">
+          <dc:group expr="$tkh_name">
+            <tkhx name="{dc:group-key()}">
+              <dc:for-each>
+                <tkhcolumn name="{$tkh_col_name}" ids="tkhx-{$tkh_col_id}-{$tkh_id}" factory="tkhxf" target_out="{$out}" info="{$info}" />
+              </dc:for-each>
+            </tkhx>
+          </dc:group>
+        </dc:if>
+      </dc:context>
+    </dc:macro>
+
+    <!-- depth_evolution imported from CSV-files for S-INFO -->
+    <dc:macro name="sinfo_predefined_depthevol-aktuell">
+      <predefined_depthevol_aktuell>
+        <dc:variable name="depthevol_groupname" expr="'aktuell'" />
+        <dc:call-macro name="sinfo_predefined_depthevol" />
+      </predefined_depthevol_aktuell>
+    </dc:macro>
+
+    <dc:macro name="sinfo_predefined_depthevol-etappe">
+      <predefined_depthevol_etappe>
+        <dc:variable name="depthevol_groupname" expr="'etappe'" />
+        <dc:call-macro name="sinfo_predefined_depthevol" />
+      </predefined_depthevol_etappe>
+    </dc:macro>
+
+    <dc:macro name="sinfo_predefined_depthevol">
+      <dc:context>
+        <dc:statement>
+          SELECT s.id AS depthevol_id, MIN(s.filename) AS depthevol_name, MIN(v.station) AS km_min, MAX(v.station) AS km_max,
+          MIN(s.filename) || '&lt;br /&gt;'
+          || MIN(s.kmrange_info) || ']&lt;br /&gt;'
+          || MIN(s.start_year) || ' - ' || MIN(s.reference_year) || '&lt;br /&gt;'
+          || MIN(s.old_sounding) || ' - ' || MIN(s.curr_sounding) || '&lt;br /&gt;'
+          || MIN(s.old_glw) || ' - ' ||
+          MIN(s.curr_glw) AS info
+          FROM depth_evolution s
+          INNER JOIN depth_evolution_values v ON s.id=v.depth_evolution_id
+          WHERE (s.river_id=${river_id})
+          AND (lower(s.groupname)=${depthevol_groupname})
+          AND (v.station BETWEEN ${fromkm}-0.0001 AND ${tokm}+0.0001)
+          GROUP BY s.id
+          ORDER BY s.id
+        </dc:statement>
+        <dc:for-each>
+          <depth_evol name="{$depthevol_name}" ids="depthevolx-{$depthevol_id}-{$depthevol_name}" factory="depthevolxf" target_out="{$out}" info="{$info}" />
+        </dc:for-each>
+      </dc:context>
+    </dc:macro>
+
+    <!-- flow depth imported from CSV-files for S-INFO -->
+    <dc:macro name="sinfo_predefined_flowdepth-m">
+      <dc:call-macro name="sinfo_predefined_flowdepth-m1" />
+    </dc:macro>
+
+    <dc:macro name="sinfo_predefined_flowdepth-m1">
+      <dc:context>
+        <dc:statement>
+          SELECT sc.flow_depth_id AS flowdepth_id, sc.id AS flowdepth_col_id, MIN(sc.name) AS flowdepth_col_name,
+          MIN(s.filename) AS flowdepth_name, MIN(v.station) AS km_min, MAX(v.station) AS km_max,
+          MIN(s.filename) || '&lt;br /&gt;'
+          || MIN(s.kmrange_info) || ']&lt;br /&gt;'
+          || MIN(s.sounding_info) || '&lt;br /&gt;'
+          || MIN(s.evaluation_by) AS info
+          FROM flow_depth_column sc
+          INNER JOIN flow_depth s ON sc.flow_depth_id=s.id
+          INNER JOIN flow_depth_values v ON sc.id=v.flow_depth_column_id
+          WHERE (s.river_id=${river_id})
+          AND (v.station BETWEEN ${fromkm}-0.0001 AND ${tokm}+0.0001)
+          GROUP BY sc.flow_depth_id, sc.id
+          ORDER BY sc.id
+        </dc:statement>
+        <dc:if test="dc:has-result()">
+          <dc:group expr="$flowdepth_name">
+            <sinfo_predefined_flowdepth>
+              <dc:for-each>
+                <flowdepthcolumn name="{$flowdepth_col_name}" ids="flowdepthx-{$flowdepth_col_id}-{$flowdepth_id}" factory="flowdepthxf" target_out="{$out}" info="{$info}" />
+              </dc:for-each>
+            </sinfo_predefined_flowdepth>
+          </dc:group>
+        </dc:if>
+      </dc:context>
+    </dc:macro>
+
+    <!-- infrastructure height imported from CSV-files for S-INFO -->
+    <dc:macro name="sinfo_infrastructure">
+      <dc:context>
+        <dc:statement>
+          SELECT s.id AS id, MIN(s.filename) AS seriesname, MIN(v.station) AS km_min, MAX(v.station) AS km_max,
+          MIN(x.name) AS typename,
+          MIN(s.filename) || '&lt;br /&gt;'
+          || MIN(s.kmrange_info) || '&lt;br /&gt;'
+          || MIN(s.year) || '&lt;br /&gt;' AS info
+          FROM infrastructure s
+          INNER JOIN infrastructure_values v ON s.id=v.infrastructure_id
+          INNER JOIN annotation_types x ON
+          s.annotation_type_id=x.id
+          WHERE (s.river_id=${river_id})
+          AND (v.station BETWEEN ${fromkm}-0.0001 AND ${tokm}+0.0001)
+          GROUP BY s.id
+          ORDER BY MIN(s.filename) DESC
+        </dc:statement>
+        <dc:if test="dc:has-result()">
+          <dc:for-each>
+            <infrastructureseries name="{$seriesname}" ids="infrastructurex-{$id}-{$seriesname}" factory="infrastructuref" target_out="{$out}" info="{$info}" />
+          </dc:for-each>
+        </dc:if>
+      </dc:context>
+    </dc:macro>
+
+    <!-- collisions imported from CSV-files for S-INFO -->
+    <dc:macro name="sinfo_collisions">
+      <dc:context>
+        <dc:statement>
+          SELECT s.id AS id, MIN(s.filename) AS seriesname, MIN(v.station) AS km_min, MAX(v.station) AS km_max, MIN(s.year) AS year,
+          MIN(s.filename) || '&lt;br /&gt;'
+          || MIN(s.kmrange_info) || '&lt;br /&gt;'
+          || MIN(s.year) || '&lt;br /&gt;' AS info
+          FROM collision s
+          INNER JOIN collision_values v ON s.id=v.collision_id
+          WHERE (s.river_id=${river_id})
+          AND (v.station BETWEEN ${fromkm}-0.0001 AND ${tokm}+0.0001)
+          GROUP BY s.id
+          ORDER BY MIN(s.year)
+        </dc:statement>
+        <dc:if test="dc:has-result()">
+          <dc:for-each>
+            <collisionseries name="{$seriesname}" ids="collisionx-{$id}-{$year}-{$seriesname}" factory="collisionf" target_out="{$out}" info="{$info}" />
+          </dc:for-each>
+        </dc:if>
+      </dc:context>
     </dc:macro>
 
   </datacage>
-</dc:template>
+</dc:template>
\ No newline at end of file
--- a/artifacts/doc/conf/modules.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/modules.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -1,19 +1,43 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <modules>
   <module name="winfo" selected="true">
-    <river name="Beispielfluss"/>
-  </module>
-  <module name="minfo">
-    <river name="Beispielfluss"/>
-  </module>
-  <module name="new_map">
-    <river name="Beispielfluss"/>
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
   </module>
-  <module name="new_chart">
-    <river name="Beispielfluss"/>
+  <module name="uinfo" group="module.group.ingwerds">
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
   </module>
-  <module name="fixanalysis">
-    <river name="Beispielfluss"/>
+  <module name="minfo" group="module.group.ingwerds">
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
   </module>
-</modules>
-
+  <module name="sinfo" group="module.group.ingwerds">
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
+  </module>
+  <module name="bundu" group="module.group.ingwerds">
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
+  </module>
+  <module name="new_map" group="module.group.bottom">
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
+  </module>
+  <module name="new_chart" group="module.group.bottom">
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
+  </module>
+  <module name="fixanalysis" group="module.group.bottom">
+    <river name="Beispielfluss" />
+    <river name="Elbe" />
+    <river name="Rhein" />
+  </module>
+</modules>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/sinfo_tkh_sohlhoehen_Beispielfluss.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,15 @@
+# Konfigurationsdatei f\u00fcr die in der Berechnungsart SINFO-Transportk\u00f6rperh\u00f6hen zu verwendenden Sohlh\u00f6hen.
+# Je Gew\u00e4sser ist eine Datei mit Namen "sinfo_tkh_sohlhoehen_<Gew\u00e4ssername>.properties" anzulegen. Gro\u00df-/Kleinschriebung beim Gew\u00e4ssernamen ist zu beachten!
+# Die Datei ist im Charset 'ISO-8859-1' zu kodieren.
+
+# Die Datei definiert die Standardm\u00e4\u00dfig zu verwendenden Sohlh\u00f6hen und deren G\u00fcltigkeitsbereiche.
+# Pro Sohlh\u00f6he ist eine Zeile folgender Form anzulegen:
+# <Sohlh\u00f6he> = <von km>;<bis km>
+
+# 'Sohlh\u00f6he' entspricht dem Feld 'description' in der Tabelle 'bed_height' der D4E Datenbank.  
+# 'von km' entpsricht dem Start des G\u00fcltigkeitsbereichs in km
+# 'bis km' entpsricht dem Ende des G\u00fcltigkeitsbereichs in km
+
+# Der G\u00fcltigkeitsbereich schr\u00e4nkt den zu verwendenden Daten bereich der Sohlh\u00f6he f\u00fcr die TKH Berechnung ein, die Daten in der Datenbank k\u00f6nnen einen gr\u00f6\u00dferen G\u00fcltigkeitsbereich besitzen.
+# Leerzeichen im Namen der Sohlh\u00f6he m\u00fcssen mit u0020 kodiert werden.
+DGM-2004_Epoche-2-SOBEK = 0.0;182.4
--- a/artifacts/doc/conf/themes.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/themes.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -404,6 +404,69 @@
 
         <!-- Mappings for porosity from backend-DB -->
         <mapping from="porosity" to="Porosity" />
+
+        <!--  Mappings for S-INFO -->
+        <mapping from="bedheight_min" to="SInfoBedHeightMin" />
+        <mapping from="bedheight_max" to="SInfoBedHeightMax" />
+        
+        <mapping from="sinfo_facet_flow_depth" to="SInfoFlowDepth" />
+        <mapping from="sinfo_facet_flow_depth.filtered" to="SInfoFlowDepth" />
+        <mapping from="sinfo_facet_flow_depth_with_tkh" to="SInfoFlowDepthWithTkh" />
+        <mapping from="sinfo_facet_flow_depth_with_tkh.filtered" to="SInfoFlowDepthWithTkh" />
+        <mapping from="sinfo_facet_flow_depth_min" to="SInfoFlowDepthMin" />
+        <mapping from="sinfo_facet_flow_depth_min.filtered" to="SInfoFlowDepthMin" />
+        <mapping from="sinfo_facet_flow_depth_max" to="SInfoFlowDepthMax" />
+        <mapping from="sinfo_facet_flow_depth_max.filtered" to="SInfoFlowDepthMax" />
+
+        <mapping from="sinfo_facet_flow_depth_current" to="SInfoFlowDepthCurrent" />
+        <mapping from="sinfo_facet_flow_depth_current.filtered" to="SInfoFlowDepthCurrent" />
+        <mapping from="sinfo_facet_flow_depth_historical" to="SInfoFlowDepthHistorical" />
+        <mapping from="sinfo_facet_flow_depth_historical.filtered" to="SInfoFlowDepthHistorical" />
+
+        <mapping from="sinfo_facet_tkh" to="SInfoTkh" />
+
+        <mapping from="sinfo_facet_d50" to="BedDiameterTopLines" />
+        <mapping from="sinfo_facet_tau" to="FlowVelocityTau" />
+        <mapping from="sinfo_facet_velocity" to="FlowVelocityVMainChannel" />
+
+        <mapping from="sinfo_facet_flow_depth_current" to="FlowVelocityVMainChannel" />
+        <mapping from="sinfo_facet_flow_depth_current.filtered" to="FlowVelocityVMainChannel" />
+        <mapping from="sinfo_facet_flow_depth_historical" to="FlowVelocityVMainChannel" />
+        <mapping from="sinfo_facet_flow_depth_historical.filtered" to="FlowVelocityVMainChannel" />
+
+        <mapping from="sinfo_facet_flow_depth_development" to="SInfoFlowDepthDevelopment" />
+        <mapping from="sinfo_facet_flow_depth_development.filtered" to="SInfoFlowDepthDevelopment" />
+        <mapping from="sinfo_facet_flow_depth_development_per_year" to="SInfoFlowDepthDevelopmentPerYear" />
+        <mapping from="sinfo_facet_flow_depth_development_per_year.filtered" to="SInfoFlowDepthDevelopmentPerYear" />
+        <mapping from="sinfo_facet_waterlevel_difference.filtered" to="SInfoWaterlevelDifference" />
+        <mapping from="sinfo_facet_bedheight_difference.filtered" to="SInfoBedHeightDifference" />
+        
+        <mapping from="sinfo_facet_collision_calc_count" to="SInfoCollisionCount" />
+        <mapping from="sinfo_facet_collision_calc_count.2" to="SInfoCollisionCount2" />
+        <mapping from="sinfo_facet_collision_calc_count.3" to="SInfoCollisionCount3" />
+        
+        <mapping from="sinfo_facet_flood_duration.left" to="SInfoFloodDurationLeft" />
+        <mapping from="sinfo_facet_flood_duration.right" to="SInfoFloodDurationRight" />
+        <mapping from="mainvalue.duration" to="SInfoMainValues" /> 
+        <mapping from="sinfo_facet_flood_height.left" to="SInfoInfrastructureHeightLeft" />
+        <mapping from="sinfo_facet_flood_height.right" to="SInfoInfrastructureHeightRight" />
+        <mapping from="mainvalue.w" to="SInfoMainValues" />
+        
+        <mapping from="sinfo_facet_predefined_channel_width" to="SInfoPredefinedChannelWidth" />
+        <mapping from="sinfo_facet_predefined_channel_depth" to="SInfoPredefinedChannelDepth" />
+        <mapping from="sinfo_facet_predefined_tkh" to="SInfoPredefinedTkh" />
+        <mapping from="sinfo_facet_predefined_depthevol" to="SInfoPredefinedDepthEvol" />
+        <mapping from="sinfo_facet_predefined_depthevol_per_year" to="SInfoPredefinedDepthEvolPerYear" />
+        <mapping from="sinfo_facet_predefined_flowdepth" to="SInfoPredefinedFlowDepth" />
+        <mapping from="sinfo_facet_infrastructure_height" to="SInfoInfrastructureHeight" />
+        <mapping from="sinfo_facet_collision_count" to="SInfoCollisionCount" />
+
+        <mapping from="sinfo_flow_depth.manualpoints" to="ManualPoints" />
+        <mapping from="sinfo_flow_depth_minmax.manualpoints" to="ManualPoints" />
+        <mapping from="sinfo_flow_depth_development.manualpoints" to="ManualPoints" />
+        <mapping from="sinfo_flow_depth_development_peryear.manualpoints" to="ManualPoints" />
+        <mapping from="sinfo_tkk.manualpoints" to="ManualPoints" />
+        <mapping from="sinfo_collision.manualpoints" to="ManualPoints" />
+        <mapping from="sinfo_flood_duration.manualpoints" to="ManualPoints" />
     </mappings>
-
-</themes>
+</themes>
\ No newline at end of file
--- a/artifacts/doc/conf/themes/default.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/themes/default.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -1,2875 +1,2886 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <themegroup name="default">
-    <theme name="MainValuesQ">
-        <inherits>
-            <inherit from="Lines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Farbe"
-                default="200, 0, 15" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showlinelabel" type="boolean"
-                display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="MainValuesW">
-        <inherits>
-            <inherit from="Lines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Farbe"
-                default="0, 215, 0" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showlinelabel" type="boolean"
-                display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="RelativePoint">
-        <inherits>
-            <inherit from="Points" />
-        </inherits>
-    </theme>
-
-    <theme name="Annotations">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Text" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
-
-    <theme name="ManualPoints">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" hints="hidden" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-    <theme name="WKms">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-    <theme name="WKmsAnnotation">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="WQKms">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="WQKmsHorizontal">
-        <inherits>
-            <inherit from="WQKms" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-
-    <theme name="WQPoints">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Linienfarbe"
-                default="204, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="heightmarks_points">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="Area">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <!-- top level classes defining additional attributes-->
-    <theme name="LongitudinalSection">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="bandwidth" type="double" display="Bandbreite"
-                default="0"/>
-            <field name="bandwidthcolor" type="Color" display="Bandbreitenfarbe"
-                default="104, 104, 104"/>
-            <field name="transparency" type="int" default="20" display="Transparenz"/>
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionPoints">
-        <inherits>
-            <inherit from="Points" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
-
-    <theme name="Differences">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-
-    <!-- Classes defining special values -->
-    <theme name="LongitudinalSectionW_HQ1">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ2">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ5">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 153, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ10">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ20">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ25">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 51, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ50">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ100">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ200">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 100, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ300">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 100" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ500">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ1000">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQRZ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HSQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="253, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MHQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 255, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MNQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 51, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_NQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 204, 255" />
-        </fields>
-    </theme>
+  <theme name="MainValuesQ">
+    <inherits>
+      <inherit from="Lines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Farbe" default="200, 0, 15" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionW_HQExtrem">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ1_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ2_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ5_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 153, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ10_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ20_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="153, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ25_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 51, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ50_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 153, 153" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ100_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ200_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ300_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 100, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ500_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ1000_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQRZ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HSQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="253, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MHQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 255, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MNQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 51, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_NQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="153, 204, 255" />
-        </fields>
-    </theme>
+  <theme name="MainValuesW">
+    <inherits>
+      <inherit from="Lines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Farbe" default="0, 215, 0" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionW_HQExtrem_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ1">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ2">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ5">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 153, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ10">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ20">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ25">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 51, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ50">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 153, 153" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ100">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ200">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
+  <theme name="RelativePoint">
+    <inherits>
+      <inherit from="Points" />
+    </inherits>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_HQ300">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 100, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ500">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ1000">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQRZ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HSQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="253, 153, 0" />
-        </fields>
-    </theme>
+  <theme name="Annotations">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Text" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_MHQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 255, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_MNQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 255" />
-        </fields>
-    </theme>
+  <theme name="ManualPoints">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" hints="hidden" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_MQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 51, 204" />
-        </fields>
-    </theme>
+  <theme name="WKms">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_NQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 204, 255" />
-        </fields>
-    </theme>
+  <theme name="WKmsAnnotation">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_HQExtrem">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
+  <theme name="WQKms">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
 
-    <theme name="DischargeLongitudinalSectionW">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
+  <theme name="WQKmsHorizontal">
+    <inherits>
+      <inherit from="WQKms" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
 
-    <theme name="DischargeLongitudinalSectionC">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0 , 0" />
-        </fields>
-    </theme>
-
-    <theme name="DischargeLongitudinalSectionQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQInfoldCut">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 102, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQInfolding">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="51, 51, 51" />
-        </fields>
-    </theme>
-
-    <!-- MIDDLE BED HEIGHT -->
-    <theme name="MiddleBedHeightSingle">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen"
-                default="true" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="1" />
-            <field name="linetype" type="Dash" display="Linienart"
-                default="10" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" />
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <!-- Bed Quality -->
-    <theme name="PorosityTopPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="PorositySubPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="DensityTopPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="DensitySubPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterTopPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterSubPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedLoadDiameterPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="PorosityTopLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="PorositySubLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="DensityTopLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="DensitySubLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterTopLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterSubLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedLoadDiameterLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterDataTop">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="2" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterDataSub">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="2" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
-        </fields>
-    </theme>
-
-    <theme name="BedloadDiameterData">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="2" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="100, 0, 0" />
-        </fields>
-    </theme>
-    <!-- Bedheight differences -->
-    <theme name="BedheightDiffYear">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffMorphWidth">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffEpoch">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 0, 204" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffAbsHeight1">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 0, 204" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffAbsHeight2">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 100, 100" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffHeightYear">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="MorphologicWidth">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-    <!-- Flow velocity -->
-    <theme name="FlowVelocityVMainChannel">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="FlowVelocityVTotalChannel">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="FlowVelocityTau">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="FlowVelocityDischarge">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 0" />
-        </fields>
-    </theme>
-
-    <!-- Sediment load longitudinal sections, M^3/A -->
-    <theme name="SedimentLoadLSM3A">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" default="2" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ACoarse">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
+  <theme name="WQPoints">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Linienfarbe" default="204, 0, 0" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadLSM3AFineMid">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASand">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASuspSand">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASediment">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASuspSandBed">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ATotal">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ABed">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ABedSusp">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASusp">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
-
-    <!-- Sediment load longitudinal sections, T/A -->
-    <theme name="SedimentLoadLSTACoarse">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTAFineMid">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASand">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASuspSand">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASediment">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASuspSandBed">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTATotal">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTABed">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTABedSusp">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASusp">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
-
-    <!-- Sediment load at measurement stations, T/A -->
-    <theme name="SedimentLoad">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linetype" type="Dash" default="10,5" />
-            <field name="showpoints" type="boolean" default="true" />
-            <field name="pointsize" type="int" default="3" />
-        </fields>
-    </theme>
+  <theme name="heightmarks_points">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadTACoarse">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-            <field name="pointcolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTAFineMid">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-            <field name="pointcolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASand">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-            <field name="pointcolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASuspSand">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-            <field name="pointcolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASediment">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-            <field name="pointcolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASuspSandBed">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="pointcolor" type="Color" default="0, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTATotal">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="pointcolor" type="Color" default="0, 100, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTABed">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-            <field name="pointcolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTABedSusp">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-            <field name="pointcolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASusp">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-            <field name="pointcolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="Area">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
 
-    <!-- Sediment load at measurement stations, M3/A -->
-    <theme name="SedimentLoadM3A">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" default="2" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ACoarse">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-            <field name="pointcolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3AFineMid">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-            <field name="pointcolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASand">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-            <field name="pointcolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASuspSand">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-            <field name="pointcolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
+  <!-- top level classes defining additional attributes -->
+  <theme name="LongitudinalSection">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadM3ASediment">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-            <field name="pointcolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASuspSandBed">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="pointcolor" type="Color" default="0, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="LongitudinalSectionW">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="bandwidth" type="double" display="Bandbreite" default="0" />
+      <field name="bandwidthcolor" type="Color" display="Bandbreitenfarbe" default="104, 104, 104" />
+      <field name="transparency" type="int" default="20" display="Transparenz" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadM3ATotal">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="pointcolor" type="Color" default="0, 100, 200" />
-        </fields>
-    </theme>
+  <theme name="LongitudinalSectionPoints">
+    <inherits>
+      <inherit from="Points" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadM3ABed">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-            <field name="pointcolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ABedSusp">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-            <field name="pointcolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASusp">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-            <field name="pointcolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="Differences">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
 
 
-    <theme name="LongitudinalSectionArea">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
+  <!-- Classes defining special values -->
+  <theme name="LongitudinalSectionW_HQ1">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ2">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ5">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 153, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ10">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ20">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ25">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 51, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ50">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ100">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ200">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 100, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ300">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 100" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ500">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ1000">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQRZ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HSQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="253, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MHQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MNQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 51, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_NQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 204, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQExtrem">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ1_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ2_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ5_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 153, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ10_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ20_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ25_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 51, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ50_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 153, 153" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ100_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ200_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ300_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 100, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ500_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ1000_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQRZ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HSQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="253, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MHQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MNQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 51, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_NQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 204, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQExtrem_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ1">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ2">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ5">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 153, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ10">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ20">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ25">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 51, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ50">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 153, 153" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ100">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ200">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ300">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 100, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ500">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ1000">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQRZ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HSQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="253, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_MHQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_MNQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_MQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 51, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_NQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 204, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQExtrem">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="DischargeLongitudinalSectionW">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+
+  <theme name="DischargeLongitudinalSectionC">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0 , 0" />
+    </fields>
+  </theme>
+
+  <theme name="DischargeLongitudinalSectionQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQInfoldCut">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 102, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQInfolding">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="51, 51, 51" />
+    </fields>
+  </theme>
+
+  <!-- MIDDLE BED HEIGHT -->
+  <theme name="MiddleBedHeightSingle">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="true" />
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+      <field name="linetype" type="Dash" display="Linienart" default="10" />
+      <field name="linecolor" type="Color" display="Linienfarbe" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <!-- Bed Quality -->
+  <theme name="PorosityTopPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="PorositySubPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="DensityTopPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="DensitySubPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterTopPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterSubPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedLoadDiameterPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="PorosityTopLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="PorositySubLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="DensityTopLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="DensitySubLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterTopLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterSubLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedLoadDiameterLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterDataTop">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterDataSub">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
+    </fields>
+  </theme>
+
+  <theme name="BedloadDiameterData">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="100, 0, 0" />
+    </fields>
+  </theme>
+  <!-- Bedheight differences -->
+  <theme name="BedheightDiffYear">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffMorphWidth">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffEpoch">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 0, 204" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffAbsHeight1">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 0, 204" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffAbsHeight2">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 100, 100" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffHeightYear">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="MorphologicWidth">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+  <!-- Flow velocity -->
+  <theme name="FlowVelocityVMainChannel">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="FlowVelocityVTotalChannel">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="FlowVelocityTau">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="FlowVelocityDischarge">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load longitudinal sections, M^3/A -->
+  <theme name="SedimentLoadLSM3A">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ACoarse">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3AFineMid">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASand">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASuspSand">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASediment">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASuspSandBed">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ATotal">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ABed">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ABedSusp">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASusp">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load longitudinal sections, T/A -->
+  <theme name="SedimentLoadLSTACoarse">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTAFineMid">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASand">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASuspSand">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASediment">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASuspSandBed">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTATotal">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTABed">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTABedSusp">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASusp">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load at measurement stations, T/A -->
+  <theme name="SedimentLoad">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linetype" type="Dash" default="10,5" />
+      <field name="showpoints" type="boolean" default="true" />
+      <field name="pointsize" type="int" default="3" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTACoarse">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+      <field name="pointcolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTAFineMid">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+      <field name="pointcolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASand">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+      <field name="pointcolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASuspSand">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+      <field name="pointcolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASediment">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+      <field name="pointcolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASuspSandBed">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="pointcolor" type="Color" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTATotal">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="pointcolor" type="Color" default="0, 100, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTABed">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+      <field name="pointcolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTABedSusp">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+      <field name="pointcolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASusp">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+      <field name="pointcolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load at measurement stations, M3/A -->
+  <theme name="SedimentLoadM3A">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ACoarse">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+      <field name="pointcolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3AFineMid">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+      <field name="pointcolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASand">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+      <field name="pointcolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASuspSand">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+      <field name="pointcolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASediment">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+      <field name="pointcolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASuspSandBed">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="pointcolor" type="Color" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ATotal">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="pointcolor" type="Color" default="0, 100, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ABed">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+      <field name="pointcolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ABedSusp">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+      <field name="pointcolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASusp">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+      <field name="pointcolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+
+  <theme name="LongitudinalSectionArea">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
 
 
 
-    <theme name="CrossSection">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="CrossSectionWaterLine">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0,0,153" />
-            <field name="showwidth" type="boolean" display="Breite anzeigen"
-                default="false" />
-            <field name="showlevel" type="boolean" display="Wasserstand anzeigen"
-                default="true" />
-            <field name="showlinelabel" type="boolean" default="true"
-                display="Beschriftung anzeigen" />
-            <field name="showmiddleheight" type="boolean"
-                display="Wasserstand anzeigen" default="false" />
-        </fields>
-    </theme>
-
-    <theme name="Hyk">
-        <inherits>
-            <inherit from="Text" />
-        </inherits>
-        <fields>
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-    <theme name="CrossSectionArea">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-
-
-    <theme name="DischargeCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 153" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-        </fields>
-    </theme>
-
-    <theme name="ExtremeWQCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showextramark" type="boolean" display="Linie anzeigen ab wo extrapoliert wurde"
-                default="true" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 153" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-            <field name="showlinelabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="ExtremeWQBaseCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="2" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showlinelabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-
-
-    <theme name="DurationCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"
-                hints="hidden"/>
-        </fields>
-    </theme>
-
-    <theme name="DurationCurveW">
-        <inherits>
-            <inherit from="DurationCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0,51,204" />
-        </fields>
-    </theme>
-
-    <theme name="DurationCurveQ">
-        <inherits>
-            <inherit from="DurationCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0,204,0" />
-        </fields>
-    </theme>
-
-
-
-    <theme name="FixPoints">
-        <inherits>
-            <inherit from="ColorfulPoints" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="true" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="FixLines">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" hints="hidden" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-        </fields>
-    </theme>
-
-    <theme name="FixAreas">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingCalculatedPoint">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 0" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="5"/>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingWQCurve">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="227, 27, 162" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDerivedCurve">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="227, 27, 162" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" hints="hidden" hidden="true" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="5" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorAverageWQ0">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 128, 0" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
+  <theme name="CrossSection">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="FixingSectorAverageWQ1">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 255" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorAverageWQ2">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 255" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorAverageWQ3">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 0" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingAnalysisEventsWQ">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 255, 0" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingReferenceEvents">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 80, 160" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingOutliers">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden"/>
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="true" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage0">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 128, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage1">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage2">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage3">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAnalysis">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="CrossSectionWaterLine">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0,0,153" />
+      <field name="showwidth" type="boolean" display="Breite anzeigen" default="false" />
+      <field name="showlevel" type="boolean" display="Wasserstand anzeigen" default="true" />
+      <field name="showlinelabel" type="boolean" default="true" display="Beschriftung anzeigen" />
+      <field name="showmiddleheight" type="boolean" display="Wasserstand anzeigen" default="false" />
+    </fields>
+  </theme>
 
-    <theme name="FixingLSAverage0">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 128, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingLSAverage1">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingLSAverage2">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingLSAverage3">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorDeviationLS0">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="0, 128, 0" />
-        </fields>
-    </theme>
-    <theme name="FixingSectorDeviationLS1">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="0, 0, 255" />
-
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorDeviationLS2">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
+  <theme name="Hyk">
+    <inherits>
+      <inherit from="Text" />
+    </inherits>
+    <fields>
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
-    <theme name="FixingSectorDeviationLS3">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixLSDeviation">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="100, 100, 100" />
-        </fields>
-    </theme>
-
-    <theme name="FixLSAnalysis">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixLSReference">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 80, 160" />
-        </fields>
-    </theme>
-
-    <theme name="FixDeltaWtDeviation">
-        <inherits>
-            <inherit from="FixAreas"/>
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" default="0, 0, 0" display="Füllfarbe"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAnalysisPeriods">
-        <inherits>
-            <inherit from="FixAreas"/>
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" default="255, 0, 0" display="Füllfarbe" />
-        </fields>
-    </theme>
-
-    <theme name="FixingReferencePeriod">
-        <inherits>
-            <inherit from="FixAreas"/>
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" default="0, 0, 255" display="Füllfarbe" />
-        </fields>
-    </theme>
-
-    <theme name="QSectors">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="true" hints="hidden" />
-        </fields>
-    </theme>
+  <theme name="CrossSectionArea">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
 
 
 
-    <theme name="MapLines">
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 205" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="3" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="Floodmaps">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="Floodplains">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="Floodmarks">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="WSPLGEN">
-        <inherits>
-            <inherit from="Uesk" />
-        </inherits>
-        <fields>
-            <field name="startcolor" type="Color"
-                display="Farbverlauf Startfarbe" default="178, 201, 215" />
-            <field name="endcolor" type="Color"
-                display="Farbverlauf Endfarbe" default="2, 27, 42" />
-            <field name="numclasses" type="int" display="Anzahl Klassen"
-                default="6" />
-        </fields>
-    </theme>
-
-    <theme name="RiverAxis">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-        <fields>
-       </fields>
-    </theme>
-
-    <theme name="Kms">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Label" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-
-    <theme name="Fixpoints">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="Floodmarks">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-
-    <theme name="GaugeLocation">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="Qps">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="Hws">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="HwsPoints">
-        <inherits>
-            <inherit from="MapLines"/>
-            <inherit from="Label" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="Catchment">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="FloodmapLines">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="140, 200, 130" />
-        </fields>
-    </theme>
-
-    <theme name="Buildings">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="HydrBoundariesLines">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="HydrBoundariesPolys">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="Jetties">
-        <inherits>
-            <inherit from="MapLines"/>
-            <inherit from="Label" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-
+  <theme name="DischargeCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 153" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+    </fields>
+  </theme>
 
-    <theme name="HistoricalDischargeCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 153" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveQ">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveQDiff">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveW">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="100, 100, 153" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveWDiff">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="250, 250, 204" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
+  <theme name="ExtremeWQCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showextramark" type="boolean" display="Linie anzeigen ab wo extrapoliert wurde" default="true" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 153" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+      <field name="showlinelabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="HistoricalDischargeWQW">
-        <!-- the facet has no styling...
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 255" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="1" />
-            <field name="linetype" type="Dash" display="Linienart"
-                default="10" />
-            <field name="showlines" type="boolean" display="Linie anzeigen"
-                default="true" hints="hidden" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>-->
-    </theme>
-
-    <theme name="HistoricalDischargeWQQ">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="1" />
-            <field name="linetype" type="Dash" display="Linienart"
-                default="10" />
-            <field name="showlines" type="boolean" display="Linie anzeigen"
-                default="true" hints="hidden" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-
-
-    <theme name="ReferenceCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="ReferenceCurveNormalized">
-        <inherits>
-            <inherit from="ReferenceCurve" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
+  <theme name="ExtremeWQBaseCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showlinelabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
 
 
-    <theme name="SQMeasurements">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="SQMeasurementsOverview">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <theme name="SQOutliers">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="SQCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" default="0, 0, 0" />
-            <field name="linesize" type="int" display="Liniendicke" default="2"/>
-        </fields>
-    </theme>
-
-    <theme name="SQMeasurementsA">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsB">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 255, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsC">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsD">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsE">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsF">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 0, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsG">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SQMeasurementsOverviewA">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewB">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 255, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewC">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewD">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewE">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewF">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 0, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewG">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 0, 0" />
-        </fields>
-    </theme>
+  <theme name="DurationCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="SQOutliersA">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="6" />
-            <field name="pointcolor" type="color" default="100, 100, 255" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersB">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="6" />
-            <field name="pointcolor" type="color" default="100, 255, 255" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersC">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="6" />
-            <field name="pointcolor" type="color" default="100, 255, 100" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersD">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="6" />
-            <field name="pointcolor" type="color" default="255, 100, 255" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersE">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="6" />
-            <field name="pointcolor" type="color" default="255, 255, 100" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersF">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="6" />
-            <field name="pointcolor" type="color" default="255, 100, 100" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersG">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="6" />
-            <field name="pointcolor" type="color" default="100, 100, 100" />
-        </fields>
-    </theme>
+  <theme name="DurationCurveW">
+    <inherits>
+      <inherit from="DurationCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0,51,204" />
+    </fields>
+  </theme>
 
-    <theme name="SQOutliersOverviewA">
-        <inherits>
-            <inherit from="SQOutliersA" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewB">
-        <inherits>
-            <inherit from="SQOutliersB" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewC">
-        <inherits>
-            <inherit from="SQOutliersC" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewD">
-        <inherits>
-            <inherit from="SQOutliersD" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewE">
-        <inherits>
-            <inherit from="SQOutliersE" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewF">
-        <inherits>
-            <inherit from="SQOutliersF" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewG">
-        <inherits>
-            <inherit from="SQOutliersG" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
+  <theme name="DurationCurveQ">
+    <inherits>
+      <inherit from="DurationCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0,204,0" />
+    </fields>
+  </theme>
 
-    <theme name="SQCurveA">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="0, 0, 175" />
-        </fields>
-    </theme>
-    <theme name="SQCurveB">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="0, 175, 175" />
-        </fields>
-    </theme>
-    <theme name="SQCurveC">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="0, 175, 0" />
-        </fields>
-    </theme>
-    <theme name="SQCurveD">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 0, 175" />
-        </fields>
-    </theme>
-    <theme name="SQCurveE">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 175, 0" />
-        </fields>
-    </theme>
-    <theme name="SQCurveF">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 0, 0" />
-        </fields>
-    </theme>
-    <theme name="SQCurveG">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 175, 175" />
-        </fields>
-    </theme>
 
-    <theme name="SQOutlierCurveA">
-        <inherits>
-            <inherit from="SQCurveA" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveB">
-        <inherits>
-            <inherit from="SQCurveB" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveC">
-        <inherits>
-            <inherit from="SQCurveC" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveD">
-        <inherits>
-            <inherit from="SQCurveD" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveE">
-        <inherits>
-            <inherit from="SQCurveE" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveF">
-        <inherits>
-            <inherit from="SQCurveF" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveG">
-        <inherits>
-            <inherit from="SQCurveG" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
 
-    <theme name="Porosity">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 175, 175" />
-        </fields>
-    </theme>
-</themegroup>
+  <theme name="FixPoints">
+    <inherits>
+      <inherit from="ColorfulPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="true" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="FixLines">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen" default="false" hints="hidden" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+    </fields>
+  </theme>
+
+  <theme name="FixAreas">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="FixingCalculatedPoint">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+      <field name="pointsize" type="int" display="Punktdicke" default="5" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="FixingWQCurve">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="227, 27, 162" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDerivedCurve">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="227, 27, 162" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen" default="false" hints="hidden" hidden="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="5" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ0">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 128, 0" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ1">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 255" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ2">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 255" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ3">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingAnalysisEventsWQ">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingReferenceEvents">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 80, 160" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingOutliers">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage0">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage1">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage2">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage3">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAnalysis">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage0">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 128, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage1">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage2">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage3">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorDeviationLS0">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="0, 128, 0" />
+    </fields>
+  </theme>
+  <theme name="FixingSectorDeviationLS1">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="0, 0, 255" />
+
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorDeviationLS2">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorDeviationLS3">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixLSDeviation">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="100, 100, 100" />
+    </fields>
+  </theme>
+
+  <theme name="FixLSAnalysis">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixLSReference">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 80, 160" />
+    </fields>
+  </theme>
+
+  <theme name="FixDeltaWtDeviation">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" default="0, 0, 0" display="Füllfarbe" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAnalysisPeriods">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" default="255, 0, 0" display="Füllfarbe" />
+    </fields>
+  </theme>
+
+  <theme name="FixingReferencePeriod">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" default="0, 0, 255" display="Füllfarbe" />
+    </fields>
+  </theme>
+
+  <theme name="QSectors">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="true" hints="hidden" />
+    </fields>
+  </theme>
+
+
+
+  <theme name="MapLines">
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 205" />
+      <field name="linesize" type="int" display="Liniendicke" default="3" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="Floodmaps">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="Floodplains">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="Floodmarks">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="WSPLGEN">
+    <inherits>
+      <inherit from="Uesk" />
+    </inherits>
+    <fields>
+      <field name="startcolor" type="Color" display="Farbverlauf Startfarbe" default="178, 201, 215" />
+      <field name="endcolor" type="Color" display="Farbverlauf Endfarbe" default="2, 27, 42" />
+      <field name="numclasses" type="int" display="Anzahl Klassen" default="6" />
+    </fields>
+  </theme>
+
+  <theme name="RiverAxis">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
+
+  <theme name="Kms">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Label" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+
+  <theme name="Fixpoints">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="Floodmarks">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+
+  <theme name="GaugeLocation">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="Qps">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="Hws">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="HwsPoints">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Label" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="Catchment">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="FloodmapLines">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="140, 200, 130" />
+    </fields>
+  </theme>
+
+  <theme name="Buildings">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="HydrBoundariesLines">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="HydrBoundariesPolys">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="Jetties">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Label" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+
+
+  <theme name="HistoricalDischargeCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 153" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveQ">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveQDiff">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveW">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="100, 100, 153" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveWDiff">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="250, 250, 204" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeWQW">
+    <!-- the facet has no styling...
+      <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="Label" />
+      </inherits>
+      <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe"
+      default="0, 0, 255" />
+      <field name="linesize" type="int" display="Liniendicke"
+      default="1" />
+      <field name="linetype" type="Dash" display="Linienart"
+      default="10" />
+      <field name="showlines" type="boolean" display="Linie anzeigen"
+      default="true" hints="hidden" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
+      default="false" />
+      <field name="pointsize" type="int" display="Punktdicke"
+      default="3" />
+      <field name="showlinelabel" type="boolean"
+      display="Beschriftung anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean"
+      display="Beschriftung anzeigen" default="false" hints="hidden" />
+      </fields> -->
+  </theme>
+
+  <theme name="HistoricalDischargeWQQ">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+      <field name="linetype" type="Dash" display="Linienart" default="10" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="true" hints="hidden" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen" default="false" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+
+
+  <theme name="ReferenceCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="ReferenceCurveNormalized">
+    <inherits>
+      <inherit from="ReferenceCurve" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
+
+
+
+  <theme name="SQMeasurements">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="SQMeasurementsOverview">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutliers">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="SQCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" default="0, 0, 0" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="SQMeasurementsA">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsB">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 255, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsC">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsD">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsE">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsF">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsG">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SQMeasurementsOverviewA">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewB">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 255, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewC">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewD">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewE">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewF">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewG">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutliersA">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="6" />
+      <field name="pointcolor" type="color" default="100, 100, 255" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersB">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="6" />
+      <field name="pointcolor" type="color" default="100, 255, 255" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersC">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="6" />
+      <field name="pointcolor" type="color" default="100, 255, 100" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersD">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="6" />
+      <field name="pointcolor" type="color" default="255, 100, 255" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersE">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="6" />
+      <field name="pointcolor" type="color" default="255, 255, 100" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersF">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="6" />
+      <field name="pointcolor" type="color" default="255, 100, 100" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersG">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="6" />
+      <field name="pointcolor" type="color" default="100, 100, 100" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutliersOverviewA">
+    <inherits>
+      <inherit from="SQOutliersA" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewB">
+    <inherits>
+      <inherit from="SQOutliersB" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewC">
+    <inherits>
+      <inherit from="SQOutliersC" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewD">
+    <inherits>
+      <inherit from="SQOutliersD" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewE">
+    <inherits>
+      <inherit from="SQOutliersE" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewF">
+    <inherits>
+      <inherit from="SQOutliersF" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewG">
+    <inherits>
+      <inherit from="SQOutliersG" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="SQCurveA">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="0, 0, 175" />
+    </fields>
+  </theme>
+  <theme name="SQCurveB">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="0, 175, 175" />
+    </fields>
+  </theme>
+  <theme name="SQCurveC">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="0, 175, 0" />
+    </fields>
+  </theme>
+  <theme name="SQCurveD">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 0, 175" />
+    </fields>
+  </theme>
+  <theme name="SQCurveE">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 175, 0" />
+    </fields>
+  </theme>
+  <theme name="SQCurveF">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SQCurveG">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 175, 175" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutlierCurveA">
+    <inherits>
+      <inherit from="SQCurveA" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveB">
+    <inherits>
+      <inherit from="SQCurveB" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveC">
+    <inherits>
+      <inherit from="SQCurveC" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveD">
+    <inherits>
+      <inherit from="SQCurveD" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveE">
+    <inherits>
+      <inherit from="SQCurveE" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveF">
+    <inherits>
+      <inherit from="SQCurveF" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveG">
+    <inherits>
+      <inherit from="SQCurveG" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+
+  <theme name="Porosity">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 175, 175" />
+    </fields>
+  </theme>
+
+  <!-- S-INFO Data-Themes -->
+  <theme name="SInfoBedHeightMin">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoBedHeightMax">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 0" />
+    </fields>
+  </theme>
+
+  <!-- S-INFO Flow-Depth Themes -->
+  <theme name="SInfoFlowDepth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthWithTkh">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthMin">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthMax">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthCurrent">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 128" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthHistorical">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="51, 102, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoTkh">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+
+      <field name="calculateRange" type="boolean" display="Ausdehnung berechnen" default="true" hints="hidden" />
+
+      <!-- Areas use 'showborder' instead of showlines (but inconsistently uses 'linecolor' and 'linesize'), so we hide 'showline' and replace it with 'showbordder' -->
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="true" hints="hidden" />
+      <field name="showborder" type="boolean" display="Linien anzeigen" default="true" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="228, 108, 10" />
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+
+      <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="false" />
+
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" />
+      <field name="areabgcolor" type="Color" default="245, 245, 220" display="Füllfarbe" />
+      <field name="areabgpattern" type="areapattern" default="patternFill" display="Flächentyp" />
+      <field name="areatransparency" type="int" default="20" />
+
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" hints="hidden" />
+
+      <field name="showmaximum" type="boolean" display="Maximum anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthDevelopment">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthDevelopmentPerYear">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoWaterlevelDifference">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+  <theme name="SInfoBedHeightDifference">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedChannelWidth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="128, 64, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedChannelDepth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="128, 64, 64" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedTkh">
+    <inherits>
+      <inherit from="SInfoTkh" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="128, 64, 10" />
+      <field name="areabgcolor" type="Color" default="255, 240, 224" display="Füllfarbe" />
+      <field name="areabgpattern" type="areapattern" default="patternFill" display="Flächentyp" />
+      <field name="areatransparency" type="int" default="20" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedDepthEvol">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 192" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedDepthEvolPerYear">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 128" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedFlowDepth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="96, 128, 192" />
+    </fields>
+  </theme>
+  <theme name="SInfoInfrastructureHeight">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 192, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoInfrastructureHeightLeft">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="68, 216, 40" />
+    </fields>
+  </theme>
+  <theme name="SInfoInfrastructureHeightRight">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="192, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoCollisionCount">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="64, 192, 64" />
+    </fields>
+  </theme>
+  <theme name="SInfoCollisionCount2">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="192, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoCollisionCount3">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="48, 96, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFloodDurationLeft">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="68, 216, 40" />
+    </fields>
+  </theme>
+  <theme name="SInfoFloodDurationRight">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="192, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoMainValues">
+    <inherits>
+      <inherit from="MainValuesW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Farbe" default="0, 96, 192" />
+    </fields>
+  </theme>
+</themegroup>
\ No newline at end of file
--- a/artifacts/doc/conf/themes/second.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/themes/second.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -1,2872 +1,2874 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <themegroup name="second">
-    <theme name="MainValuesQ">
-        <inherits>
-            <inherit from="Lines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Farbe"
-                default="200, 0, 15" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showlinelabel" type="boolean"
-                display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="MainValuesW">
-        <inherits>
-            <inherit from="Lines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Farbe"
-                default="0, 215, 0" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showlinelabel" type="boolean"
-                display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="RelativePoint">
-        <inherits>
-            <inherit from="Points" />
-        </inherits>
-    </theme>
-
-    <theme name="Annotations">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Text" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
-
-    <theme name="ManualPoints">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" hints="hidden" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-    <theme name="WKms">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-    <theme name="WKmsAnnotation">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="WQKms">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="WQKmsHorizontal">
-        <inherits>
-            <inherit from="WQKms" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-
-    <theme name="WQPoints">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Linienfarbe"
-                default="204, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="heightmarks_points">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="Area">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <!-- top level classes defining additional attributes-->
-    <theme name="LongitudinalSection">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="bandwidth" type="double" display="Bandbreite"
-                default="0"/>
-            <field name="bandwidthcolor" type="Color" display="Bandbreitenfarbe"
-                default="104, 104, 104"/>
-            <field name="transparency" type="int" default="20" display="Transparenz"/>
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionPoints">
-        <inherits>
-            <inherit from="Points" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
-
-    <theme name="Differences">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-
-    <!-- Classes defining special values -->
-    <theme name="LongitudinalSectionW_HQ1">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ2">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ5">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 153, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ10">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ20">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ25">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 51, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ50">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ100">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ200">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 100, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ300">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 100" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ500">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ1000">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQRZ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HSQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="253, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MHQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 255, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MNQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 51, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_NQ">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 204, 255" />
-        </fields>
-    </theme>
+  <theme name="MainValuesQ">
+    <inherits>
+      <inherit from="Lines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Farbe" default="200, 0, 15" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionW_HQExtrem">
-        <inherits>
-            <inherit from="LongitudinalSectionW" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ1_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ2_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ5_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 153, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ10_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ20_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="153, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ25_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 51, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ50_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 153, 153" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ100_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ200_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ300_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 100, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ500_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQ1000_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HQRZ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_HSQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="253, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MHQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="102, 255, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MNQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_MQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 51, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionW_NQ_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="153, 204, 255" />
-        </fields>
-    </theme>
+  <theme name="MainValuesW">
+    <inherits>
+      <inherit from="Lines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Farbe" default="0, 215, 0" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionW_HQExtrem_Points">
-        <inherits>
-            <inherit from="LongitudinalSectionPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ1">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ2">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ5">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 153, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ10">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ20">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 153, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ25">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 51, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ50">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 153, 153" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ100">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 51" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ200">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
+  <theme name="RelativePoint">
+    <inherits>
+      <inherit from="Points" />
+    </inherits>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_HQ300">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 100, 255" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ500">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQ1000">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HQRZ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_HSQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="253, 153, 0" />
-        </fields>
-    </theme>
+  <theme name="Annotations">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Text" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_MHQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 255, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQ_MNQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 255" />
-        </fields>
-    </theme>
+  <theme name="ManualPoints">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" hints="hidden" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_MQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 51, 204" />
-        </fields>
-    </theme>
+  <theme name="WKms">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_NQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 204, 255" />
-        </fields>
-    </theme>
+  <theme name="WKmsAnnotation">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="LongitudinalSectionQ_HQExtrem">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
+  <theme name="WQKms">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
 
-    <theme name="DischargeLongitudinalSectionW">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
+  <theme name="WQKmsHorizontal">
+    <inherits>
+      <inherit from="WQKms" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
 
-    <theme name="DischargeLongitudinalSectionC">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0 , 0" />
-        </fields>
-    </theme>
-
-    <theme name="DischargeLongitudinalSectionQ">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQInfoldCut">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="102, 102, 102" />
-        </fields>
-    </theme>
-
-    <theme name="LongitudinalSectionQInfolding">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="51, 51, 51" />
-        </fields>
-    </theme>
-
-    <!-- MIDDLE BED HEIGHT -->
-    <theme name="MiddleBedHeightSingle">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="MinMaxPoints" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen"
-                default="true" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="1" />
-            <field name="linetype" type="Dash" display="Linienart"
-                default="10" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" />
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <!-- Bed Quality -->
-    <theme name="PorosityTopPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="PorositySubPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="DensityTopPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="DensitySubPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterTopPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterSubPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedLoadDiameterPoints">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 0" />
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="3" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="PorosityTopLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="PorositySubLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="DensityTopLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="DensitySubLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="153, 99, 102" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterTopLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterSubLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedLoadDiameterLines">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterDataTop">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="2" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
-        </fields>
-    </theme>
-
-    <theme name="BedDiameterDataSub">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="2" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
-        </fields>
-    </theme>
-
-    <theme name="BedloadDiameterData">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="showlines" type="boolean" display="Linie anzeigen" default="false"/>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true"/>
-            <field name="pointsize" type="int" display="Punktdicke" default="2" />
-            <field name="pointcolor" type="Color" display="Punktfarbe" default="100, 0, 0" />
-        </fields>
-    </theme>
-    <!-- Bedheight differences -->
-    <theme name="BedheightDiffYear">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffMorphWidth">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 0" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffEpoch">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 0, 204" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffAbsHeight1">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 0, 204" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffAbsHeight2">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 100, 100" />
-        </fields>
-    </theme>
-
-    <theme name="BedheightDiffHeightYear">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="MorphologicWidth">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-    <!-- Flow velocity -->
-    <theme name="FlowVelocityVMainChannel">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="FlowVelocityVTotalChannel">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 102" />
-        </fields>
-    </theme>
-
-    <theme name="FlowVelocityTau">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="FlowVelocityDischarge">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 204, 0" />
-        </fields>
-    </theme>
-
-    <!-- Sediment load longitudinal sections, M^3/A -->
-    <theme name="SedimentLoadLSM3A">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" default="2" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ACoarse">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
+  <theme name="WQPoints">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Linienfarbe" default="204, 0, 0" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadLSM3AFineMid">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASand">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASuspSand">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASediment">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASuspSandBed">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ATotal">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ABed">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ABedSusp">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSM3ASusp">
-        <inherits>
-            <inherit from="SedimentLoadLSM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
-
-    <!-- Sediment load longitudinal sections, T/A -->
-    <theme name="SedimentLoadLSTACoarse">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTAFineMid">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASand">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASuspSand">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASediment">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASuspSandBed">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTATotal">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTABed">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTABedSusp">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadLSTASusp">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
-
-    <!-- Sediment load at measurement stations, T/A -->
-    <theme name="SedimentLoad">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linetype" type="Dash" default="10,5" />
-            <field name="showpoints" type="boolean" default="true" />
-            <field name="pointsize" type="int" default="3" />
-        </fields>
-    </theme>
+  <theme name="heightmarks_points">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadTACoarse">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-            <field name="pointcolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTAFineMid">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-            <field name="pointcolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASand">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-            <field name="pointcolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASuspSand">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-            <field name="pointcolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASediment">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-            <field name="pointcolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASuspSandBed">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="pointcolor" type="Color" default="0, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTATotal">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="pointcolor" type="Color" default="0, 100, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTABed">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-            <field name="pointcolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTABedSusp">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-            <field name="pointcolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadTASusp">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-            <field name="pointcolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="Area">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
 
-    <!-- Sediment load at measurement stations, M3/A -->
-    <theme name="SedimentLoadM3A">
-        <inherits>
-            <inherit from="SedimentLoad" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" default="2" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ACoarse">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-            <field name="pointcolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3AFineMid">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-            <field name="pointcolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASand">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-            <field name="pointcolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASuspSand">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 255, 0" />
-            <field name="pointcolor" type="Color" default="255, 255, 0" />
-        </fields>
-    </theme>
+  <!-- top level classes defining additional attributes -->
+  <theme name="LongitudinalSection">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadM3ASediment">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 255" />
-            <field name="pointcolor" type="Color" default="0, 255, 255" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASuspSandBed">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-            <field name="pointcolor" type="Color" default="0, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="LongitudinalSectionW">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="bandwidth" type="double" display="Bandbreite" default="0" />
+      <field name="bandwidthcolor" type="Color" display="Bandbreitenfarbe" default="104, 104, 104" />
+      <field name="transparency" type="int" default="20" display="Transparenz" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadM3ATotal">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 100, 200" />
-            <field name="pointcolor" type="Color" default="0, 100, 200" />
-        </fields>
-    </theme>
+  <theme name="LongitudinalSectionPoints">
+    <inherits>
+      <inherit from="Points" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
 
-    <theme name="SedimentLoadM3ABed">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="200, 200, 200" />
-            <field name="pointcolor" type="Color" default="200, 200, 200" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ABedSusp">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="150, 255, 150" />
-            <field name="pointcolor" type="Color" default="150, 255, 150" />
-        </fields>
-    </theme>
-
-    <theme name="SedimentLoadM3ASusp">
-        <inherits>
-            <inherit from="SedimentLoadM3A" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="85, 255, 0" />
-            <field name="pointcolor" type="Color" default="85, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="Differences">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
 
 
-    <theme name="LongitudinalSectionArea">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
+  <!-- Classes defining special values -->
+  <theme name="LongitudinalSectionW_HQ1">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ2">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ5">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 153, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ10">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ20">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ25">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 51, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ50">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ100">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ200">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 100, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ300">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 100" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ500">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ1000">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQRZ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HSQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="253, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MHQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MNQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 51, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_NQ">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 204, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQExtrem">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ1_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ2_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ5_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 153, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ10_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ20_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ25_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 51, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ50_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 153, 153" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ100_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ200_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ300_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 100, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ500_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQ1000_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQRZ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HSQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="253, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MHQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MNQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_MQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 51, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_NQ_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 204, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionW_HQExtrem_Points">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ1">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ2">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ5">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 153, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ10">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ20">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ25">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 51, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ50">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 153, 153" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ100">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 51" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ200">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ300">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 100, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ500">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQ1000">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQRZ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HSQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="253, 153, 0" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_MHQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_MNQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_MQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 51, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_NQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 204, 255" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQ_HQExtrem">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="DischargeLongitudinalSectionW">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+
+  <theme name="DischargeLongitudinalSectionC">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0 , 0" />
+    </fields>
+  </theme>
+
+  <theme name="DischargeLongitudinalSectionQ">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQInfoldCut">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 102, 102" />
+    </fields>
+  </theme>
+
+  <theme name="LongitudinalSectionQInfolding">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="51, 51, 51" />
+    </fields>
+  </theme>
+
+  <!-- MIDDLE BED HEIGHT -->
+  <theme name="MiddleBedHeightSingle">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="MinMaxPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="true" />
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+      <field name="linetype" type="Dash" display="Linienart" default="10" />
+      <field name="linecolor" type="Color" display="Linienfarbe" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <!-- Bed Quality -->
+  <theme name="PorosityTopPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="PorositySubPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="DensityTopPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="DensitySubPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterTopPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterSubPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedLoadDiameterPoints">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="PorosityTopLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="PorositySubLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="DensityTopLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="DensitySubLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="153, 99, 102" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterTopLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterSubLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedLoadDiameterLines">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterDataTop">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
+    </fields>
+  </theme>
+
+  <theme name="BedDiameterDataSub">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 100" />
+    </fields>
+  </theme>
+
+  <theme name="BedloadDiameterData">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="false" />
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="100, 0, 0" />
+    </fields>
+  </theme>
+  <!-- Bedheight differences -->
+  <theme name="BedheightDiffYear">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffMorphWidth">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 0" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffEpoch">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 0, 204" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffAbsHeight1">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 0, 204" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffAbsHeight2">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 100, 100" />
+    </fields>
+  </theme>
+
+  <theme name="BedheightDiffHeightYear">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="MorphologicWidth">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+  <!-- Flow velocity -->
+  <theme name="FlowVelocityVMainChannel">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="FlowVelocityVTotalChannel">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 102" />
+    </fields>
+  </theme>
+
+  <theme name="FlowVelocityTau">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="FlowVelocityDischarge">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load longitudinal sections, M^3/A -->
+  <theme name="SedimentLoadLSM3A">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ACoarse">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3AFineMid">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASand">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASuspSand">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASediment">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASuspSandBed">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ATotal">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ABed">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ABedSusp">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSM3ASusp">
+    <inherits>
+      <inherit from="SedimentLoadLSM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load longitudinal sections, T/A -->
+  <theme name="SedimentLoadLSTACoarse">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTAFineMid">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASand">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASuspSand">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASediment">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASuspSandBed">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTATotal">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTABed">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTABedSusp">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadLSTASusp">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load at measurement stations, T/A -->
+  <theme name="SedimentLoad">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linetype" type="Dash" default="10,5" />
+      <field name="showpoints" type="boolean" default="true" />
+      <field name="pointsize" type="int" default="3" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTACoarse">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+      <field name="pointcolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTAFineMid">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+      <field name="pointcolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASand">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+      <field name="pointcolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASuspSand">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+      <field name="pointcolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASediment">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+      <field name="pointcolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASuspSandBed">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="pointcolor" type="Color" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTATotal">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="pointcolor" type="Color" default="0, 100, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTABed">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+      <field name="pointcolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTABedSusp">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+      <field name="pointcolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadTASusp">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+      <field name="pointcolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+  <!-- Sediment load at measurement stations, M3/A -->
+  <theme name="SedimentLoadM3A">
+    <inherits>
+      <inherit from="SedimentLoad" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ACoarse">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+      <field name="pointcolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3AFineMid">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+      <field name="pointcolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASand">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+      <field name="pointcolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASuspSand">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 255, 0" />
+      <field name="pointcolor" type="Color" default="255, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASediment">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 255" />
+      <field name="pointcolor" type="Color" default="0, 255, 255" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASuspSandBed">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+      <field name="pointcolor" type="Color" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ATotal">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 100, 200" />
+      <field name="pointcolor" type="Color" default="0, 100, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ABed">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="200, 200, 200" />
+      <field name="pointcolor" type="Color" default="200, 200, 200" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ABedSusp">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="150, 255, 150" />
+      <field name="pointcolor" type="Color" default="150, 255, 150" />
+    </fields>
+  </theme>
+
+  <theme name="SedimentLoadM3ASusp">
+    <inherits>
+      <inherit from="SedimentLoadM3A" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="85, 255, 0" />
+      <field name="pointcolor" type="Color" default="85, 255, 0" />
+    </fields>
+  </theme>
+
+
+  <theme name="LongitudinalSectionArea">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
 
 
 
-    <theme name="CrossSection">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="CrossSectionWaterLine">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0,0,153" />
-            <field name="showwidth" type="boolean" display="Breite anzeigen"
-                default="false" />
-            <field name="showlevel" type="boolean" display="Wasserstand anzeigen"
-                default="true" />
-            <field name="showlinelabel" type="boolean" default="true"
-                display="Beschriftung anzeigen" />
-            <field name="showmiddleheight" type="boolean"
-                display="Wasserstand anzeigen" default="false" />
-        </fields>
-    </theme>
-
-    <theme name="Hyk">
-        <inherits>
-            <inherit from="Text" />
-        </inherits>
-        <fields>
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-        </fields>
-    </theme>
-
-    <theme name="CrossSectionArea">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-
-
-    <theme name="DischargeCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 153" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-        </fields>
-    </theme>
-
-    <theme name="ExtremeWQCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showextramark" type="boolean" display="Linie anzeigen ab wo extrapoliert wurde"
-                default="true" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 153" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-            <field name="showlinelabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="ExtremeWQBaseCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="2" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showlinelabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-
-
-    <theme name="DurationCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"
-                hints="hidden"/>
-        </fields>
-    </theme>
-
-    <theme name="DurationCurveW">
-        <inherits>
-            <inherit from="DurationCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0,51,204" />
-        </fields>
-    </theme>
-
-    <theme name="DurationCurveQ">
-        <inherits>
-            <inherit from="DurationCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0,204,0" />
-        </fields>
-    </theme>
-
-
-
-    <theme name="FixPoints">
-        <inherits>
-            <inherit from="ColorfulPoints" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="true" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="FixLines">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" hints="hidden" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-        </fields>
-    </theme>
-
-    <theme name="FixAreas">
-        <inherits>
-            <inherit from="Areas" />
-        </inherits>
-        <fields>
-            <field name="areashowbg" type="boolean" display="Hintergrund anzeigen"
-                default="true" hints="hidden" />
-            <field name="areashowborder" type="boolean" display="Begrenzung"
-                default="false" hints="hidden" />
-            <field name="areabordercolor" type="Color" default="0, 0, 0"
-                display="Begrenzungslinienfarbe" hints="hidden" />
-            <field name="showarea" type="boolean" display="Flaeche anzeigen"
-              default="true" hints="hidden" />
-            <field name="showarealabel" type="boolean"
-                display="Flächenbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingCalculatedPoint">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 0" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="5"/>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingWQCurve">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="227, 27, 162" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDerivedCurve">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="227, 27, 162" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" hints="hidden" hidden="true" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="5" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorAverageWQ0">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 128, 0" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
+  <theme name="CrossSection">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="FixingSectorAverageWQ1">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 0, 255" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorAverageWQ2">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 255" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorAverageWQ3">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="255, 0, 0" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingAnalysisEventsWQ">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 255, 0" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingReferenceEvents">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 80, 160" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingOutliers">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden"/>
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="true" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage0">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 128, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage1">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage2">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAverage3">
-        <inherits>
-            <inherit from="FixingDeltaWtAverage" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAnalysis">
-        <inherits>
-            <inherit from="FixPoints" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-            <field name="pointcolor" type="Color" display="Punktfarbe"
-                default="0, 255, 0" />
-        </fields>
-    </theme>
+  <theme name="CrossSectionWaterLine">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0,0,153" />
+      <field name="showwidth" type="boolean" display="Breite anzeigen" default="false" />
+      <field name="showlevel" type="boolean" display="Wasserstand anzeigen" default="true" />
+      <field name="showlinelabel" type="boolean" default="true" display="Beschriftung anzeigen" />
+      <field name="showmiddleheight" type="boolean" display="Wasserstand anzeigen" default="false" />
+    </fields>
+  </theme>
 
-    <theme name="FixingLSAverage0">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 128, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingLSAverage1">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingLSAverage2">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 255" />
-        </fields>
-    </theme>
-
-    <theme name="FixingLSAverage3">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorDeviationLS0">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="0, 128, 0" />
-        </fields>
-    </theme>
-    <theme name="FixingSectorDeviationLS1">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="0, 0, 255" />
-
-        </fields>
-    </theme>
-
-    <theme name="FixingSectorDeviationLS2">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="255, 0, 255" />
-        </fields>
-    </theme>
+  <theme name="Hyk">
+    <inherits>
+      <inherit from="Text" />
+    </inherits>
+    <fields>
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+    </fields>
+  </theme>
 
-    <theme name="FixingSectorDeviationLS3">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="255, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixLSDeviation">
-        <inherits>
-            <inherit from="FixAreas" />
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" display="Fuellfarbe"
-                default="100, 100, 100" />
-        </fields>
-    </theme>
-
-    <theme name="FixLSAnalysis">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 255, 0" />
-        </fields>
-    </theme>
-
-    <theme name="FixLSReference">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="0, 80, 160" />
-        </fields>
-    </theme>
-
-    <theme name="FixDeltaWtDeviation">
-        <inherits>
-            <inherit from="FixAreas"/>
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" default="0, 0, 0" display="Füllfarbe"/>
-        </fields>
-    </theme>
-
-    <theme name="FixingDeltaWtAnalysisPeriods">
-        <inherits>
-            <inherit from="FixAreas"/>
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" default="255, 0, 0" display="Füllfarbe" />
-        </fields>
-    </theme>
-
-    <theme name="FixingReferencePeriod">
-        <inherits>
-            <inherit from="FixAreas"/>
-        </inherits>
-        <fields>
-            <field name="areabgcolor" type="Color" default="0, 0, 255" display="Füllfarbe" />
-        </fields>
-    </theme>
-
-    <theme name="QSectors">
-        <inherits>
-            <inherit from="FixLines" />
-        </inherits>
-        <fields>
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="true" hints="hidden" />
-        </fields>
-    </theme>
+  <theme name="CrossSectionArea">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
 
 
 
-    <theme name="MapLines">
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 205" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="3" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="Floodmaps">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="Floodplains">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="Floodmarks">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="WSPLGEN">
-        <inherits>
-            <inherit from="Uesk" />
-        </inherits>
-        <fields>
-            <field name="startcolor" type="Color"
-                display="Farbverlauf Startfarbe" default="178, 201, 215" />
-            <field name="endcolor" type="Color"
-                display="Farbverlauf Endfarbe" default="2, 27, 42" />
-            <field name="numclasses" type="int" display="Anzahl Klassen"
-                default="6" />
-        </fields>
-    </theme>
-
-    <theme name="RiverAxis">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-        <fields>
-       </fields>
-    </theme>
-
-    <theme name="Kms">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Label" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-
-    <theme name="Fixpoints">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="Floodmarks">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-
-    <theme name="GaugeLocation">
-        <inherits>
-            <inherit from="MapLines" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="Qps">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="Hws">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="HwsPoints">
-        <inherits>
-            <inherit from="MapLines"/>
-            <inherit from="Label" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-    <theme name="Catchment">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="FloodmapLines">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="140, 200, 130" />
-        </fields>
-    </theme>
-
-    <theme name="Buildings">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="HydrBoundariesLines">
-        <inherits>
-            <inherit from="MapLines" />
-        </inherits>
-    </theme>
-
-    <theme name="HydrBoundariesPolys">
-        <inherits>
-            <inherit from="Map" />
-        </inherits>
-    </theme>
-
-    <theme name="Jetties">
-        <inherits>
-            <inherit from="MapLines"/>
-            <inherit from="Label" />
-            <inherit from="Symbol" />
-        </inherits>
-    </theme>
-
-
+  <theme name="DischargeCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 153" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+    </fields>
+  </theme>
 
-    <theme name="HistoricalDischargeCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 153" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="2" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveQ">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveQDiff">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveW">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="100, 100, 153" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-    <theme name="HistoricalDischargeCurveWDiff">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="250, 250, 204" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
+  <theme name="ExtremeWQCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showextramark" type="boolean" display="Linie anzeigen ab wo extrapoliert wurde" default="true" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 153" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+      <field name="showlinelabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="HistoricalDischargeWQW">
-        <!-- the facet has no styling...
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="0, 0, 255" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="1" />
-            <field name="linetype" type="Dash" display="Linienart"
-                default="10" />
-            <field name="showlines" type="boolean" display="Linie anzeigen"
-                default="true" hints="hidden" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>-->
-    </theme>
-
-    <theme name="HistoricalDischargeWQQ">
-        <inherits>
-            <inherit from="HistoricalDischargeCurve" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-            <field name="linesize" type="int" display="Liniendicke"
-                default="1" />
-            <field name="linetype" type="Dash" display="Linienart"
-                default="10" />
-            <field name="showlines" type="boolean" display="Linie anzeigen"
-                default="true" hints="hidden" />
-            <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
-                default="false" />
-            <field name="pointsize" type="int" display="Punktdicke"
-                default="3" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
-        </fields>
-    </theme>
-
-
-
-    <theme name="ReferenceCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-            <inherit from="MinMaxPoints" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" display="Linienfarbe"
-                default="204, 204, 204" />
-        </fields>
-    </theme>
-
-    <theme name="ReferenceCurveNormalized">
-        <inherits>
-            <inherit from="ReferenceCurve" />
-        </inherits>
-        <fields>
-        </fields>
-    </theme>
+  <theme name="ExtremeWQBaseCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showlinelabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
 
 
-    <theme name="SQMeasurements">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" default="0, 153, 255" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="SQMeasurementsOverview">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-
-    <theme name="SQOutliers">
-        <inherits>
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="Color" default="204, 0, 0" />
-            <field name="textorientation" type="boolean" display="Textausrichtung"
-                default="true" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="true"/>
-        </fields>
-    </theme>
-
-    <theme name="SQCurve">
-        <inherits>
-            <inherit from="Lines" />
-            <inherit from="Points" />
-            <inherit from="Label" />
-        </inherits>
-        <fields>
-            <field name="showpoints" type="boolean" display="Punkte anzeigen"
-                default="false" />
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
-            <field name="linecolor" type="Color" default="0, 0, 0" />
-            <field name="linesize" type="int" display="Liniendicke" default="2"/>
-        </fields>
-    </theme>
-
-    <theme name="MySQCurve">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="Color" default="255, 0, 0" />
-        </fields>
-    </theme>
+  <theme name="DurationCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="SQMeasurementsA">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="0, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsB">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="0, 255, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsC">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="0, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsD">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="255, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsE">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="255, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsF">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="255, 0, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsG">
-        <inherits>
-            <inherit from="SQMeasurements" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="0, 0, 0" />
-        </fields>
-    </theme>
+  <theme name="DurationCurveW">
+    <inherits>
+      <inherit from="DurationCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0,51,204" />
+    </fields>
+  </theme>
 
-    <theme name="SQMeasurementsOverviewA">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewB">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 255, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewC">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewD">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 0, 255" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewE">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 255, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewF">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="255, 0, 0" />
-        </fields>
-    </theme>
-    <theme name="SQMeasurementsOverviewG">
-        <inherits>
-            <inherit from="SQMeasurementsOverview" />
-        </inherits>
-        <fields>
-            <field name="pointsize" type="int" default="4" />
-            <field name="pointcolor" type="color" default="0, 0, 0" />
-        </fields>
-    </theme>
-
-    <theme name="SQOutliersA">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="100, 100, 255" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersB">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="100, 255, 255" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersC">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="100, 255, 100" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersD">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="255, 100, 255" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersE">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="255, 255, 100" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersF">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="255, 100, 100" />
-        </fields>
-    </theme>
-    <theme name="SQOutliersG">
-        <inherits>
-            <inherit from="SQOutliers" />
-        </inherits>
-        <fields>
-            <field name="pointcolor" type="color" default="100, 100, 100" />
-        </fields>
-    </theme>
+  <theme name="DurationCurveQ">
+    <inherits>
+      <inherit from="DurationCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0,204,0" />
+    </fields>
+  </theme>
 
 
-    <theme name="SQOutliersOverviewA">
-        <inherits>
-            <inherit from="SQOutliersA" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewB">
-        <inherits>
-            <inherit from="SQOutliersB" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewC">
-        <inherits>
-            <inherit from="SQOutliersC" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewD">
-        <inherits>
-            <inherit from="SQOutliersD" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewE">
-        <inherits>
-            <inherit from="SQOutliersE" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewF">
-        <inherits>
-            <inherit from="SQOutliersF" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
-    <theme name="SQOutliersOverviewG">
-        <inherits>
-            <inherit from="SQOutliersG" />
-        </inherits>
-        <fields>
-            <field name="showpointlabel" type="boolean"
-                display="Punktbeschriftung anzeigen" default="false"/>
-        </fields>
-    </theme>
 
-    <theme name="SQCurveA">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="0, 0, 175" />
-        </fields>
-    </theme>
-    <theme name="SQCurveB">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="0, 175, 175" />
-        </fields>
-    </theme>
-    <theme name="SQCurveC">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="0, 175, 0" />
-        </fields>
-    </theme>
-    <theme name="SQCurveD">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 0, 175" />
-        </fields>
-    </theme>
-    <theme name="SQCurveE">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 175, 0" />
-        </fields>
-    </theme>
-    <theme name="SQCurveF">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 0, 0" />
-        </fields>
-    </theme>
-    <theme name="SQCurveG">
-        <inherits>
-            <inherit from="SQCurve" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 175, 175" />
-        </fields>
-    </theme>
+  <theme name="FixPoints">
+    <inherits>
+      <inherit from="ColorfulPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="true" hints="hidden" />
+    </fields>
+  </theme>
 
-    <theme name="SQOutlierCurveA">
-        <inherits>
-            <inherit from="SQCurveA" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveB">
-        <inherits>
-            <inherit from="SQCurveB" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveC">
-        <inherits>
-            <inherit from="SQCurveC" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveD">
-        <inherits>
-            <inherit from="SQCurveD" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveE">
-        <inherits>
-            <inherit from="SQCurveE" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveF">
-        <inherits>
-            <inherit from="SQCurveF" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
-    <theme name="SQOutlierCurveG">
-        <inherits>
-            <inherit from="SQCurveG" />
-        </inherits>
-        <fields>
-            <field name="linesize" type="int" display="Liniendicke" default="1"/>
-        </fields>
-    </theme>
+  <theme name="FixLines">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen" default="false" hints="hidden" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+    </fields>
+  </theme>
 
-    <theme name="Porosity">
-        <inherits>
-            <inherit from="LongitudinalSection" />
-        </inherits>
-        <fields>
-            <field name="linecolor" type="color" default="175, 175, 175" />
-        </fields>
-    </theme>
-</themegroup>
+  <theme name="FixAreas">
+    <inherits>
+      <inherit from="Areas" />
+    </inherits>
+    <fields>
+      <field name="areashowbg" type="boolean" display="Hintergrund anzeigen" default="true" hints="hidden" />
+      <field name="areashowborder" type="boolean" display="Begrenzung" default="false" hints="hidden" />
+      <field name="areabordercolor" type="Color" default="0, 0, 0" display="Begrenzungslinienfarbe" hints="hidden" />
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" hints="hidden" />
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="FixingCalculatedPoint">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 0" />
+      <field name="pointsize" type="int" display="Punktdicke" default="5" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="FixingWQCurve">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="227, 27, 162" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDerivedCurve">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="227, 27, 162" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen" default="false" hints="hidden" hidden="true" />
+      <field name="pointsize" type="int" display="Punktdicke" default="5" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ0">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 128, 0" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ1">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 0, 255" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ2">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 255" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorAverageWQ3">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="255, 0, 0" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingAnalysisEventsWQ">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingReferenceEvents">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 80, 160" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingOutliers">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage0">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage1">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage2">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAverage3">
+    <inherits>
+      <inherit from="FixingDeltaWtAverage" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAnalysis">
+    <inherits>
+      <inherit from="FixPoints" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage0">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 128, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage1">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage2">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingLSAverage3">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorDeviationLS0">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="0, 128, 0" />
+    </fields>
+  </theme>
+  <theme name="FixingSectorDeviationLS1">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="0, 0, 255" />
+
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorDeviationLS2">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="255, 0, 255" />
+    </fields>
+  </theme>
+
+  <theme name="FixingSectorDeviationLS3">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixLSDeviation">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" display="Fuellfarbe" default="100, 100, 100" />
+    </fields>
+  </theme>
+
+  <theme name="FixLSAnalysis">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 255, 0" />
+    </fields>
+  </theme>
+
+  <theme name="FixLSReference">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" default="0, 80, 160" />
+    </fields>
+  </theme>
+
+  <theme name="FixDeltaWtDeviation">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" default="0, 0, 0" display="Füllfarbe" />
+    </fields>
+  </theme>
+
+  <theme name="FixingDeltaWtAnalysisPeriods">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" default="255, 0, 0" display="Füllfarbe" />
+    </fields>
+  </theme>
+
+  <theme name="FixingReferencePeriod">
+    <inherits>
+      <inherit from="FixAreas" />
+    </inherits>
+    <fields>
+      <field name="areabgcolor" type="Color" default="0, 0, 255" display="Füllfarbe" />
+    </fields>
+  </theme>
+
+  <theme name="QSectors">
+    <inherits>
+      <inherit from="FixLines" />
+    </inherits>
+    <fields>
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="true" hints="hidden" />
+    </fields>
+  </theme>
+
+
+
+  <theme name="MapLines">
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 205" />
+      <field name="linesize" type="int" display="Liniendicke" default="3" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="Floodmaps">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="Floodplains">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="Floodmarks">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="WSPLGEN">
+    <inherits>
+      <inherit from="Uesk" />
+    </inherits>
+    <fields>
+      <field name="startcolor" type="Color" display="Farbverlauf Startfarbe" default="178, 201, 215" />
+      <field name="endcolor" type="Color" display="Farbverlauf Endfarbe" default="2, 27, 42" />
+      <field name="numclasses" type="int" display="Anzahl Klassen" default="6" />
+    </fields>
+  </theme>
+
+  <theme name="RiverAxis">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
+
+  <theme name="Kms">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Label" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+
+  <theme name="Fixpoints">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="Floodmarks">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+
+  <theme name="GaugeLocation">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="Qps">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="Hws">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="HwsPoints">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Label" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+  <theme name="Catchment">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="FloodmapLines">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="140, 200, 130" />
+    </fields>
+  </theme>
+
+  <theme name="Buildings">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="HydrBoundariesLines">
+    <inherits>
+      <inherit from="MapLines" />
+    </inherits>
+  </theme>
+
+  <theme name="HydrBoundariesPolys">
+    <inherits>
+      <inherit from="Map" />
+    </inherits>
+  </theme>
+
+  <theme name="Jetties">
+    <inherits>
+      <inherit from="MapLines" />
+      <inherit from="Label" />
+      <inherit from="Symbol" />
+    </inherits>
+  </theme>
+
+
+
+  <theme name="HistoricalDischargeCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 153" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveQ">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveQDiff">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveW">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="100, 100, 153" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeCurveWDiff">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="250, 250, 204" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+  <theme name="HistoricalDischargeWQW">
+    <!-- the facet has no styling...
+      <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="Label" />
+      </inherits>
+      <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe"
+      default="0, 0, 255" />
+      <field name="linesize" type="int" display="Liniendicke"
+      default="1" />
+      <field name="linetype" type="Dash" display="Linienart"
+      default="10" />
+      <field name="showlines" type="boolean" display="Linie anzeigen"
+      default="true" hints="hidden" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen"
+      default="false" />
+      <field name="pointsize" type="int" display="Punktdicke"
+      default="3" />
+      <field name="showlinelabel" type="boolean"
+      display="Beschriftung anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean"
+      display="Beschriftung anzeigen" default="false" hints="hidden" />
+      </fields> -->
+  </theme>
+
+  <theme name="HistoricalDischargeWQQ">
+    <inherits>
+      <inherit from="HistoricalDischargeCurve" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+      <field name="linetype" type="Dash" display="Linienart" default="10" />
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="true" hints="hidden" />
+      <field name="showpoints" type="boolean" display="Datenpunkte anzeigen" default="false" />
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="showlinelabel" type="boolean" display="Beschriftung anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Beschriftung anzeigen" default="false" hints="hidden" />
+    </fields>
+  </theme>
+
+
+
+  <theme name="ReferenceCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+      <inherit from="MinMaxPoints" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="204, 204, 204" />
+    </fields>
+  </theme>
+
+  <theme name="ReferenceCurveNormalized">
+    <inherits>
+      <inherit from="ReferenceCurve" />
+    </inherits>
+    <fields>
+    </fields>
+  </theme>
+
+
+
+  <theme name="SQMeasurements">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" default="0, 153, 255" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="SQMeasurementsOverview">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutliers">
+    <inherits>
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="Color" default="204, 0, 0" />
+      <field name="textorientation" type="boolean" display="Textausrichtung" default="true" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="true" />
+    </fields>
+  </theme>
+
+  <theme name="SQCurve">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+      <field name="linecolor" type="Color" default="0, 0, 0" />
+      <field name="linesize" type="int" display="Liniendicke" default="2" />
+    </fields>
+  </theme>
+
+  <theme name="SQMeasurementsA">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsB">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="0, 255, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsC">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="0, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsD">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="255, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsE">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="255, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsF">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="255, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsG">
+    <inherits>
+      <inherit from="SQMeasurements" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SQMeasurementsOverviewA">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewB">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 255, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewC">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewD">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewE">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewF">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="255, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SQMeasurementsOverviewG">
+    <inherits>
+      <inherit from="SQMeasurementsOverview" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" default="4" />
+      <field name="pointcolor" type="color" default="0, 0, 0" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutliersA">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="100, 100, 255" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersB">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="100, 255, 255" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersC">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="100, 255, 100" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersD">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="255, 100, 255" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersE">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="255, 255, 100" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersF">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="255, 100, 100" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersG">
+    <inherits>
+      <inherit from="SQOutliers" />
+    </inherits>
+    <fields>
+      <field name="pointcolor" type="color" default="100, 100, 100" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutliersOverviewA">
+    <inherits>
+      <inherit from="SQOutliersA" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewB">
+    <inherits>
+      <inherit from="SQOutliersB" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewC">
+    <inherits>
+      <inherit from="SQOutliersC" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewD">
+    <inherits>
+      <inherit from="SQOutliersD" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewE">
+    <inherits>
+      <inherit from="SQOutliersE" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewF">
+    <inherits>
+      <inherit from="SQOutliersF" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SQOutliersOverviewG">
+    <inherits>
+      <inherit from="SQOutliersG" />
+    </inherits>
+    <fields>
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" />
+    </fields>
+  </theme>
+
+  <theme name="SQCurveA">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="0, 0, 175" />
+    </fields>
+  </theme>
+  <theme name="SQCurveB">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="0, 175, 175" />
+    </fields>
+  </theme>
+  <theme name="SQCurveC">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="0, 175, 0" />
+    </fields>
+  </theme>
+  <theme name="SQCurveD">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 0, 175" />
+    </fields>
+  </theme>
+  <theme name="SQCurveE">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 175, 0" />
+    </fields>
+  </theme>
+  <theme name="SQCurveF">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SQCurveG">
+    <inherits>
+      <inherit from="SQCurve" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 175, 175" />
+    </fields>
+  </theme>
+
+  <theme name="SQOutlierCurveA">
+    <inherits>
+      <inherit from="SQCurveA" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveB">
+    <inherits>
+      <inherit from="SQCurveB" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveC">
+    <inherits>
+      <inherit from="SQCurveC" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveD">
+    <inherits>
+      <inherit from="SQCurveD" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveE">
+    <inherits>
+      <inherit from="SQCurveE" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveF">
+    <inherits>
+      <inherit from="SQCurveF" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+  <theme name="SQOutlierCurveG">
+    <inherits>
+      <inherit from="SQCurveG" />
+    </inherits>
+    <fields>
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+    </fields>
+  </theme>
+
+  <theme name="Porosity">
+    <inherits>
+      <inherit from="LongitudinalSection" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="color" default="175, 175, 175" />
+    </fields>
+  </theme>
+
+  <!-- S-INFO Data-Themes -->
+  <theme name="SInfoBedHeightMin">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoBedHeightMax">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 0" />
+    </fields>
+  </theme>
+
+  <!-- S-INFO Flow-Depth Themes -->
+  <theme name="SInfoFlowDepth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthWithTkh">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthMin">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 204, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthMax">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthCurrent">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 128" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthHistorical">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="51, 102, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoTkh">
+    <inherits>
+      <inherit from="Lines" />
+      <inherit from="Points" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="showpoints" type="boolean" display="Punkte anzeigen" default="false" />
+      <field name="showpointlabel" type="boolean" display="Punktbeschriftung anzeigen" default="false" hints="hidden" />
+
+      <field name="calculateRange" type="boolean" display="Ausdehnung berechnen" default="true" hints="hidden" />
+
+      <!-- Areas use 'showborder' instead of showlines (but inconsistently uses 'linecolor' and 'linesize'), so we hide 'showline' and replace it with 'showbordder' -->
+      <field name="showlines" type="boolean" display="Linie anzeigen" default="true" hints="hidden" />
+      <field name="showborder" type="boolean" display="Linien anzeigen" default="true" />
+      <field name="linecolor" type="Color" display="Linienfarbe" default="228, 108, 10" />
+      <field name="linesize" type="int" display="Liniendicke" default="1" />
+
+      <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="false" />
+
+      <field name="showarea" type="boolean" display="Flaeche anzeigen" default="true" />
+      <field name="areabgcolor" type="Color" default="245, 245, 220" display="Füllfarbe" />
+      <field name="areabgpattern" type="areapattern" default="patternFill" display="Flächentyp" />
+      <field name="areatransparency" type="int" default="20" />
+
+      <field name="showarealabel" type="boolean" display="Flächenbeschriftung anzeigen" default="false" hints="hidden" />
+
+      <field name="showmaximum" type="boolean" display="Maximum anzeigen" default="false" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthDevelopment">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFlowDepthDevelopmentPerYear">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 0, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoWaterlevelDifference">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="102, 255, 102" />
+    </fields>
+  </theme>
+  <theme name="SInfoBedHeightDifference">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="255, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedChannelWidth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="128, 64, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedChannelDepth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="128, 64, 64" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedTkh">
+    <inherits>
+      <inherit from="SInfoTkh" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="128, 64, 10" />
+      <field name="areabgcolor" type="Color" default="255, 240, 224" display="Füllfarbe" />
+      <field name="areabgpattern" type="areapattern" default="patternFill" display="Flächentyp" />
+      <field name="areatransparency" type="int" default="20" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedDepthEvol">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 192" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedDepthEvolPerYear">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 128" />
+    </fields>
+  </theme>
+  <theme name="SInfoPredefinedFlowDepth">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="96, 128, 192" />
+    </fields>
+  </theme>
+  <theme name="SInfoInfrastructureHeight">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+      <inherit from="Label" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="0, 192, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoInfrastructureHeightLeft">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="68, 216, 40" />
+    </fields>
+  </theme>
+  <theme name="SInfoInfrastructureHeightRight">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="192, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoCollisionCount">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="64, 192, 64" />
+    </fields>
+  </theme>
+  <theme name="SInfoCollisionCount2">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="192, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoCollisionCount3">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="2" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="48, 96, 255" />
+    </fields>
+  </theme>
+  <theme name="SInfoFloodDurationLeft">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="68, 216, 40" />
+    </fields>
+  </theme>
+  <theme name="SInfoFloodDurationRight">
+    <inherits>
+      <inherit from="LongitudinalSectionPoints" />
+    </inherits>
+    <fields>
+      <field name="pointsize" type="int" display="Punktdicke" default="3" />
+      <field name="pointcolor" type="Color" display="Punktfarbe" default="192, 0, 0" />
+    </fields>
+  </theme>
+  <theme name="SInfoMainValues">
+    <inherits>
+      <inherit from="MainValuesW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Farbe" default="0, 96, 192" />
+    </fields>
+  </theme>
+</themegroup>
\ No newline at end of file
--- a/artifacts/doc/conf/themes/virtual.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/doc/conf/themes/virtual.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -79,16 +79,20 @@
 
     <theme name="Areas" type="virtual">
         <fields>
+            <!-- 'showarea' is not used in the code... -->        
             <field name="showarea" type="boolean" display="Flaeche anzeigen"
                 default="true" />
             <field name="showarealabel" type="boolean"
                 display="Flaechenbeschriftung anzeigen" default="false" />
             <field name="areabgcolor" type="Color" display="Fuellfarbe"
                 default="0, 100, 0" />
+            <!-- 'areashowbg': no code exits that reads it... -->                
             <field name="areashowbg" type="boolean"
                 display="Hintergrund anzeigen" default="true" hidden="true" />
+            <!-- FIXME: "areashowborder" does not exist, the constant in ThemeDocument is 'showborder" -->
             <field name="areashowborder" type="boolean"
                 display="Flaechebegrenzungslinie anzeigen" default="false" />
+            <!-- 'areabordercolor' is not used in the code..., implementation uses 'linecolor' -->                
             <field name="areabordercolor" type="Color" default="0, 0, 0"
                 display="Begrenzungslinienfarbe" />
             <field name="areatransparency" type="int" default="50" display="Transparenz" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/uinfo_uedauern_aue_Beispielfluss.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,10 @@
+jahre=1995,1996,1997
+#url=htps://geoportal.bafg.de/wms/${jahr}
+url=http://osm.intevation.de/bfg/service?
+scenario_url=htps://geoportal.bafg.de/wms/${jahr}_${scenario}
+
+#mittel_url=htps://geoportal.bafg.de/wms/${jahr}
+mittel_url=http://osm.intevation.de/bfg/service?
+mittel_scenario_url=htps://geoportal.bafg.de/wms/${scenario}
+mittel_start=8888
+mittel_ende=2000
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/doc/conf/uinfo_uedauern_aue_Elbe.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,8 @@
+jahre=1995,1996,1997
+url=htps://geoportal.bafg.de/wms/${jahr}
+scenario_url=htps://geoportal.bafg.de/wms/${jahr}_${scenario}
+
+mittel_url=htps://geoportal.bafg.de/wms/
+mittel_start=1998
+mittel_ende=2000
+mittel_scenario_url=htps://geoportal.bafg.de/wms/${scenario}
--- a/artifacts/pom-oracle.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/pom-oracle.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -1,12 +1,10 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>org.dive4elements.river</groupId>
   <artifactId>river-artifacts</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
-
   <name>river-artifacts</name>
   <url>http://maven.apache.org</url>
 
@@ -17,13 +15,13 @@
   <build>
     <plugins>
       <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <version>2.0.2</version>
-          <configuration>
-              <source>1.7</source>
-              <target>1.7</target>
-          </configuration>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.0.2</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
@@ -42,11 +40,40 @@
           </descriptors>
         </configuration>
       </plugin>
+      <!--plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>3.0.0</version>
+        <configuration>
+        <configLocation>../checkstyle.xml</configLocation>
+        <encoding>UTF-8</encoding>
+        </configuration>
+        <executions>
+        <execution>
+        <id>validate</id>
+        <phase>validate</phase>
+        <configuration>
+        <consoleOutput>true</consoleOutput>
+        <failsOnError>true</failsOnError>
+        </configuration>
+        <goals>
+        <goal>check</goal>
+        </goals>
+        </execution>
+        </executions>
+        </plugin -->
     </plugins>
   </build>
 
   <dependencies>
     <dependency>
+      <groupId>roboto.jar</groupId>
+      <artifactId>roboto</artifactId>
+      <version>0</version>
+      <scope>system</scope>
+      <systemPath>${project.basedir}/contrib/fonts/roboto.jar</systemPath>
+    </dependency>
+    <dependency>
       <groupId>net.sf.ehcache</groupId>
       <artifactId>ehcache-core</artifactId>
       <version>2.4.2</version>
@@ -113,9 +140,9 @@
       <version>1.3.158</version>
     </dependency>
     <dependency>
-        <groupId>commons-io</groupId>
-        <artifactId>commons-io</artifactId>
-        <version>2.4</version>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.4</version>
     </dependency>
     <dependency>
       <groupId>org.geotools</groupId>
@@ -171,9 +198,9 @@
   </dependencies>
   <repositories>
     <repository>
-        <id>jboss-repo2</id>
-        <name>JBoss repo2</name>
-        <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+      <id>jboss-repo2</id>
+      <name>JBoss repo2</name>
+      <url>http://repository.jboss.org/nexus/content/groups/public/</url>
     </repository>
     <repository>
       <id>gt2.repo</id>
--- a/artifacts/pom.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/pom.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -1,12 +1,10 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>org.dive4elements.river</groupId>
   <artifactId>river-artifacts</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
-
   <name>river-artifacts</name>
   <url>http://maven.apache.org</url>
 
@@ -17,13 +15,13 @@
   <build>
     <plugins>
       <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <version>2.0.2</version>
-          <configuration>
-              <source>1.7</source>
-              <target>1.7</target>
-          </configuration>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.0.2</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
@@ -42,33 +40,40 @@
           </descriptors>
         </configuration>
       </plugin>
-      <plugin>
+      <!--plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
         <version>3.0.0</version>
         <configuration>
-          <configLocation>../checkstyle.xml</configLocation>
-          <encoding>UTF-8</encoding>
+        <configLocation>../checkstyle.xml</configLocation>
+        <encoding>UTF-8</encoding>
         </configuration>
         <executions>
-          <execution>
-            <id>validate</id>
-            <phase>validate</phase>
-            <configuration>
-              <consoleOutput>true</consoleOutput>
-              <failsOnError>true</failsOnError>
-            </configuration>
-            <goals>
-              <goal>check</goal>
-            </goals>
-          </execution>
+        <execution>
+        <id>validate</id>
+        <phase>validate</phase>
+        <configuration>
+        <consoleOutput>true</consoleOutput>
+        <failsOnError>true</failsOnError>
+        </configuration>
+        <goals>
+        <goal>check</goal>
+        </goals>
+        </execution>
         </executions>
-      </plugin>
+        </plugin -->
     </plugins>
   </build>
 
   <dependencies>
     <dependency>
+      <groupId>roboto.jar</groupId>
+      <artifactId>roboto</artifactId>
+      <version>0</version>
+      <scope>system</scope>
+      <systemPath>${project.basedir}/contrib/fonts/roboto.jar</systemPath>
+    </dependency>
+    <dependency>
       <groupId>net.sf.ehcache</groupId>
       <artifactId>ehcache-core</artifactId>
       <version>2.4.2</version>
@@ -135,9 +140,9 @@
       <version>1.3.158</version>
     </dependency>
     <dependency>
-        <groupId>commons-io</groupId>
-        <artifactId>commons-io</artifactId>
-        <version>2.4</version>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.4</version>
     </dependency>
     <dependency>
       <groupId>org.geotools</groupId>
@@ -193,9 +198,9 @@
   </dependencies>
   <repositories>
     <repository>
-        <id>jboss-repo2</id>
-        <name>JBoss repo2</name>
-        <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+      <id>jboss-repo2</id>
+      <name>JBoss repo2</name>
+      <url>http://repository.jboss.org/nexus/content/groups/public/</url>
     </repository>
     <repository>
       <id>gt2.repo</id>
--- a/artifacts/src/assembly/assembly.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/assembly/assembly.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -13,6 +13,10 @@
       <outputDirectory>/bin</outputDirectory>
     </fileSet>
     <fileSet>
+      <directory>${project.basedir}/contrib/fonts</directory>
+      <outputDirectory>/bin/lib</outputDirectory>
+    </fileSet>
+    <fileSet>
       <directory>${project.basedir}/doc/conf</directory>
       <outputDirectory>/conf</outputDirectory>
     </fileSet>
@@ -30,10 +34,6 @@
       <directory>${project.basedir}/../backend/doc/schema</directory>
       <outputDirectory>/schema</outputDirectory>
     </fileSet>
-    <fileSet>
-      <directory>${project.basedir}/../contrib/init.d</directory>
-      <outputDirectory>/init.d</outputDirectory>
-    </fileSet>
   </fileSets>
   <dependencySets>
     <dependencySet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/FLYS.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,18 @@
+/** 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;
+
+/**
+ * @author Gernot Belger
+ *
+ */
+public interface FLYS {
+    static final String VERSION = "3.3.0";
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -12,47 +12,42 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-import org.w3c.dom.Document;
-
 import org.dive4elements.artifactdatabase.state.DefaultOutput;
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.ArtifactFactory;
-import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.minfo.BedHeightFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedHeightFactory;
+import org.dive4elements.river.artifacts.model.minfo.BedHeightMinMaxFacet;
 import org.dive4elements.river.artifacts.model.minfo.BedHeightSoundingWidthFacet;
+import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.artifacts.states.StaticState;
-
-import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.exports.process.BedHeightProcessor;
+import org.dive4elements.river.model.BedHeightValueType;
+import org.w3c.dom.Document;
 
-public class BedHeightsArtifact
-extends      AbstractStaticStateArtifact
-implements   FacetTypes
-{
+public class BedHeightsArtifact extends AbstractStaticStateArtifact implements FacetTypes {
     /** The log for this class. */
-    private static Logger log =
-        Logger.getLogger(BedHeightsArtifact.class);
+    private static Logger log = Logger.getLogger(BedHeightsArtifact.class);
 
     /** Artifact name. */
     private static final String NAME = "bedheights";
 
     static {
         // TODO: Move to configuration.
-        FacetActivity.Registry.getInstance()
-            .register(NAME, FacetActivity.INACTIVE);
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
     }
 
-    public static final String STATIC_STATE_NAME =
-        "state.additional_bedheights.static";
+    public static final String STATIC_STATE_NAME = "state.additional_bedheights.static";
 
-    /** Data Item name to know whether we are Heighmarks and receive
-     * some data slightly different. */
-    public static final String DATA_HEIGHT_TYPE =
-        "height_marks";
+    /**
+     * Data Item name to know whether we are Heighmarks and receive
+     * some data slightly different.
+     */
+    public static final String DATA_HEIGHT_TYPE = "height_marks";
 
     /**
      * Trivial Constructor.
@@ -70,74 +65,61 @@
      * Gets called from factory, to set things up.
      */
     @Override
-    public void setup(
-        String          identifier,
-        ArtifactFactory factory,
-        Object          context,
-        CallMeta        callMeta,
-        Document        data,
-        List<Class>     loadFacets)
-    {
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
         log.debug("BedHeightsArtifact.setup");
 
         if (log.isDebugEnabled()) {
             log.debug(XMLUtils.toString(data));
         }
 
-        String code = getDatacageIDValue(data);
-
-        if (code != null) {
-            String [] parts = code.split("-");
-
-            if (parts.length >= 3) {
-                // The setting is a bit complicated:
-                // This artifact can spawn epoch type bedheight facets,
-                // 'singlevalue'/singleyear bedheight facets or
-                // sounding-width facets. The type is indicated by
-                // the ids-param which comes from datacage.
-
-                String name = parts[0];
-                String type = parts[1];
-                String facetType = BEDHEIGHT;
-                if (type.equals("soundings")) {
-                    type = "singlevalues";
-                    facetType = BEDHEIGHT_SOUNDING_WIDTH;
-                }
-                addStringData("height_id", parts[2]);
-                addStringData("type", type);
-                String btype = type;
-                int hId = Integer.parseInt(parts[2]);
+        final String code = getDatacageIDValue(data);
 
-                if (type.equals("singlevalues")) {
-                    btype = "single";
-                }
-
-                String bedHName = BedHeightFactory.getHeightName(btype, hId);
+        createFacets(callMeta, code);
 
-                Facet facet =  null;
-                if (facetType.equals(BEDHEIGHT_SOUNDING_WIDTH)) {
-                    bedHName = Resources.getMsg(
-                        callMeta,
-                        "facet.bedheight.sounding_width",
-                        new Object[] { bedHName });
-                    facet = new BedHeightSoundingWidthFacet(
-                        facetType, bedHName);
-                }
-                else {
-                    facet = new BedHeightFacet(facetType, bedHName);
-                }
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
 
-
-                ArrayList<Facet> facets = new ArrayList<Facet>(1);
-                facets.add(facet);
+    private void createFacets(final CallMeta callMeta, final String code) {
+        if (code == null)
+            return;
 
-                addFacets(STATIC_STATE_NAME, facets);
-            }
-            else {
-                log.error("Invalid datacage ID '" + code + "'");
-            }
+        final String[] parts = code.split("-", 5);
+        if (parts.length < 5) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
         }
-        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+
+        // String name = parts[0];
+
+        // type may only be 'single' or 'soundings'
+        final String type = parts[1];
+
+        final String heightId = parts[2];
+        // final int hId = Integer.parseInt(heightId);
+
+        // final String year = parts[3];
+        final String bedHName = parts[4];
+
+        addStringData("height_id", heightId);
+        if (type.equals("soundings"))
+            addStringData("type", "singlevalues");
+        else
+            addStringData("type", type);
+
+        final ArrayList<Facet> facets = new ArrayList<>(1);
+
+        if ("soundings".equals(type)) {
+            final String description = Resources.getMsg(callMeta, "facet.bedheight.sounding_width", new Object[] { bedHName });
+            facets.add(new BedHeightSoundingWidthFacet(BEDHEIGHT_SOUNDING_WIDTH, description));
+        } else if ("single".equals(type))
+            facets.add(new BedHeightFacet(BEDHEIGHT, bedHName));
+        else if ("singleMin".equals(type))
+            facets.add(new BedHeightMinMaxFacet(BedHeightProcessor.FACET_BED_HEIGHTS_MIN, bedHName, BedHeightValueType.min));
+        else if ("singleMax".equals(type))
+            facets.add(new BedHeightMinMaxFacet(BedHeightProcessor.FACET_BED_HEIGHTS_MAX, bedHName, BedHeightValueType.max));
+
+        addFacets(STATIC_STATE_NAME, facets);
     }
 
     @Override
@@ -145,14 +127,10 @@
 
         log.debug("initStaticState " + getName() + " " + identifier());
 
-        StaticState state = new StaticState(STATIC_STATE_NAME);
-        DefaultOutput output = new DefaultOutput(
-                "general",
-                "general",
-                "image/png",
-                "chart");
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
 
-        List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
         output.addFacets(facets);
         state.addOutput(output);
 
@@ -160,20 +138,15 @@
     }
 
     @Override
-    protected void initialize(
-        Artifact artifact,
-        Object context,
-        CallMeta meta
-    ) {
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
         // do not clone facets, etc. from master artifact
 
         log.debug("initialize");
-        importData((D4EArtifact)artifact, "river");
-        importData((D4EArtifact)artifact, "ld_from");
-        importData((D4EArtifact)artifact, "ld_to");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
 
         log.debug("ld_from " + getDataAsString("ld_from"));
         log.debug("ld_to " + getDataAsString("ld_to"));
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -89,9 +89,7 @@
             } else { // Not found in cache -> generate it.
                 Element r = createElement(XMLUtils.newDocument());
 
-                Recommendations.getInstance().recommend(
-                    artifact, null, outs,
-                    getNoneUserSpecificParameters(artifact, context), r);
+                Recommendations.getInstance().recommend( artifact, null, outs, getNoneUserSpecificParameters(artifact, context), r, context);
 
                 recommendations = (Element)doc.importNode(r, true);
 
@@ -101,10 +99,7 @@
 
             recommendations = createElement(doc);
 
-            Recommendations.getInstance().recommend(
-                artifact, null, outs,
-                getNoneUserSpecificParameters(artifact, context),
-                recommendations);
+            Recommendations.getInstance().recommend( artifact, null, outs, getNoneUserSpecificParameters(artifact, context), recommendations, context);
         }
 
         return recommendations;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/D4EArtifact.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/D4EArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -1014,6 +1014,19 @@
         log.debug("Bound to out: " + getBoundToOut());
         log.debug("OutName: " + outName);
 
+        // REMARK: look for facets of the current state
+        final List<Facet> currentFacets = facets.get(getCurrentStateId());
+        if( currentFacets != null ) {
+            for (Facet f: currentFacets) {
+                if (f.getIndex() == index && f.getName().equals(name)) 
+                    return f;
+            }
+        }
+        
+        // REMARK: this is old code, we should never get here actually.
+        // This posed leads to a problem when the user changes the calculation-mode after one calculation was executed.
+        // If both (new and old) calculations contained the same output-facet, it could happen that an old facet was executed
+        // with the calculation results of the new calculation.
         for (List<Facet> fs: facets.values()) {
             for (Facet f: fs) {
                 if (f.getIndex() == index && f.getName().equals(name)) {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -181,6 +181,24 @@
         return res;
     }
 
+    /**
+     * Get WQKms from factory.
+     * @return WQKms according to parameterization (can be null);
+     */
+    public WQKms getWQKms(final double from, final double to) {
+        log.debug("StaticWQKmsArtifact.getWQKms");
+        
+        int col = Integer.parseInt(getDataAsString("col_pos"));
+        int wst = Integer.parseInt(getDataAsString("wst_id"));
+        
+        /** TODO do not run twice against db to do this. */
+        String wkmsName = WKmsFactory.getWKmsName(col, wst);
+        
+        WQKms res = WQKmsFactory.getWQKms(col, wst, from, to);
+        res.setName(wkmsName);
+        return res;
+    }
+
     /** Return specific name. */
     @Override
     public String getName() {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -20,7 +20,8 @@
 
 import org.dive4elements.river.artifacts.access.Calculation4Access;
 import org.dive4elements.river.artifacts.access.RangeAccess;
-
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
 import org.dive4elements.river.artifacts.geom.Lines;
 
 import org.dive4elements.river.artifacts.model.Calculation1;
@@ -42,8 +43,6 @@
 
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
 
-import org.dive4elements.river.artifacts.states.LocationDistanceSelect;
-
 import org.dive4elements.river.model.DischargeTable;
 import org.dive4elements.river.model.FastCrossSectionLine;
 import org.dive4elements.river.model.Gauge;
@@ -174,7 +173,7 @@
         return this.getWaterlevelData(null);
     }
 
-    protected CalculationResult getDischargeLongitudinalSectionData() {
+    private CalculationResult getDischargeLongitudinalSectionData() {
         // TODO: This caluclation should be cached as it is quite expensive.
         return new Calculation4(new Calculation4Access(this)).calculate();
     }
@@ -191,44 +190,51 @@
         String calculationMode = getDataAsString("calculation_mode");
 
         // If this WINFO-Artifact has a calculation trait.
-        if (calculationMode != null) {
-            if (calculationMode.equals("calc.discharge.longitudinal.section")
-            ) {
+        if (calculationMode != null) 
+        {
+            if (calculationMode.equals("calc.discharge.longitudinal.section"))
                 return getDischargeLongitudinalSectionData();
-            }
-            else if (calculationMode.equals("calc.extreme.curve")) {
-                return (CalculationResult)
-                    this.compute(context, ComputeType.ADVANCE, false);
-            }
-            else if (calculationMode.equals("calc.w.differences")) {
-                return (CalculationResult)
-                    this.compute(context, ComputeType.ADVANCE, true);
-            }
-            else {
-                log.warn("Unhandled calculation_mode " + calculationMode);
-            }
+
+            if (calculationMode.equals("calc.extreme.curve")) 
+                return (CalculationResult)this.compute(context, ComputeType.ADVANCE, false);
+
+            if (calculationMode.equals("calc.w.differences")) 
+                return (CalculationResult)this.compute(context, ComputeType.ADVANCE, true);
+            
+            log.warn("Unhandled calculation_mode " + calculationMode);
         }
-
+        
         // Otherwise get it from parameterization.
-        River river = RiverUtils.getRiver(this);
-        if (river == null) {
+        // TODO: wrong comment: now always a waterlevle computation is executed; actually there is a calc_mode for that, why dont check?
+        return computeWaterlevelData();
+    }
+
+    /** Execu5tes the calculation of 'waterlevel', fetches all input data from this artifact */
+    private CalculationResult computeWaterlevelData() {
+        final double[] kms = new ComputationRangeAccess(this).getKms();
+        if (kms == null) 
+            return error(new WQKms[0], "no.kms.selected");
+
+        return computeWaterlevelData(kms);
+    }
+    
+    /** 
+     * Execu5tes the calculation of 'waterlevel'.
+     * Allows to override the stations for which the calculation is done. All other inputs are fetched from this artifact.
+     */
+    public final CalculationResult computeWaterlevelData(final double kms[]) {
+
+        final River river = new RiverAccess(this).getRiver();
+        if (river == null) 
             return error(new WQKms[0], "no.river.selected");
-        }
-
-        double[] kms = getKms();
-        if (kms == null) {
-            return error(new WQKms[0], "no.kms.selected");
-        }
 
         double[] qs   = getQs();
         double[] ws   = null;
-        boolean  qSel = true;
 
         Calculation report = new Calculation();
 
         if (qs == null) {
             log.debug("Determine Q values based on a set of W values.");
-            qSel = false;
             ws   = getWs();
             double [][] qws = getQsForWs(ws, report);
             if (qws == null || qws.length == 0) {
@@ -273,10 +279,9 @@
                 "reference gauge: " + gauge.getName() + " (km " + refKm + ")");
         }
 
-        return computeWaterlevelData(kms, qs, ws, wst, refKm, report);
+        return computeWaterlevelData(kms, qs, ws, wst, refKm, report);        
     }
 
-
     /**
      * Computes the data of a waterlevel computation based on the interpolation
      * in WstValueTable.
@@ -287,7 +292,7 @@
      *
      * @return an array of data triples that consist of W, Q and Kms.
      */
-    public static CalculationResult computeWaterlevelData(
+    private static CalculationResult computeWaterlevelData(
         double []     kms,
         double []     qs,
         double []     ws,
@@ -349,7 +354,7 @@
      *
      * @return the computed data.
      */
-    public static CalculationResult computeDurationCurveData(
+    private static CalculationResult computeDurationCurveData(
         Gauge         gauge,
         WstValueTable wst,
         double        location)
@@ -409,7 +414,7 @@
      * @return an object that contains tuples of W/Q values at the specified
      * location.
      */
-    public static CalculationResult computeDischargeCurveData(
+    private static CalculationResult computeDischargeCurveData(
         WstValueTable wst,
         double location)
     {
@@ -544,7 +549,7 @@
     /**
      * Get corrected waterline against surface/profile.
      */
-    public Lines.LineData waterLineC(int idx, FastCrossSectionLine csl) {
+    private Lines.LineData waterLineC(int idx, FastCrossSectionLine csl) {
         List<Point2D> points = csl.getPoints();
 
         WQKms[] wqckms = (WQKms[])
@@ -665,7 +670,7 @@
      *
      * @return an array of Q values.
      */
-    public double [][] getQsForWs(double[] ws, Calculation report) {
+    private double [][] getQsForWs(double[] ws, Calculation report) {
 
         if (ws == null) {
             log.error("getQsForWs: ws == null");
@@ -803,54 +808,6 @@
 
 
     /**
-     * Returns the selected Kms.
-     *
-     * @return the selected kms.
-     */
-    public double[] getKms() {
-        RangeAccess rangeAccess = new RangeAccess(this);
-        if (rangeAccess.isRange()) {
-            return rangeAccess.getKmSteps();
-        }
-        else {
-            return LocationDistanceSelect.getLocations(this);
-        }
-    }
-
-
-    public double [] getFromToStep() {
-        RangeAccess rangeAccess = new RangeAccess(this);
-        if (!rangeAccess.isRange()) {
-            return null;
-        }
-        double [] fromTo = rangeAccess.getKmRange();
-
-        if (fromTo == null) {
-            return null;
-        }
-
-        StateData dStep = getData("ld_step");
-        if (dStep == null) {
-            return null;
-        }
-
-        double [] result = new double[3];
-        result[0] = fromTo[0];
-        result[1] = fromTo[1];
-
-        try {
-            String step = (String)dStep.getValue();
-            result[2] = DoubleUtil.round(Double.parseDouble(step) / 1000d);
-        }
-        catch (NumberFormatException nfe) {
-            return null;
-        }
-
-        return result;
-    }
-
-
-    /**
      * This method returns the Q values.
      *
      * @return the selected Q values or null, if no Q values are selected.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/ComputationRangeAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,84 @@
+/** 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.access;
+
+import org.dive4elements.artifactdatabase.data.StateData;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.states.ComputationRangeState;
+import org.dive4elements.river.utils.DoubleUtil;
+
+/**
+ * Access to data handled by {@link ComputationRangeState}.
+ *
+ * @author Gernot Belger
+ */
+public class ComputationRangeAccess extends RangeAccess {
+
+    public ComputationRangeAccess(final D4EArtifact artifact) {
+        super(artifact);
+    }
+
+    public double[] getFromToStep() {
+
+        if (!isRange())
+            return null;
+
+        final double[] fromTo = getKmRange();
+
+        if (fromTo == null)
+            return null;
+
+        final StateData dStep = getArtifact().getData("ld_step");
+        if (dStep == null)
+            return null;
+
+        final double[] result = new double[3];
+        result[0] = fromTo[0];
+        result[1] = fromTo[1];
+
+        try {
+            final String dStepValue = (String) dStep.getValue();
+            result[2] = DoubleUtil.round(Double.parseDouble(dStepValue) / 1000d);
+            return result;
+        }
+        catch (final NumberFormatException nfe) {
+            nfe.printStackTrace();
+            return null;
+        }
+    }
+
+    public final double getStartKm() {
+
+        final KM_MODE mode = getKmRangeMode();
+        switch (mode) {
+        case RANGE:
+        case DISTANCE_ONLY:
+            return getFrom();
+
+        case LOCATIONS:
+        case NONE:
+        default:
+            final double[] locations = getLocations();
+            if( locations != null && locations.length > 0 )
+                // TODO: this is the old behaviour, but what happens if the user enters the values unsorted?
+                return locations[0];
+
+            return Double.NaN;
+        }
+    }
+
+    public double[] getKms() {
+
+        if (isRange())
+            return getKmSteps();
+
+        return getLocations();
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/DGMAccess.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/DGMAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -18,9 +18,6 @@
 
     private String geoJSON;
 
-    public DGMAccess() {
-    }
-
     public DGMAccess(D4EArtifact artifact) {
         super(artifact);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,68 +8,74 @@
 
 package org.dive4elements.river.artifacts.access;
 
-import gnu.trove.TDoubleArrayList;
-
+import org.apache.commons.lang.math.DoubleRange;
 import org.apache.log4j.Logger;
-
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.WINFOArtifact;
-
+import org.dive4elements.river.utils.DoubleUtil;
 import org.dive4elements.river.utils.RiverUtils;
-import org.dive4elements.river.utils.DoubleUtil;
 
+import gnu.trove.TDoubleArrayList;
 
 /** For the moment, light-weight wrapper around RiverUtils. */
 // TODO employ 'Caching' like other Accesses, remove usage of RiverUtils.
-public class RangeAccess
-extends RiverAccess
-{
+public class RangeAccess extends RiverAccess {
     private static Logger log = Logger.getLogger(RangeAccess.class);
 
-    public static enum KM_MODE { RANGE, LOCATIONS, NONE };
+    public static enum KM_MODE {
+        RANGE, LOCATIONS, NONE, DISTANCE_ONLY
+    }
 
     /** The default step width between the start end end kilometer. */
     public static final double DEFAULT_KM_STEPS = 0.1;
 
-    double[] kmRange;
+    private Double from;
 
-    Double from;
+    private Double to;
 
-    Double to;
-
-    Double step;
+    private Double step;
 
     private KM_MODE mode;
 
-    public RangeAccess() {
-    }
-
-    public RangeAccess(D4EArtifact artifact) {
+    public RangeAccess(final D4EArtifact artifact) {
         super(artifact);
     }
 
-
     /** Evaluate the ld_mode data of artifact. */
     public KM_MODE getKmRangeMode() {
-        if (mode != null) {
-            return mode;
-        }
-        String modeData = getString("ld_mode");
+        if (this.mode != null)
+            return this.mode;
 
-        if (modeData == null || modeData.length() == 0) {
-            mode = KM_MODE.NONE;
+        final String modeData = getString("ld_mode");
+        this.mode = parseRangeMode(modeData);
+
+        return this.mode;
+    }
+
+    private KM_MODE parseRangeMode(final String modeData) {
+
+        if (modeData == null)
+            return KM_MODE.NONE;
+
+        switch (modeData) {
+        case "distance":
+            return KM_MODE.RANGE;
+
+        case "distance_only":
+            return KM_MODE.DISTANCE_ONLY;
+
+        case "locations":
+            return KM_MODE.LOCATIONS;
+
+        default:
+            return KM_MODE.NONE;
         }
-        else if (modeData.equals("distance"))  {
-            mode = KM_MODE.RANGE;
-        }
-        else if (modeData.equals("locations")) {
-            mode = KM_MODE.LOCATIONS;
-        }
-        else {
-            mode = KM_MODE.NONE;
-        }
+    }
 
-        return mode;
+    public final DoubleRange getRange() {
+        final double from = getFrom();
+        final double to = getTo();
+        return new DoubleRange(from, to);
     }
 
     /** Check if the calculation mode is Range. */
@@ -82,39 +88,28 @@
      * (from ld_locations data), null if not parameterized this way.
      */
     public double[] getLocations() {
-        String locationStr = getString("ld_locations");
+        final String locationStr = getString("ld_locations");
 
         if (locationStr == null || locationStr.length() == 0) {
             if (getArtifact() instanceof WINFOArtifact) {
-                WINFOArtifact winfo = (WINFOArtifact) getArtifact();
-                if (winfo.getReferenceStartKm() != null
-                    && winfo.getReferenceEndKms() != null
-                ) {
-                    return new double[]
-                        {
-                            winfo.getReferenceStartKm().doubleValue(),
-                            winfo.getReferenceEndKms()[0]
-                        };
-                }
-                else if (winfo.getReferenceStartKm() != null) {
-                    return new double[]
-                        {
-                            winfo.getReferenceStartKm().doubleValue(),
-                            winfo.getReferenceStartKm().doubleValue()
-                        };
+                final WINFOArtifact winfo = (WINFOArtifact) getArtifact();
+                if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) {
+                    return new double[] { winfo.getReferenceStartKm().doubleValue(), winfo.getReferenceEndKms()[0] };
+                } else if (winfo.getReferenceStartKm() != null) {
+                    return new double[] { winfo.getReferenceStartKm().doubleValue(), winfo.getReferenceStartKm().doubleValue() };
                 }
             }
             return null;
         }
 
-        String[] tmp               = locationStr.split(" ");
-        TDoubleArrayList locations = new TDoubleArrayList();
+        final String[] tmp = locationStr.split(" ");
+        final TDoubleArrayList locations = new TDoubleArrayList();
 
-        for (String l: tmp) {
+        for (final String l : tmp) {
             try {
                 locations.add(Double.parseDouble(l));
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 log.debug(nfe.getLocalizedMessage(), nfe);
             }
         }
@@ -125,87 +120,89 @@
     }
 
     public boolean hasFrom() {
-        return from != null || (from = getDouble("ld_from")) != null;
+        return this.from != null || (this.from = getDouble("ld_from")) != null;
     }
 
     public boolean hasTo() {
-        return to != null || (to = getDouble("ld_to")) != null;
+        return this.to != null || (this.to = getDouble("ld_to")) != null;
     }
 
-    /* If left_to_right is set to true this returns
-     * the smaller value of from and to. */
-    public double getFrom(boolean left_to_right) {
+    /*
+     * If left_to_right is set to true this returns
+     * the smaller value of from and to.
+     */
+    public double getFrom(final boolean left_to_right) {
         if (!left_to_right) {
             return getFrom();
         }
-        double from = getFrom();
-        double to = getTo();
+        final double from = getFrom();
+        final double to = getTo();
         return from > to ? to : from;
     }
 
     /** Return ld_from data (in km). If not found, the min. */
     public double getFrom() {
-        if (from == null) {
-            from = getDouble("ld_from");
+        if (this.from == null) {
+            this.from = getDouble("ld_from");
         }
 
         if (log.isDebugEnabled()) {
-            log.debug("from from data: '" + from + "'");
+            log.debug("from from data: '" + this.from + "'");
         }
 
-        if (from == null) {
+        if (this.from == null) {
             log.warn("No 'from' found. Assume min of river.");
             return getRiver().determineMinMaxDistance()[0];
         }
 
-        return from.doubleValue();
+        return this.from.doubleValue();
     }
 
-    /* If left_to_right is set to true this returns
-     * the larger value of from and to. */
-    public double getTo(boolean left_to_right) {
+    /*
+     * If left_to_right is set to true this returns
+     * the larger value of from and to.
+     */
+    public double getTo(final boolean left_to_right) {
         if (!left_to_right) {
             return getTo();
         }
-        double from = getFrom();
-        double to = getTo();
+        final double from = getFrom();
+        final double to = getTo();
         return from > to ? from : to;
     }
 
     /** Return ld_to data (in km), if not found, the max. */
     public double getTo() {
-        if (to == null) {
-            to = getDouble("ld_to");
+        if (this.to == null) {
+            this.to = getDouble("ld_to");
         }
 
         if (log.isDebugEnabled()) {
-            log.debug("to from data: '" + to + "'");
+            log.debug("to from data: '" + this.to + "'");
         }
 
-        if (to == null) {
+        if (this.to == null) {
             log.warn("No 'to' found. Assume max of river.");
             return getRiver().determineMinMaxDistance()[1];
         }
 
-        return to.doubleValue();
+        return this.to.doubleValue();
     }
 
-
     /** Step width for calculation. */
     public Double getStep() {
 
-        if (step == null) {
-            step = getDouble("ld_step");
+        if (this.step == null) {
+            this.step = getDouble("ld_step");
         }
 
         if (log.isDebugEnabled()) {
-            log.debug("step: '" + step + "'");
+            log.debug("step: '" + this.step + "'");
         }
 
-        return step;
+        return this.step;
     }
 
-
     /**
      * Get min and max kilometer, independent of parametization
      * (ld_from/to vs ld_locations).
@@ -213,37 +210,35 @@
     public double[] getKmRange() {
         // TODO store kmRange in field.
         switch (getKmRangeMode()) {
-            case RANGE: {
+        case RANGE:
+        case DISTANCE_ONLY:
+            return getKmFromTo();
+
+        case LOCATIONS: {
+            final double[] locs = getLocations();
+            // if no locations, nPE.
+            if (locs == null) {
+                log.warn("no locations to get km range from.");
+                return new double[] { Double.NaN, Double.NaN };
+            }
+            return new double[] { locs[0], locs[locs.length - 1] };
+        }
+
+        case NONE: {
+            final double[] locs = getLocations();
+            if (locs != null) {
+                return new double[] { locs[0], locs[locs.length - 1] };
+            } else {
                 return getKmFromTo();
             }
-
-            case LOCATIONS: {
-                double[] locs = getLocations();
-                // if no locations, nPE.
-                if (locs == null) {
-                    log.warn("no locations to get km range from.");
-                    return new double[] { Double.NaN, Double.NaN };
-                }
-                return new double[] { locs[0], locs[locs.length-1] };
-            }
-
-            case NONE: {
-                double[] locs = getLocations();
-                if (locs != null) {
-                    return new double[] { locs[0], locs[locs.length-1] };
-                }
-                else {
-                    return getKmFromTo();
-                }
-            }
+        }
         }
 
         return new double[] { Double.NaN, Double.NaN };
     }
 
-
     public double[] getKmFromTo() {
-         return RiverUtils.getKmFromTo(this.getArtifact());
+        return RiverUtils.getKmFromTo(this.getArtifact());
     }
 
     /**
@@ -263,5 +258,13 @@
 
         return DoubleUtil.explode(getFrom(), getTo(), step);
     }
+
+    public final double getLowerKm() {
+        return Math.min(this.getFrom(), this.getTo());
+    }
+
+    public final double getUpperKm() {
+        return Math.max(this.getFrom(), this.getTo());
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RiverAccess.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RiverAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -24,11 +24,7 @@
     private static Logger log = Logger.getLogger(RiverAccess.class);
 
     /** River name. */
-    protected String river;
-
-
-    public RiverAccess() {
-    }
+    private String river;
 
     public RiverAccess(D4EArtifact artifact) {
         super(artifact);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SQRelationAccess.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SQRelationAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -22,18 +22,15 @@
 {
     private static Logger log = Logger.getLogger(SQRelationAccess.class);
 
-    protected Double    location;
+    private Double    location;
 
-    protected DateRange period;
+    private DateRange period;
 
-    protected Double    outliers;
+    private Double    outliers;
 
     private String      method;
 
-    protected MeasurementStation measurementStation;
-
-    public SQRelationAccess() {
-    }
+    private MeasurementStation measurementStation;
 
     public SQRelationAccess(D4EArtifact artifact) {
         super(artifact);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BUNDUArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.bundu;
+
+import org.apache.commons.lang.StringUtils;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+
+/**
+ * The default BUNDU artifact.
+ *
+ * @author Gernot Belger
+ */
+public class BUNDUArtifact extends D4EArtifact {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 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 = "bundu";
+
+    private static final String FIELD_RIVER = "river";
+
+    private static final String FIELD_MODE = "calculation_mode";
+
+    static {
+        // Active/deactivate facets.
+        // BEWARE: we can only define one activity for "sinfo", so we use the artifact
+        // as place for this
+        FacetActivity.Registry.getInstance().register(ARTIFACT_NAME, new FacetActivity() {
+            @Override
+            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String output) {
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Default constructor, because it's serializable.
+     */
+    public BUNDUArtifact() {
+    }
+
+    /**
+     * Returns the name of the concrete artifact.
+     *
+     * @return the name of the concrete artifact.
+     */
+    @Override
+    public String getName() {
+        return ARTIFACT_NAME;
+    }
+
+    public BunduCalcMode getCalculationMode() {
+
+        final String calc = getDataAsString(FIELD_MODE);
+        if (calc == null) {
+            throw new IllegalArgumentException(ERROR_NO_CALCULATION_MODE);
+        }
+
+        try {
+            return BunduCalcMode.valueOf(StringUtils.trimToEmpty(calc).toLowerCase());
+        }
+        catch (final Exception e) {
+            throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE, e);
+        }
+    }
+
+    public String getRiver() {
+        return getDataAsString(FIELD_RIVER);
+    }
+}
\ 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/bundu/BunduCalcMode.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,16 @@
+/* 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.bundu;
+
+public enum BunduCalcMode {
+
+    bundu_analysis, bundu_vollmer, bundu_bezugswst
+}
\ 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/bundu/CalculationSelectBundu.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,61 @@
+/* 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.bundu;
+
+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 CalculationSelectBundu extends DefaultState {
+
+    private static final long serialVersionUID = 1L;
+
+    /** The log that is used in this class. */
+    private static Logger log = Logger.getLogger(CalculationSelectBundu.class);
+
+    @Override
+    protected Element[] createItems(final XMLUtils.ElementCreator cr, final Artifact artifact, final String name, final CallContext context) {
+        final CallMeta meta = context.getMeta();
+
+        final Collection<Element> calcs = new ArrayList<>(BunduCalcMode.values().length);
+
+        for (final BunduCalcMode calcMode : BunduCalcMode.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(final Artifact artifact) throws IllegalArgumentException {
+        log.debug("CalculationSelect.validate");
+
+        final BUNDUArtifact m_artifact = (BUNDUArtifact) artifact;
+        /* throws an exception if calculation mode is invalid */
+        m_artifact.getCalculationMode();
+        return true;
+    }
+}
\ 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/bundu/bezugswst/BezugswstState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,32 @@
+/** 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.bundu.bezugswst;
+
+import org.dive4elements.river.artifacts.states.DefaultState;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class BezugswstState extends DefaultState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FlowDepthState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * From this state can only be continued trivially.
+     */
+    @Override
+    protected String getUIProvider() {
+        return "continue";
+    }
+
+}
\ 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/bundu/bezugswst/FixationChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,31 @@
+/* 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.bundu.bezugswst;
+
+import java.util.LinkedHashMap;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.states.RadioSelect;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class FixationChoice extends RadioSelect {
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected LinkedHashMap<String, String> makeEntries(final CallMeta meta, final Artifact artifact) {
+        final LinkedHashMap<String, String> entries = new LinkedHashMap<>();
+        entries.put("state.bundu.fix.auto", null);
+        entries.put("state.bundu.fix.manual", null);
+        return entries;
+    }
+
+}
\ 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/common/AbstractCalculationExportableResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,78 @@
+/** 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.common;
+
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+import net.sf.jasperreports.engine.JRException;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public abstract class AbstractCalculationExportableResult extends AbstractCalculationResult {
+
+    private static final long serialVersionUID = 1L;
+
+    public AbstractCalculationExportableResult(final String label, final Collection<ResultRow> rows) {
+        super(label, rows);
+    }
+
+    public abstract void writeCSVHeader(ExportContextCSV exportContextCSV, final RiverInfo river);
+
+    public final void writeCsv(final ExportContextCSV exportContextCSV) {
+
+        writeCSVResultMetadata(exportContextCSV);
+        // wenn resultsmetadata null sind!? keine neue zeile
+        // writer.writeNext(new String[] { "" }); // break line in den Implementationen,
+        // weil es sein kann, dass KEINE ResultMetadata geschrieben werden; dann wäre eine Leerzeile überflüssig
+
+        /* now the value rows */
+        final Collection<ResultRow> rows = getRows();
+        for (final ResultRow row : rows)
+            writeCSVRow(exportContextCSV, row);
+    }
+
+    protected abstract void writeCSVResultMetadata(final ExportContextCSV exportContextCSV);
+
+    protected void writeCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+        final String[] formattedRow = formatCSVRow(exportContextCSV, row);
+        exportContextCSV.writeCSVLine(formattedRow);
+    }
+
+    protected abstract String[] formatCSVRow(ExportContextCSV exportContextCSV, final ResultRow row);
+
+    protected abstract String[] formatPDFRow(ExportContextPDF exportContextPDF, ResultRow row);
+
+    public JasperDesigner addReport(final ExportContextPDF exportContext, final JasperReporter reporter, final MetaAndTableJRDataSource source)
+            throws JRException {
+
+        final JasperDesigner design = reporter.addReport(getJasperFile(), source);
+        addJRTableHeader(exportContext, source);
+        addJRTableData(exportContext, source);
+        return design;
+    }
+
+    protected abstract String getJasperFile();
+
+    protected abstract void addJRTableHeader(ExportContextPDF exportContext, MetaAndTableJRDataSource source);
+
+    private void addJRTableData(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+
+        final Collection<ResultRow> rows = getRows();
+
+        for (final ResultRow row : rows) {
+
+            final String[] formattedRow = formatPDFRow(exportContext, row);
+            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/common/AbstractCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,77 @@
+/** 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.common;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * @author Gernot Belger
+ */
+public abstract class AbstractCalculationResult implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    protected final Collection<ResultRow> rows;
+
+    private final String label;
+
+    public AbstractCalculationResult(final String label, final Collection<ResultRow> rows) {
+        this.label = label;
+        this.rows = new ArrayList<>(rows);
+    }
+
+    public final String getLabel() {
+        return this.label;
+    }
+
+    public boolean isEmpty() {
+        return this.rows.isEmpty();
+    }
+
+    public Collection<ResultRow> getRows() {
+        return Collections.unmodifiableCollection(this.rows);
+    }
+
+    public final double[][] getStationPoints(final IResultType type) { // gehört die Methode hier rein? oder in erbende Klassen?
+
+        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
+        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
+
+        for (final ResultRow row : this.rows) {
+
+            final double station = row.getDoubleValue(GeneralResultType.station); // TODO: move "station" (and others) to common
+            final double value = row.getDoubleValue(type);
+
+            xPoints.add(station);
+            yPoints.add(value);
+        }
+
+        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
+    }
+
+    protected final <TYPE> List<TYPE> getValues(final IResultType type) {
+
+        final List<TYPE> values = new ArrayList<>();
+
+        for (final ResultRow row : this.rows) {
+            @SuppressWarnings("unchecked")
+            final TYPE value = (TYPE) row.getValue(type);
+            values.add(value);
+        }
+
+        return values;
+    }
+}
\ 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/common/AbstractCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,79 @@
+/** 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.common;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Gernot Belger
+ */
+public abstract class AbstractCalculationResults<RESULT extends AbstractCalculationResult> implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final List<RESULT> results = new ArrayList<>();
+
+    private final String calcModeLabel;
+
+    private final String user;
+
+    private final RiverInfo river;
+
+    private final DoubleRange calcRange;
+
+    public AbstractCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) {
+        this.calcModeLabel = calcModeLabel;
+        this.user = user;
+        this.river = river;
+        this.calcRange = calcRange;
+    }
+
+    public final String getCalcModeLabel() {
+        return this.calcModeLabel;
+    }
+
+    public final String getUser() {
+        return this.user;
+    }
+
+    public final RiverInfo getRiver() {
+        return this.river;
+    }
+
+    public final DoubleRange getCalcRange() {
+        return this.calcRange;
+    }
+
+    //// COPY FROM AbtractCalculationListResults -> further refactoring necessary?
+    public final void addResult(final RESULT result, final Calculation problems) {
+        /* we assume error reporting was already done in this case */
+        if (result == null)
+            return;
+
+        if (result.isEmpty()) {
+            problems.addProblem("abstractsinfocalculationresults.emptyResult", result.getLabel());
+            return;
+        }
+
+        this.results.add(result);
+    }
+
+    public final List<RESULT> getResults() {
+        return Collections.unmodifiableList(this.results);
+    }
+
+}
\ 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/common/AbstractCommonExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,132 @@
+/** 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.common;
+
+import java.io.OutputStream;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.exports.AbstractExporter;
+import org.w3c.dom.Document;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import net.sf.jasperreports.engine.JRException;
+
+/**
+ * @author Gernot Belger
+ */
+public abstract class AbstractCommonExporter<RESULT extends AbstractCalculationExportableResult, RESULTS extends AbstractCalculationResults<RESULT>> extends AbstractExporter {
+
+    /** The log used in this exporter. */
+    private final Logger log = Logger.getLogger(getClass());
+
+    /** The log used in this exporter. */
+    protected final Logger getLog() {
+        return this.log;
+    }
+
+    private RESULTS results = null;
+
+    @Override
+    public void init(final String outName, final Document request, final OutputStream out, final CallContext context) {
+        super.init(outName, request, out, context);
+    }
+
+    @Override
+    protected final void addData(final Object d) {
+        /* reset */
+        this.results = null;
+
+        if (d instanceof CalculationResult) {
+
+            final Object dat = ((CalculationResult) d).getData();
+            if (dat != null) {
+                @SuppressWarnings("unchecked")
+                final RESULTS result = (RESULTS) dat;
+                this.results = result;
+            }
+        }
+    }
+
+    protected final RESULTS getResults() {
+        return this.results;
+    }
+
+    @Override
+    protected final void writeCSVData(final CSVWriter writer) {
+
+        final ExportContextCSV exportContext = new ExportContextCSV(this.context, writer, this.results);
+
+        doWriteCSVData(exportContext, this.results);
+    }
+
+    protected final void doWriteCSVData(final ExportContextCSV exportContext, final RESULTS results) {
+
+        writeCSVGlobalMetadata(exportContext, results);
+
+        final RiverInfo river = results.getRiver();
+
+        final Class<?> lastResultType = null;
+
+        for (final AbstractCalculationExportableResult result : results.getResults()) {
+
+            final Class<?> resultType = result.getClass();
+            if (lastResultType == null || lastResultType != resultType) {
+                exportContext.writeBlankLine();
+                result.writeCSVHeader(exportContext, river);
+                exportContext.writeBlankLine();
+            } else
+                exportContext.writeCSVLine(new String[] { "#" });
+
+            result.writeCsv(exportContext);
+        }
+    }
+
+    protected abstract void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final RESULTS results);
+
+    @Override
+    protected final void writePDF(final OutputStream out) {
+        doWritePdf(out, this.results);
+    }
+
+    private final void doWritePdf(final OutputStream out, final RESULTS results) {
+
+        try {
+            final ExportContextPDF exportContext = new ExportContextPDF(this.context, results);
+
+            final JasperReporter reporter = new JasperReporter();
+
+            for (final RESULT result : results.getResults()) {
+
+                final MetaAndTableJRDataSource source = new MetaAndTableJRDataSource();
+
+                writePDFGlobalMetadata(exportContext, source);
+
+                final JasperDesigner design = result.addReport(exportContext, reporter, source);
+                configureDesign(result, design);
+            }
+
+            reporter.exportPDF(out);
+        }
+        catch (final JRException je) {
+            getLog().warn("Error generating PDF Report!", je);
+        }
+    }
+
+    /**
+     * Override to implement, does nothing by default.
+     */
+    protected void configureDesign(final RESULT result, final JasperDesigner design) {
+    }
+
+    protected abstract void writePDFGlobalMetadata(ExportContextPDF exportContext, MetaAndTableJRDataSource source);
+}
\ 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/common/AbstractExportContext.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,92 @@
+/** 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.common;
+
+import java.text.NumberFormat;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.utils.Formatter;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public abstract class AbstractExportContext implements IExportContext {
+
+    private NumberFormat qFormat = null;
+
+    private NumberFormat flowDepthFormat = null;
+    private NumberFormat salixScenFormat = null;
+    private NumberFormat kmFormat = null;
+
+    /** The CallContext object. */
+    private final CallContext context;
+
+    private final AbstractCalculationResults<?> results;
+
+    public AbstractExportContext(final CallContext context, final AbstractCalculationResults<?> results) {
+        this.context = context;
+        this.results = results;
+    }
+
+    protected final CallContext getContext() {
+        return this.context;
+    }
+
+    @Override
+    public final <RESULTS extends AbstractCalculationResults<?>> RESULTS getResults() {
+        @SuppressWarnings("unchecked")
+        final RESULTS resultsCast = (RESULTS) this.results;
+        return resultsCast;
+    }
+
+    // copy from AbstractExporter TODO merge with ExportContextPDF
+    protected NumberFormat getKmFormatter() {
+
+        if (this.kmFormat == null)
+            this.kmFormat = Formatter.getWaterlevelKM(getContext());
+
+        return this.kmFormat;
+    }
+
+    public NumberFormat getQFormatter() {
+        if (this.qFormat == null)
+            this.qFormat = Formatter.getWaterlevelQ(this.context);
+
+        return this.qFormat;
+    }
+
+    public final NumberFormat getFlowDepthFormatter() {
+        if (this.flowDepthFormat == null)
+            this.flowDepthFormat = Formatter.getFlowDepth(this.context);
+
+        return this.flowDepthFormat;
+    }
+
+    public final NumberFormat getSalixScenFormatter() {
+        if (this.salixScenFormat == null)
+            this.salixScenFormat = Formatter.getSalixLine(this.context);
+
+        return this.salixScenFormat;
+    }
+
+    protected String msg(final String key) {
+        return Resources.getMsg(this.context.getMeta(), key, key);
+    }
+
+    public final String msg(final String key, final Object... args) {
+        return Resources.getMsg(this.context.getMeta(), key, key, args);
+    }
+
+    @Override
+    public final String formatRowValue(final ResultRow row, final IResultType type) {
+        return row.exportValue(this.context, type);
+    }
+}
\ 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/common/AbstractResultType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,115 @@
+/** 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.common;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public abstract class AbstractResultType implements IResultType {
+
+    /* Cache for formatters because Formatter will always create new formats (which is very expensive) */
+    private final Map<Locale, NumberFormat> formatters = new HashMap<>();
+
+    private final String unit;
+
+    private final String csvHeader;
+
+    private final String pdfHeader;
+
+    protected AbstractResultType(final String unit, final String csvHeader, final String pdfHeader) {
+        this.unit = unit;
+        this.csvHeader = csvHeader;
+        this.pdfHeader = pdfHeader;
+
+    }
+
+    @Override
+    public abstract String exportValue(final CallContext context, final Object value);
+
+    protected final String exportStringValue(final Object value) {
+
+        if (value == null)
+            return StringUtils.EMPTY;
+
+        if (!(value instanceof String))
+            throw new IllegalStateException();
+
+        return (String) value;
+    }
+
+    @Override
+    public final double asDouble(final Object value) {
+        if (value == null)
+            return Double.NaN;
+
+        if (!(value instanceof Number))
+            throw new IllegalStateException();
+
+        final Number number = (Number) value;
+        return number.doubleValue();
+    }
+
+    protected final String exportDoubleValue(final CallContext context, final double value) {
+        if (Double.isNaN(value))
+            return StringUtils.EMPTY;
+
+        final NumberFormat formatter = getFormatter(context);
+        return formatter.format(value);
+    }
+
+    private NumberFormat getFormatter(final CallContext context) {
+        final CallMeta meta = context.getMeta();
+        final Locale locale = Resources.getLocale(meta);
+
+        if (!this.formatters.containsKey(locale))
+            this.formatters.put(locale, createFormatter(context));
+
+        return this.formatters.get(locale);
+    }
+
+    protected abstract NumberFormat createFormatter(CallContext context);
+
+    protected final String exportDateValue(final CallContext context, final Date value) {
+        final Locale locale = Resources.getLocale(context.getMeta());
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
+        return df.format(value);
+    }
+
+    @Override
+    public final String getCsvHeader() {
+        return this.csvHeader;
+    }
+
+    public final String getCsvHeader(final CallMeta meta) {
+        return Resources.getMsg(meta, this.csvHeader, this.csvHeader);
+    }
+
+    @Override
+    public final String getPdfHeader(final CallMeta meta) {
+        return Resources.getMsg(meta, this.pdfHeader, this.pdfHeader);
+    }
+
+    @Override
+    public final String getUnit() {
+        return this.unit;
+    }
+}
\ 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/common/DefaultCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,26 @@
+/** 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.common;
+
+import java.util.Collection;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class DefaultCalculationResult extends AbstractCalculationResult {
+
+    public DefaultCalculationResult(final String label, final Collection<ResultRow> rows) {
+        super(label, rows);
+        // do nothing,
+        // this class only serves as instantiable version of AbstractCalculationResult
+        // not intended for pdf/csv-export
+    }
+}
\ 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/common/EpochYearAccessHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,101 @@
+/** 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.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.Access;
+import org.dive4elements.river.artifacts.model.DateRange;
+import org.dive4elements.river.backend.utils.DateUtil;
+
+import gnu.trove.TIntArrayList;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+// TODO: rename?
+public class EpochYearAccessHelper extends Access {
+
+    private static Logger log = Logger.getLogger(EpochYearAccessHelper.class);
+
+    // private final Artifact artifact;
+
+    public EpochYearAccessHelper(final Artifact artifact) {
+        this.artifact = (D4EArtifact) artifact;
+    }
+
+    public String getYearEpoch() {
+        return getString("ye_select"); // ACHTUNG, Ergebniswerte wurden geändert in state.sinfo.epoch und state.sinfo.year
+    }
+
+    /** [year1, years2,..] if its about years. */
+    public int[] getYears(final String yearSelectedValue, final String yearKey) {
+        int[] years = null;
+
+        if (getYearEpoch().equals(yearSelectedValue)) {
+            final TIntArrayList ints = new TIntArrayList();
+            final String yearsData = getString(yearKey);
+            if (yearsData == null || yearsData.isEmpty()) {
+                log.warn("No years provided");
+                return null;
+            }
+            for (final String sValue : yearsData.split(" ")) {
+                try {
+                    ints.add(Integer.parseInt(sValue));
+                }
+                catch (final NumberFormatException e) {
+                    /* Client should prevent this */
+                    log.warn("Invalid year value: " + sValue);
+                    continue;
+                }
+            }
+
+            if (!ints.isEmpty()) {
+                ints.sort();
+                years = ints.toNativeArray();
+            }
+            return years;
+        }
+        return null;
+    }
+
+    public List<DateRange> getEpochs(final String epochSelectedValue, final String epochKey) {
+        final List<DateRange> epochs = new ArrayList<>();
+        // if (epochs != null) {
+        // return epochs;
+        // }
+
+        if (!getYearEpoch().equals(epochSelectedValue)) {
+            return null;
+        }
+
+        final String data = getString(epochKey);
+        if (data == null) {
+            log.warn("No 'epochs' parameter specified!");
+            return null;
+        }
+
+        for (final String part : data.split(";")) {
+            final String[] values = part.split(",");
+            try {
+                epochs.add(new DateRange(DateUtil.getStartDateFromYear(Integer.parseInt(values[0])), DateUtil.getEndDateFromYear(Integer.parseInt(values[1]))));
+            }
+            catch (final NumberFormatException nfe) {
+                log.warn("Cannot parse int from string: '" + values + "'");
+            }
+        }
+        return epochs;
+    }
+}
\ 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/common/ExportContextCSV.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,186 @@
+/** 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.common;
+
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Locale;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.FLYS;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoI18NStrings;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+
+import au.com.bytecode.opencsv.CSVWriter;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public final class ExportContextCSV extends AbstractExportContext {
+
+    private static final String CSV_META_HEADER_EVALUATOR = "sinfo.export.flow_depth.csv.meta.header.sounding.evaluator";
+
+    private static final String CSV_META_HEADER_SOUNDING = "sinfo.export.flow_depth.csv.meta.header.sounding";
+
+    private static final String CSV_META_HEADER_SOUNDING_YEAR = "sinfo.export.flow_depth.csv.meta.header.sounding.year";
+
+    private static final String CSV_META_HEADER_SOUNDING_TYPE = "sinfo.export.flow_depth.csv.meta.header.sounding.type";
+
+    private static final String CSV_META_HEADER_SOUNDING_PRJ = "sinfo.export.flow_depth.csv.meta.header.sounding.prj";
+
+    private static final String CSV_META_HEADER_SOUNDING_ELEVATIOIN_MODEL = "sinfo.export.flow_depth.csv.meta.header.sounding.elevationmodel";
+
+    private static final String CSV_META_HEADER_SOUNDING_ELEVATIOIN_MODEL_ORIGINAL = "sinfo.export.flow_depth.csv.meta.header.sounding.elevationmodel.original";
+
+    private final CSVWriter writer;
+
+    private final AbstractCalculationResults<?> results;
+
+    public ExportContextCSV(final CallContext context, final CSVWriter writer, final AbstractCalculationResults<?> results) {
+        super(context, results);
+
+        this.writer = writer;
+        this.results = results;
+    }
+
+    public final void writeCSVMetaEntry(final String message, final Object... messageArgs) {
+
+        final CallMeta meta = getContext().getMeta();
+
+        this.writer.writeNext(new String[] { Resources.getMsg(meta, message, message, messageArgs) });
+    }
+
+    public void writeBlankLine() {
+        writeCSVLine(new String[] { "" });
+    }
+
+    // *** CUSTOM STUFF that is used multiple times ***///
+
+    public final void writeCSVSoundingMetadata(final BedHeightInfo sounding) {
+        // "##METADATEN PEILUNG"
+        writeCSVSoundingMetadata(sounding, CSV_META_HEADER_SOUNDING);
+
+    }
+
+    public void writeCSVLine(final String[] line) {
+        this.writer.writeNext(line);
+    }
+
+    public String formatCsvHeader(final IResultType type) {
+        return msg(type.getCsvHeader());
+    }
+
+    public final void writeCSVGlobalMetadataDefaults() {
+        // TODO: results as member
+        final String calcModeLabel = this.results.getCalcModeLabel();
+        final RiverInfo river = this.results.getRiver();
+        final DoubleRange calcRange = this.results.getCalcRange();
+
+        writeCSVMetaEntry(I18NStrings.CSV_META_HEADER_RESULT, msg(I18NStrings.CSV_META_HEADER_RESULT_LABEL), river.getName(), calcModeLabel);
+
+        // "# FLYS-Version: "
+        writeCSVMetaEntry(I18NStrings.CSV_META_VERSION, msg(I18NStrings.CSV_META_VERSION_LABEL), FLYS.VERSION);
+
+        // "# Bearbeiter: "
+        writeCSVMetaEntry(I18NStrings.CSV_META_USER, msg(I18NStrings.CSV_META_USER_LABEL), this.results.getUser());
+
+        // "# Datum der Erstellung: "
+        final Locale locale = Resources.getLocale(getContext().getMeta());
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+        writeCSVMetaEntry(I18NStrings.CSV_META_CREATION, msg(I18NStrings.CSV_META_CREATION_LABEL), df.format(new Date()));
+
+        // "# Gewässer: "
+        writeCSVMetaEntry(I18NStrings.CSV_META_RIVER, msg(I18NStrings.CSV_META_RIVER_LABEL), river.getName());
+
+        // "# Höhensystem des Flusses: "
+        writeCSVMetaEntry(I18NStrings.CSV_META_HEIGHT_UNIT_RIVER, river.getWstUnit());
+
+        if (calcRange != null) {
+            // "# Ort/Bereich (km): "
+            writeCSVMetaEntry(I18NStrings.CSV_META_RANGE, msg(I18NStrings.CSV_META_RANGE_LABEL), getKmFormatter().format(calcRange.getMinimumDouble()),
+                    getKmFormatter().format(calcRange.getMaximumDouble()));
+        }
+    }
+
+    public final void writeCSVWaterlevelMetadata(final WstInfo wst) {
+        writeCSVWaterlevelMetadata(wst, SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL); // default Label; used in 99%
+    }
+
+    public final void writeCSVWaterlevelMetadata(final WstInfo wst, final String mainLabel) {
+        // "##METADATEN WASSERSPIEGELLAGE"
+        writeCSVMetaEntry(mainLabel);
+
+        // "# Bezeichnung der Wasserspiegellage: "
+        writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_NAME, wst.getLabel());
+
+        // "# Bezugspegel: "
+        writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_GAUGE, wst.getGauge());
+
+        // "# Jahr/Zeitraum der Wasserspiegellage: "
+        final int year = wst.getYear();
+        if (year > 0)
+            writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_YEAR, Integer.toString(year));
+    }
+
+    /**
+     * Formats header with unit: msg [unit]
+     */
+
+    public String msgUnitCSV(final IResultType typeWithUnit) { // TODO: use generic Type!
+        final String unit = msg(typeWithUnit.getUnit());
+        return msgUnitCSV(typeWithUnit, unit);
+    }
+
+    public String msgUnitCSV(final IResultType type, final String unit) {
+        final String msg = msg(type.getCsvHeader());
+        return String.format("%s [%s]", msg, unit);
+    }
+
+    public void writeCSVSoundingMetadata(final BedHeightInfo sounding, final String label) {
+
+        // "##METADATEN PEILUNG"
+        writeCSVMetaEntry(label);
+
+        // "# Jahr der Peilung: "
+        writeCSVMetaEntry(CSV_META_HEADER_SOUNDING_YEAR, Integer.toString(sounding.getYear()));
+        // "# Aufnahmeart: "
+        writeCSVMetaEntry(CSV_META_HEADER_SOUNDING_TYPE, sounding.getType());
+        // "# Auswerter: "
+        writeCSVMetaEntry(CSV_META_HEADER_EVALUATOR, sounding.getEvaluationBy());
+        // "# Lagesystem: "
+        writeCSVMetaEntry(CSV_META_HEADER_SOUNDING_PRJ, sounding.getLocationSystem());
+        // "# Höhensystem: "
+        writeCSVMetaEntry(CSV_META_HEADER_SOUNDING_ELEVATIOIN_MODEL, sounding.getCurElevationModelUnit());
+        // "# ursprüngliches Höhensystem: "
+        writeCSVMetaEntry(CSV_META_HEADER_SOUNDING_ELEVATIOIN_MODEL_ORIGINAL, sounding.getOldElevationModelUnit());
+
+    }
+
+    public final String msgUnitLabel(final IResultType typeWithUnit, final String label) {
+        final String msg = msg(typeWithUnit.getCsvHeader());
+        final String unit = msg(typeWithUnit.getUnit());
+        return String.format("%s [%s] (%s)", msg, unit, label);
+    }
+
+    public void writeTitleForTabs(final String tabTitleMsg, final int colSize) {
+
+        final Collection<String> title = new ArrayList<>(colSize);
+        title.add(msg("export_csv_title") + msg(tabTitleMsg));
+        writeCSVLine(title.toArray(new String[colSize]));
+    }
+}
\ 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/common/ExportContextPDF.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,83 @@
+/** 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.common;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.FLYS;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public final class ExportContextPDF extends AbstractExportContext {
+
+    public ExportContextPDF(final CallContext context, final AbstractCalculationResults<?> results) {
+        super(context, results);
+    }
+
+    // TODO: rename
+    public String msgPdf(final SInfoResultType type) {
+        return type.getPdfHeader(getContext().getMeta());
+    }
+
+    public void addJRMetadata(final MetaAndTableJRDataSource source, final String key, final IResultType type) {
+        source.addMetaData(key, type.getPdfHeader(getContext().getMeta()));
+    }
+
+    public void addJRMetadata(final MetaAndTableJRDataSource source, final String key, final String msg) {
+        source.addMetaData(key, msg);
+    }
+
+    // *** CUSTOM STUFF that is used multiple times ***///
+    public void addJRMetaDataDefaults(final MetaAndTableJRDataSource source) {
+
+        source.addMetaData("header", msg(I18NStrings.CSV_META_HEADER_RESULT_LABEL));
+        source.addMetaData("calcMode", getResults().getCalcModeLabel());
+
+        source.addMetaData("version_label", msg(I18NStrings.CSV_META_VERSION_LABEL));
+        source.addMetaData("version", FLYS.VERSION);
+
+        source.addMetaData("user_label", msg(I18NStrings.CSV_META_USER_LABEL));
+        source.addMetaData("user", getResults().getUser());
+
+        final Locale locale = Resources.getLocale(getContext().getMeta());
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+        source.addMetaData("date_label", msg(I18NStrings.CSV_META_CREATION_LABEL));
+        source.addMetaData("date", df.format(new Date()));
+    }
+
+    public void addJRMetaDataUSINFO(final MetaAndTableJRDataSource source) {
+
+        /* general metadata */
+        addJRMetaDataDefaults(source);
+
+        final RiverInfo river = getResults().getRiver();
+        final String wstUnitName = river.getWstUnit();
+
+        source.addMetaData("river_label", msg(I18NStrings.CSV_META_RIVER_LABEL));
+        source.addMetaData("river", river.getName());
+        source.addMetaData("river_unit", wstUnitName);
+
+        final DoubleRange calcRange = getResults().getCalcRange();
+        final NumberFormat kmFormatter = getKmFormatter();
+        final String rangeValue = String.format("%s - %s", kmFormatter.format(calcRange.getMinimumDouble()), kmFormatter.format(calcRange.getMaximumDouble()));
+        source.addMetaData("range_label", msg(I18NStrings.CSV_META_RANGE_LABEL));
+        source.addMetaData("range", rangeValue);
+    }
+}
\ 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/common/GeneralResultType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,59 @@
+/** 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.common;
+
+import java.text.NumberFormat;
+import java.util.Date;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.utils.Formatter;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class GeneralResultType extends AbstractResultType {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final GeneralResultType station = new GeneralResultType(I18NStrings.UNIT_KM, I18NStrings.CSV_KM_HEADER) {
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getWaterlevelKM(context);
+        }
+    };
+
+    public static final GeneralResultType date = new GeneralResultType(I18NStrings.UNIT_NONE, I18NStrings.CSV_META_DATE) {
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportDateValue(context, (Date) value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    private GeneralResultType(final String unit, final String csvHeader) {
+
+        super(unit, csvHeader, csvHeader);
+    }
+
+    private GeneralResultType(final String unit, final String csvHeader, final String pdfHeader) {
+        super(unit, csvHeader, pdfHeader);
+    }
+}
\ 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/common/I18NStrings.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,67 @@
+/** 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.common;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public interface I18NStrings {
+    //////////// GENERIC TYPES + UNITS///////////////////////////////////////////////////////////////////////////////
+
+    // TODO: remove "sinfo" for these labels in messages.txt + de.messages.txt
+    // oder: die ganzen Strings hier raus und direkt verwenden
+
+    String CSV_KM_HEADER = "export.flow_depth.csv.header.km";
+
+    String CSV_META_HEADER_RESULT_LABEL = "sinfo.export.flow_depth.csv.meta.header.result.label";
+
+    String CSV_META_VERSION_LABEL = "sinfo.export.flow_depth.csv.meta.version.label";
+
+    String CSV_META_USER_LABEL = "sinfo.export.flow_depth.csv.meta.user.label";
+
+    String CSV_META_CREATION_LABEL = "sinfo.export.flow_depth.csv.meta.creation.label";
+
+    String CSV_META_RIVER_LABEL = "sinfo.export.flow_depth.csv.meta.river.label";
+
+    String CSV_META_RANGE_LABEL = "sinfo.export.flow_depth.csv.meta.range.label";
+
+    String CSV_META_HEADER_RESULT = "sinfo.export.flow_depth.csv.meta.header.result";
+
+    String CSV_META_VERSION = "sinfo.export.flow_depth.csv.meta.version";
+
+    String CSV_META_USER = "sinfo.export.flow_depth.csv.meta.user";
+
+    String CSV_META_CREATION = "sinfo.export.flow_depth.csv.meta.creation";
+
+    String CSV_META_RIVER = "sinfo.export.flow_depth.csv.meta.river";
+
+    String CSV_META_RANGE = "sinfo.export.flow_depth.csv.meta.range";
+
+    String CSV_META_HEIGHT_UNIT_RIVER = "sinfo.export.flow_depth.csv.meta.height_unit.river"; // move to child?
+
+    String CSV_META_DATE = "sinfo.export.csv.meta.date";
+
+    /// sonstiges:
+
+    // Einheiten:
+
+    String UNIT_NONE = "-";
+
+    String UNIT_M = "m";
+
+    String UNIT_KM = "km";
+
+    String UNIT_CM = "cm";
+
+    String UNIT_CM_A = "cm/a";
+
+    String UNIT_CUBIC_M = "m³/s";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/common/IExportContext.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.common;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public interface IExportContext {
+
+    String formatRowValue(ResultRow row, IResultType type);
+
+    <RESULTS extends AbstractCalculationResults<?>> RESULTS getResults();
+}
\ 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/common/IResultType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,31 @@
+/** 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.common;
+
+import java.io.Serializable;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.CallMeta;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public interface IResultType extends Serializable {
+
+    String exportValue(CallContext context, Object value);
+
+    double asDouble(Object value);
+
+    String getCsvHeader();
+
+    String getPdfHeader(CallMeta meta);
+
+    String getUnit();
+}
\ 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/common/JRReportSaxParserFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,59 @@
+/** 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.common;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import net.sf.jasperreports.engine.component.ComponentsBundle;
+import net.sf.jasperreports.engine.component.ComponentsEnvironment;
+import net.sf.jasperreports.engine.component.ComponentsXmlParser;
+import net.sf.jasperreports.engine.xml.BaseSaxParserFactory;
+import net.sf.jasperreports.engine.xml.JRXmlConstants;
+
+/**
+ * Own sax parser factory, because:
+ * - we do not want xml validation (we know it's good)
+ * - xerxes sax parser complains about two schemas with same namespace...
+ * 
+ * @author Domenico Nardi Tironi
+ */
+public class JRReportSaxParserFactory extends BaseSaxParserFactory {
+
+    @Override
+    protected boolean isValidating() {
+        return false;
+    }
+
+    @Override
+    protected List<String> getSchemaLocations() {
+        final List<String> schemas = new ArrayList<>();
+
+        schemas.add(getResourceURI(JRXmlConstants.JASPERREPORT_XSD_RESOURCE));
+        // schemas.add(getResourceURI(JRXmlConstants.JASPERREPORT_XSD_DTD_COMPAT_RESOURCE));
+
+        final Collection<ComponentsBundle> components = ComponentsEnvironment.getComponentBundles();
+        for (final ComponentsBundle componentManager : components) {
+            final ComponentsXmlParser xmlParser = componentManager.getXmlParser();
+
+            String schemaURI;
+            final String schemaResource = xmlParser.getInternalSchemaResource();
+            if (schemaResource != null) {
+                schemaURI = getResourceURI(schemaResource);
+            } else {
+                schemaURI = xmlParser.getPublicSchemaLocation();
+            }
+
+            schemas.add(schemaURI);
+        }
+        return schemas;
+    }
+}
\ 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/common/JasperDesigner.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,94 @@
+/** 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.common;
+
+import net.sf.jasperreports.engine.JRBand;
+import net.sf.jasperreports.engine.JRChild;
+import net.sf.jasperreports.engine.JRElement;
+import net.sf.jasperreports.engine.design.JasperDesign;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class JasperDesigner {
+
+    private final JasperDesign design;
+    private final MetaAndTableJRDataSource source;
+    private int startpageOffset = 0;
+
+    public JasperDesigner(final JasperDesign design, final MetaAndTableJRDataSource source) {
+        this.design = design;
+        this.source = source;
+    }
+
+    public void removeColumn(final String key) {
+
+        final JRBand colchildren = this.design.getColumnHeader();
+        final JRBand datachildren = this.design.getDetailSection().getBands()[0];
+        int width = 0;
+        if (colchildren != null && datachildren != null) {
+
+            final JRElement elementCol = colchildren.getElementByKey(key);
+            final JRElement elementData = datachildren.getElementByKey(key);
+            if (elementCol != null && elementData != null) {
+                width = elementCol.getWidth() + width;
+                final int indexCol = colchildren.getChildren().indexOf(elementCol);
+                final int indexData = datachildren.getChildren().indexOf(elementData);
+
+                elementCol.getElementGroup().getChildren().remove(elementCol);
+                elementData.getElementGroup().getChildren().remove(elementData);
+
+                for (int j = indexCol; j < colchildren.getChildren().size(); j++) {
+                    final JRChild element = colchildren.getChildren().get(j);
+                    if (element instanceof JRElement) {
+                        ((JRElement) element).setX(((JRElement) element).getX() - width);
+                    }
+                }
+                for (int j = indexData; j < datachildren.getChildren().size(); j++) {
+                    final JRChild element = datachildren.getChildren().get(j);
+                    if (element instanceof JRElement) {
+                        ((JRElement) element).setX(((JRElement) element).getX() - width);
+                    }
+                }
+            }
+
+            // width auf letzte spalte schlagen
+            addWidthToElement(colchildren.getElements()[colchildren.getElements().length - 1], width);
+            addWidthToElement(datachildren.getElements()[datachildren.getElements().length - 1], width);
+
+        } else {
+            // TODO: LOG
+            System.out.print("Column not found for key: " + key);
+        }
+
+    }
+
+    private void addWidthToElement(final JRElement element, final int width) {
+        if (element != null)
+            element.setWidth(element.getWidth() + width);
+    }
+
+    JasperDesign getDesign() {
+        return this.design;
+    }
+
+    public MetaAndTableJRDataSource getSource() {
+        return this.source;
+    }
+
+    public void setPagesCount(final int pagesCount) {
+        this.startpageOffset = pagesCount;
+    }
+
+    public int getPagesCount() {
+
+        return this.startpageOffset;
+    }
+}
\ 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/common/JasperReporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,125 @@
+/** 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.common;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.dive4elements.artifacts.common.utils.Config;
+
+import net.sf.jasperreports.engine.JRDataSource;
+import net.sf.jasperreports.engine.JRException;
+import net.sf.jasperreports.engine.JRExporterParameter;
+import net.sf.jasperreports.engine.JasperCompileManager;
+import net.sf.jasperreports.engine.JasperFillManager;
+import net.sf.jasperreports.engine.JasperPrint;
+import net.sf.jasperreports.engine.JasperReport;
+import net.sf.jasperreports.engine.design.JasperDesign;
+import net.sf.jasperreports.engine.export.JRPdfExporter;
+import net.sf.jasperreports.engine.export.JRPdfExporterParameter;
+import net.sf.jasperreports.engine.util.JRProperties;
+import net.sf.jasperreports.engine.xml.JRSaxParserFactory;
+import net.sf.jasperreports.engine.xml.JRXmlLoader;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class JasperReporter {
+
+    private final List<JasperDesigner> designs = new ArrayList<>();
+
+    private final Map<String, Object> parameters = new HashMap<>();
+
+    private final String confPath;
+
+    public JasperReporter() {
+        this.confPath = Config.getConfigDirectory().toString();
+
+        this.parameters.put("ReportTitle", "Exported Data");
+    }
+
+    public JasperDesigner addReport(final String jasperFile, final MetaAndTableJRDataSource source) throws JRException {
+
+        JRProperties.setProperty(JRSaxParserFactory.PROPERTY_REPORT_PARSER_FACTORY, JRReportSaxParserFactory.class.getName());
+
+        final String jasperPath = this.confPath + jasperFile;
+        final JasperDesign design = JRXmlLoader.load(jasperPath);
+
+        final JasperDesigner designer = new JasperDesigner(design, source);
+        this.designs.add(designer);
+
+        return designer;
+    }
+
+    public void exportPDF(final OutputStream out) throws JRException {
+
+        final List<JasperReport> compiledReports = new ArrayList<>();
+
+        final List<JRDataSource> sourcesWithPages = new ArrayList<>();
+
+        final List<JasperPrint> jasperPrintList = new ArrayList<>();
+
+        if (this.designs.size() == 1) {
+            final JasperDesigner designer = this.designs.get(0);
+            final JasperDesign jDesign = designer.getDesign();
+
+            final JasperReport compiled = JasperCompileManager.compileReport(jDesign);
+            compiledReports.add(compiled);
+            final MetaAndTableJRDataSource source = designer.getSource();
+            final JasperPrint print = JasperFillManager.fillReport(compiled, this.parameters, source);
+            jasperPrintList.add(print);
+        } else {
+            Integer totalpages = 0;
+
+            // erstes Rendern, um Seitenzahl zu ermitteln
+            for (final JasperDesigner designer : this.designs) {
+
+                final JasperReport compiled = JasperCompileManager.compileReport(designer.getDesign());
+                compiledReports.add(compiled);
+                final MetaAndTableJRDataSource source = designer.getSource();
+                final JasperPrint print = JasperFillManager.fillReport(compiled, this.parameters, source);
+
+                final Integer pagesCount = print.getPages().size();
+                designer.setPagesCount(totalpages);
+
+                totalpages += pagesCount;
+            }
+
+            // Sources mit pages machen
+            for (final JasperDesigner designer : this.designs) {
+                final JRDataSource sourceWithPages = designer.getSource().withPagePageOffsets(designer.getPagesCount(), totalpages);
+                sourcesWithPages.add(sourceWithPages);
+            }
+
+            for (int i = 0; i < compiledReports.size(); i++) {
+                final JasperReport compiledReport = compiledReports.get(i);
+                final JRDataSource source = sourcesWithPages.get(i);
+                final JasperPrint print = JasperFillManager.fillReport(compiledReport, this.parameters, source);
+                jasperPrintList.add(print);
+            }
+        }
+        doExport(jasperPrintList, out);
+    }
+
+    private void doExport(final List<JasperPrint> jasperPrintList, final OutputStream out) throws JRException {
+        final JRPdfExporter exporter = new JRPdfExporter();
+        exporter.setParameter(JRExporterParameter.JASPER_PRINT_LIST, jasperPrintList);
+        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
+        // this will make a bookmark in the exported PDF for each of the reports
+        exporter.setParameter(JRPdfExporterParameter.IS_CREATING_BATCH_MODE_BOOKMARKS, Boolean.TRUE);
+
+        exporter.exportReport();
+
+    }
+
+}
\ 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/common/MetaAndTableJRDataSource.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,74 @@
+/* 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.common;
+
+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 final List<String[]> data = new ArrayList<>();
+
+    private final Map<String, Object> metaData = new HashMap<>();
+
+    private int index = -1;
+
+    public void addData(final String[] row) {
+        this.data.add(row);
+    }
+
+    public void addMetaData(final String key, final Object value) {
+        this.metaData.put(key, value);
+    }
+
+    @Override
+    public boolean next() throws JRException {
+        this.index++;
+
+        return this.index < this.data.size();
+    }
+
+    @Override
+    public Object getFieldValue(final JRField field) throws JRException {
+        final String fieldName = field.getName();
+
+        if (fieldName.startsWith("meta:"))
+            return this.metaData.get(fieldName.substring("meta:".length()));
+
+        if (fieldName.startsWith("data:")) {
+            final int column = Integer.valueOf(fieldName.substring("data:".length()));
+            if (column >= this.data.get(this.index).length)
+                return null;
+            return this.data.get(this.index)[column];
+        }
+        return null;
+    }
+
+    public JRDataSource withPagePageOffsets(final Integer startpageoffset, final Integer totalpages) {
+
+        final MetaAndTableJRDataSource newSource = new MetaAndTableJRDataSource();
+        newSource.data.addAll(this.data);
+        newSource.metaData.putAll(this.metaData);
+
+        newSource.addMetaData("startpageoffset", startpageoffset);
+        newSource.addMetaData("totalpages", totalpages);
+
+        return newSource;
+    }
+}
\ 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/common/ResultRow.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,62 @@
+/** 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.common;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.dive4elements.artifacts.CallContext;
+
+/**
+ * Generic container for results that come in rows.
+ *
+ * @author Gernot Belger
+ */
+public class ResultRow implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private final Map<IResultType, Object> values = new HashMap<>();
+
+    public static ResultRow create() {
+        return new ResultRow();
+    }
+
+    public static ResultRow create(final ResultRow src) {
+        final ResultRow dst = create();
+        dst.values.putAll(src.values);
+        return dst;
+    }
+
+    protected ResultRow() {
+    }
+
+    public ResultRow putValue(final IResultType type, final Object value) {
+
+        this.values.put(type, value);
+
+        /* chain me */
+        return this;
+    }
+
+    public String exportValue(final CallContext context, final IResultType type) {
+        final Object value = this.values.get(type);
+        return type.exportValue(context, value);
+    }
+
+    public double getDoubleValue(final IResultType type) {
+        final Object value = this.values.get(type);
+        return type.asDouble(value);
+    }
+
+    public Object getValue(final IResultType type) {
+        return this.values.get(type);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/context/RiverContextFactory.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/context/RiverContextFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -617,30 +617,34 @@
         NodeList modulenodes = (NodeList) XMLUtils.xpath(
             cfg, XPATH_MODULES, XPathConstants.NODESET);
 
-        int num = modulenodes != null ? modulenodes.getLength() : 0;
-        ArrayList<Module> modules = new ArrayList<Module>(num);
+        final int num = modulenodes != null ? modulenodes.getLength() : 0;
+
+        final List<Module> modules = new ArrayList<>(num);
 
         for (int i = 0; i < num; i++) {
-            Element e = (Element) modulenodes.item(i);
-            String modulename = e.getAttribute("name");
-            String attrselected = e.getAttribute("selected");
-            boolean selected = attrselected == null ? false :
-                attrselected.equalsIgnoreCase("true");
+            final Element e = (Element) modulenodes.item(i);
+            final String modulename = e.getAttribute("name");
+            final String attrselected = e.getAttribute("selected");
+            final boolean selected = Boolean.parseBoolean(attrselected);
+            final String group = e.getAttribute("group");
+            
             log.debug("Loaded module " + modulename);
-            NodeList children = e.getChildNodes();
-            List<String> rivers = new ArrayList<String>(children.getLength());
+            
+            final NodeList children = e.getChildNodes();
+            final List<String> rivers = new ArrayList<>(children.getLength());
             for (int j = 0; j < children.getLength(); j++) {
                 if (children.item(j).getNodeType() != Node.ELEMENT_NODE) {
                     continue;
                 }
-                Element ce = (Element)children.item(j);
+                
+                final Element ce = (Element)children.item(j);
                 if (ce.hasAttribute("uuid")) {
                     rivers.add(ce.getAttribute("uuid"));
                 }
                 else if (ce.hasAttribute("name")) {
-                    List<River> allRivers = RiverFactory.getRivers();
-                    String name = ce.getAttribute("name");
-                    for (River r: allRivers) {
+                    final List<River> allRivers = RiverFactory.getRivers();
+                    final String name = ce.getAttribute("name");
+                    for (final River r: allRivers) {
                         if (name.equals(r.getName())) {
                             rivers.add(r.getModelUuid());
                             break;
@@ -648,7 +652,7 @@
                     }
                 }
             }
-            modules.add(new Module(modulename, selected, rivers));
+            modules.add(new Module(modulename, selected, group, rivers));
         }
         context.put(RiverContext.MODULES, modules);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java	Fri Jul 13 11:56:22 2018 +0200
@@ -31,7 +31,7 @@
 import org.hibernate.SessionFactory;
 
 import org.hibernate.jdbc.Work;
-
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.common.utils.Config;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.artifacts.common.utils.StringUtils;
@@ -175,13 +175,15 @@
     /**
      * Append recommendations to \param result.
      * @param extraParameters parameters (typical example: 'recommended')
+     * @param context 
      */
     public void  recommend(
         D4EArtifact         artifact,
         String              userId,
         String []           outs,
         Map<String, Object> extraParameters,
-        Node                result
+        Node                result, 
+        final CallContext   context
     ) {
         Map<String, Object> parameters = new HashMap<String, Object>();
 
@@ -201,27 +203,19 @@
 
         parameters.put("PARAMETERS", parameters);
 
-        recommend(parameters, userId, result);
+        recommend(parameters, userId, result, context);
     }
 
 
     /**
      * Append recommendations to \param result.
+     * @param context 
      */
-    public void recommend(
-        Map<String, Object> parameters,
-        String              userId,
-        Node                result
-    ) {
-        recommend(parameters, userId, result, SessionHolder.HOLDER.get());
+    public void recommend( final Map<String, Object> parameters, final String userId, final Node result, final CallContext context ) {
+        recommend(parameters, userId, result, SessionHolder.HOLDER.get(), context);
     }
 
-    public void recommend(
-        final Map<String, Object> parameters,
-        final String              userId,
-        final Node                result,
-        Session                   systemSession
-    ) {
+    public void recommend( final Map<String, Object> parameters, final String userId, final Node result, final Session systemSession, final CallContext context ) {
         systemSession.doWork(new Work() {
             @Override
             public void execute(final Connection systemConnection)
@@ -237,10 +231,7 @@
                         public void execute(Connection sedDBConnection)
                         throws SQLException
                         {
-                            recommend(
-                                parameters, userId, result,
-                                systemConnection,
-                                sedDBConnection);
+                            recommend( parameters, userId, result, systemConnection, sedDBConnection, context);
                         }
                     });
                 }
@@ -252,11 +243,12 @@
     }
 
     public void recommend(
-        Map<String, Object> parameters,
-        String              userId,
-        Node                result,
-        Connection          systemConnection,
-        Connection          seddbConnection
+        final Map<String, Object> parameters,
+        final String              userId,
+        final Node                result,
+        final Connection          systemConnection,
+        final Connection          seddbConnection, 
+        final CallContext         context
     ) throws SQLException
     {
         List<Builder.NamedConnection> connections =
@@ -285,7 +277,7 @@
                     CONNECTION_USER, userConnection, false));
             }
 
-            getBuilderPool().build(connections, result, parameters);
+            getBuilderPool().build(connections, result, parameters, context);
         }
         finally {
             if (userConnection != null) {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/App.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/App.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,60 +8,79 @@
 
 package org.dive4elements.river.artifacts.datacage.templating;
 
-import java.util.Map;
-import java.util.HashMap;
-
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-
-import org.dive4elements.river.backend.SessionFactoryProvider;
-
-import org.hibernate.Session;
-
-import org.w3c.dom.Document;
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.log4j.Logger;
-
+import org.apache.log4j.PropertyConfigurator;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.Config;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.datacage.Recommendations;
+import org.dive4elements.river.backend.SessionFactoryProvider;
+import org.hibernate.Session;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+import org.w3c.dom.Document;
 
-import org.dive4elements.river.artifacts.datacage.Recommendations;
-
-public class App
-{
+public class App {
     private static Logger log = Logger.getLogger(App.class);
 
-    public static final String template =
-        System.getProperty("meta.data.template", "meta-data.xml");
+    /**
+     * The logging is done via Log4j. To configure the logging
+     * a file 'log4j.properties' is search in the configuration directory.
+     */
+    private static final String LOG4J_PROPERTIES = "log4j.properties";
 
-    public static final String userId =
-        System.getProperty("user.id");
+    public static final String template = System.getProperty("meta.data.template", "meta-data.xml");
 
-    public static final String PARAMETERS =
-        System.getProperty("meta.data.parameters", "");
+    public static final String userId = System.getProperty("user.id");
 
-    public static final String OUTPUT =
-        System.getProperty("meta.data.output");
+    public static final String PARAMETERS = System.getProperty("meta.data.parameters", "");
+
+    public static final String OUTPUT = System.getProperty("meta.data.output");
 
     public static Map<String, Object> getParameters() {
-        HashMap<String, Object> map = new HashMap<String, Object>();
-        String [] parts = PARAMETERS.split("\\s*;\\s*");
-        for (String part: parts) {
-            String [] kv = part.split("\\s*:\\s*");
+        final HashMap<String, Object> map = new HashMap<>();
+        final String[] parts = PARAMETERS.split("\\s*;\\s*");
+        for (final String part : parts) {
+            final String[] kv = part.split("\\s*:\\s*");
             if (kv.length < 2 || (kv[0] = kv[0].trim()).length() == 0) {
                 continue;
             }
-            String [] values = kv[1].split("\\s*,\\s*");
+            final String[] values = kv[1].split("\\s*,\\s*");
             map.put(kv[0], values.length == 1 ? values[0] : values);
         }
         return map;
     }
 
-    public static void main(String [] args) {
+    /**
+     * Trys to load the Log4j configuration from ${config.dir}/log4j.properties.
+     */
+    private static final void configureLogging() {
+        final File configDir = Config.getConfigDirectory();
+        final File propFile = new File(configDir, LOG4J_PROPERTIES);
 
-        Recommendations rec = Recommendations.createRecommendations(
-            new File(template));
+        if (propFile.isFile() && propFile.canRead()) {
+            try {
+                PropertyConfigurator.configure(propFile.toURI().toURL());
+                SLF4JBridgeHandler.install();
+            }
+            catch (final MalformedURLException mue) {
+                mue.printStackTrace(System.err);
+            }
+        }
+    }
+
+    public static void main(final String[] args) {
+
+        configureLogging();
+
+        final Recommendations rec = Recommendations.createRecommendations(new File(template));
 
         if (rec == null) {
             System.err.println("No recommendations created");
@@ -71,15 +90,17 @@
         final Document result = XMLUtils.newDocument();
 
         final Map<String, Object> parameters = getParameters();
+        // REMARK/TODO: 'ARTIFACT-OUTS' needs a String-Array, should be handled by parser
+        parameters.put("ARTIFACT-OUTS", new String[] { "LONGITUDINAL_SECTION" });
+        parameters.put("PARAMETERS", parameters);
+        parameters.put("USER-ID", userId);
 
-        Session session = SessionFactoryProvider
-            .createSessionFactory()
-            .openSession();
+        final Session session = SessionFactoryProvider.createSessionFactory().openSession();
 
         try {
-            rec.recommend(parameters, userId, result, session);
-        }
-        finally {
+            final CallContext context = null;
+            rec.recommend(parameters, userId, result, session, context);
+        } finally {
             session.close();
         }
 
@@ -87,26 +108,29 @@
 
         if (OUTPUT == null) {
             out = System.out;
-        }
-        else {
+        } else {
             try {
                 out = new FileOutputStream(OUTPUT);
             }
-            catch (IOException ioe) {
+            catch (final IOException ioe) {
                 log.error(ioe);
                 return;
             }
         }
 
         try {
+            out.write('\n');
             XMLUtils.toStream(result, out);
+            out.write('\n');
         }
-        finally {
+        catch (final IOException e) {
+            log.error(e);
+        } finally {
             if (OUTPUT != null) {
                 try {
                     out.close();
                 }
-                catch (IOException ioe) {
+                catch (final IOException ioe) {
                     log.error(ioe);
                 }
             }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,6 +8,7 @@
 
 package org.dive4elements.river.artifacts.datacage.templating;
 
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 
 import org.dive4elements.river.utils.Pair;
@@ -138,31 +139,34 @@
         protected Deque<Object>                            groupExprStack;
         protected FunctionResolver                         functionResolver;
         protected Map<String, XPathExpression>             expressions;
+        private final CallContext context;
 
 
-        public BuildHelper(
-            Node                  output,
-            List<NamedConnection> connections,
-            Map<String, Object>   parameters
-        ) {
+        public BuildHelper( final Node output, final List<NamedConnection> connections, final Map<String, Object> parameters, CallContext context ) {
             if (connections.isEmpty()) {
                 throw new IllegalArgumentException("no connections given.");
             }
 
-            this.connections = connections;
-            connectionsStack =
-                new ArrayDeque<Pair<NamedConnection, ResultData>>();
-            this.output      = output;
+            connectionsStack = new ArrayDeque<Pair<NamedConnection, ResultData>>();
             frames           = new StackFrames(parameters);
             owner            = getOwnerDocument(output);
             macroBodies      = new ArrayDeque<NodeList>();
             groupExprStack   = new ArrayDeque<Object>();
-            functionResolver = new FunctionResolver(this);
             expressions      = new HashMap<String, XPathExpression>();
-            statements       =
-                new HashMap<String, CompiledStatement.Instance>();
+            statements       = new HashMap<String, CompiledStatement.Instance>();
+
+            this.connections = connections;
+            this.output      = output;
+            this.context = context;
+
+            // Important call this at the end of constructor, it might call back
+            functionResolver = new FunctionResolver(this);
         }
-
+        
+        public final CallContext getContext() {
+            return this.context;
+        }
+        
         public void build() throws SQLException {
             try {
                 // XXX: Thread safety is now established by the builder pool.
@@ -437,7 +441,7 @@
                 x = getXPathExpression(filter);
             }
             catch (XPathExpressionException xee) {
-                log.warn("Invalid filter expression '" + filter + "'.");
+                log.warn("Invalid filter expression '" + filter + "'.", xee);
                 return rd;
             }
 
@@ -1346,6 +1350,7 @@
     }
 
     /** Handle <dc:statement> elements. */
+    // FIXME: this prohibits using local variables inside of statements!
     protected void compileStatements() {
 
         NodeList nodes = template.getElementsByTagNameNS(
@@ -1406,17 +1411,11 @@
         return document != null ? document : (Document)node;
     }
 
-    public void build(
-        List<NamedConnection> connections,
-        Node                  output,
-        Map<String, Object>   parameters
-    )
-    throws SQLException
+    public void build( final List<NamedConnection> connections, final Node output, final Map<String, Object> parameters, final CallContext context ) throws SQLException
     {
         long startTime = System.currentTimeMillis();
         try {
-            BuildHelper helper =
-                new BuildHelper(output, connections, parameters);
+            BuildHelper helper = new BuildHelper(output, connections, parameters, context);
             helper.build();
         }
         finally {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/BuilderPool.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/BuilderPool.java	Fri Jul 13 11:56:22 2018 +0200
@@ -20,7 +20,7 @@
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.artifacts.CallContext;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 
@@ -78,12 +78,7 @@
         return document;
     }
 
-    public void build(
-        List<Builder.NamedConnection> connections,
-        Node                          output,
-        Map<String, Object>           parameters
-    )
-    throws SQLException
+    public void build( final List<Builder.NamedConnection> connections, final Node output, final Map<String, Object> parameters, final CallContext context ) throws SQLException
     {
         Builder builder;
         synchronized (pool) {
@@ -93,12 +88,12 @@
                 }
             }
             catch (InterruptedException ie) {
-                log.debug("Waiting for builder interrupted. Build canceled.");
+                log.debug("Waiting for builder interrupted. Build canceled.", ie);
                 return;
             }
         }
         try {
-            builder.build(connections, output, parameters);
+            builder.build(connections, output, parameters, context);
         }
         finally {
             synchronized (pool) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FixAnalysisYearXPathFunction.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.datacage.templating;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.xml.xpath.XPathFunction;
+import javax.xml.xpath.XPathFunctionException;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.FixationArtifact;
+import org.dive4elements.river.artifacts.access.FixRealizingAccess;
+import org.dive4elements.river.artifacts.model.fixings.FixRealizingCalculationExtended;
+import org.dive4elements.river.utils.RiverUtils;
+
+/**
+ * Very specialized function the resolves the 'year' (als middle of all used events) from a fix-analysis-vollmer
+ * artifact).
+ *
+ * @author Gernot Belger
+ */
+public class FixAnalysisYearXPathFunction implements XPathFunction {
+
+    public static final String ID = "fix_analysis_year";
+
+    public static final int ARITY = 1;
+
+    private final CallContext context;
+
+    public FixAnalysisYearXPathFunction(final CallContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public Object evaluate(final List args) throws XPathFunctionException {
+
+        final UUID uuid = (UUID) args.get(0);
+        if (uuid == null)
+            return null;
+
+        final D4EArtifact artifact = RiverUtils.getArtifact(uuid.toString(), this.context);
+        if (!(artifact instanceof FixationArtifact))
+            return null;
+
+        final FixationArtifact fixation = (FixationArtifact) artifact;
+
+        // Get W/Q input per gauge for this case.
+        final FixRealizingAccess fixAccess = new FixRealizingAccess(fixation);
+
+        /* ugly but necessary to keep this logic at least a bit inside the FixRealizing stuff */
+        final FixRealizingCalculationExtended calculation = new FixRealizingCalculationExtended(fixAccess);
+        return calculation.determineMeanYear();
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java	Fri Jul 13 11:56:22 2018 +0200
@@ -221,6 +221,14 @@
             }
         });
 
+        addFunction("column", 1, new XPathFunction() {
+            @Override
+            public Object evaluate(List args) throws XPathFunctionException {
+                return column(args.get(0));
+            }
+        });
+
+        addFunction(FixAnalysisYearXPathFunction.ID, FixAnalysisYearXPathFunction.ARITY, new FixAnalysisYearXPathFunction(buildHelper.getContext()));
     }
 
     /**
@@ -578,5 +586,17 @@
         }
         return StackFrames.NULL;
     }
+
+    private Object column(Object argument) {
+        
+        if( !(argument instanceof String) )
+            throw new IllegalArgumentException("Argument of 'column' function must be a string");
+        
+        String columnName = (String) argument;
+
+        StackFrames frms = buildHelper.frames;
+        
+        return frms.getNull(columnName);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/CollisionHibernateFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,57 @@
+/** 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.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class CollisionHibernateFactory {
+
+    public static List<Collision> getCollisionsByRiver(final River river) {
+        final String queryStr = "FROM Collision WHERE river_id = :river_id";
+
+        final List<Collision> list = new ArrayList<>();
+
+        final Session session = SessionHolder.HOLDER.get();
+        try {
+            final Transaction transaction = session.beginTransaction();
+
+            final Query query = session.createQuery(queryStr);
+            query.setParameter("river_id", river.getId());
+
+            final List<Collision> collisions = query.list();
+            final Iterator<Collision> iterator = collisions.iterator();
+            while (iterator.hasNext()) {
+                final Collision coll = iterator.next();
+                // final CollisionHibernateFactory factory = new CollisionHibernateFactory(coll.getId(), coll.getYear());
+                list.add(coll);
+            }
+            transaction.commit(); // komisch, dass die Iteration davor im Code steht...
+        }
+        catch (final HibernateException e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
+
+}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DataFacet.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DataFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -104,12 +104,14 @@
      */
     @Override
     public Facet deepCopy() {
+    	// FIXME: why not use the full constructor instead? would also fix the next problem
         DataFacet copy = new DataFacet();
+        // FIXME: usage of internal knowledge of parent class...
+        // Either the set method should be correctly overwritten, or implement a correct copy-constructor!
         copy.set(this);
         copy.type    = type;
         copy.hash    = hash;
         copy.stateId = stateId;
         return copy;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DateRange.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DateRange.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,49 +11,54 @@
 import java.io.Serializable;
 import java.util.Date;
 
-public class DateRange
-implements   Serializable
-{
+import org.dive4elements.artifacts.common.utils.DateUtils;
+
+public class DateRange implements Serializable {
     private static final long serialVersionUID = -2553914795388094818L;
 
-    protected Date from;
-    protected Date to;
+    private final Date from;
+    private final Date to;
 
-    public DateRange(Date from, Date to) {
+    public DateRange(final Date from, final Date to) {
         this.from = from;
-        this.to   = to;
+        this.to = to;
     }
 
     public Date getFrom() {
-        return from;
-    }
-
-    public void setFrom(Date from) {
-        this.from = from;
+        return this.from;
     }
 
     public Date getTo() {
-        return to;
+        return this.to;
     }
 
-    public void setTo(Date to) {
-        this.to = to;
-    }
+    private static final boolean equalDates(final Date a, final Date b) {
+        if (a == null && b != null)
+            return false;
 
-    private static final boolean equalDates(Date a, Date b) {
-        if (a == null && b != null) return false;
-        if (a != null && b == null) return false;
-        if (a == null) return true;
+        if (a != null && b == null)
+            return false;
+
+        if (a == null)
+            return true;
+
         return a.equals(b);
     }
 
     @Override
-    public boolean equals(Object other) {
-        if (!(other instanceof DateRange)) {
+    public boolean equals(final Object other) {
+        if (!(other instanceof DateRange))
             return false;
-        }
-        DateRange o = (DateRange)other;
-        return equalDates(from, o.from) && equalDates(to, o.to);
+
+        final DateRange o = (DateRange) other;
+        return equalDates(this.from, o.from) && equalDates(this.to, o.to);
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+    public int getFromYear() {
+        return DateUtils.getYearFromDate(this.from);
+    }
+
+    public int getToYear() {
+        return DateUtils.getYearFromDate(this.to);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,188 +11,148 @@
 /** 'Types' of facets. */
 public interface FacetTypes {
 
-    /** Static helper class to determine if a Facet name is of a generalized
-     * 'type'. */
+    /**
+     * Static helper class to determine if a Facet name is of a generalized
+     * 'type'.
+     */
     public static class IS {
-        public static boolean WQ_KM(String type) {
-           return type.equals(DISCHARGE_LONGITUDINAL_W)
-               || type.equals(LONGITUDINAL_W);
-        }
-        public static boolean W_KM(String type) {
-            return type.equals(STATIC_WKMS)
-               || type.equals(HEIGHTMARKS_POINTS)
-               || WQ_KM(type);
-        }
-        public static boolean AREA(String type) {
-            return type.equals(AREA)
-                || type.equals(CROSS_SECTION_AREA)
-                || type.equals(LONGITUDINAL_SECTION_AREA);
+        public static boolean WQ_KM(final String type) {
+            return type.equals(DISCHARGE_LONGITUDINAL_W) || type.equals(LONGITUDINAL_W);
         }
-        public static boolean W(String type) {
-            return type.equals(LONGITUDINAL_W)
-                || type.equals(DISCHARGE_LONGITUDINAL_W)
-                || type.equals(DURATION_W)
-                || type.equals(STATIC_WKMS)
-                || type.equals(STATIC_WQKMS_W);
+
+        public static boolean W_KM(final String type) {
+            return type.equals(STATIC_WKMS) || type.equals(HEIGHTMARKS_POINTS) || WQ_KM(type);
         }
-        public static boolean Q(String type) {
-            return type.equals(LONGITUDINAL_Q)
-                || type.equals(DISCHARGE_LONGITUDINAL_Q)
-                || type.equals(DURATION_Q)
-                || type.equals(STATIC_WQKMS_Q);
+
+        public static boolean AREA(final String type) {
+            return type.equals(AREA) || type.equals(CROSS_SECTION_AREA) || type.equals(LONGITUDINAL_SECTION_AREA);
         }
-        public static boolean V(String type) {
-            return type.equals(FLOW_VELOCITY_MAINCHANNEL)
-                || type.equals(FLOW_VELOCITY_TOTALCHANNEL);
+
+        public static boolean W(final String type) {
+            return type.equals(LONGITUDINAL_W) || type.equals(DISCHARGE_LONGITUDINAL_W) || type.equals(DURATION_W) || type.equals(STATIC_WKMS)
+                    || type.equals(STATIC_WQKMS_W);
         }
-        public static boolean T(String type) {
+
+        public static boolean Q(final String type) {
+            return type.equals(LONGITUDINAL_Q) || type.equals(DISCHARGE_LONGITUDINAL_Q) || type.equals(DURATION_Q) || type.equals(STATIC_WQKMS_Q);
+        }
+
+        public static boolean V(final String type) {
+            return type.equals(FLOW_VELOCITY_MAINCHANNEL) || type.equals(FLOW_VELOCITY_TOTALCHANNEL);
+        }
+
+        public static boolean T(final String type) {
             return type.equals(FLOW_VELOCITY_TAU);
         }
-        public static boolean H(String type) {
+
+        public static boolean H(final String type) {
             return type.equals(MIDDLE_BED_HEIGHT_SINGLE);
         }
-        public static boolean MANUALPOINTS(String type) {
+
+        public static boolean MANUALPOINTS(final String type) {
             return type.endsWith("manualpoints");
         }
-        public static boolean MANUALLINE(String type) {
+
+        public static boolean MANUALLINE(final String type) {
             return type.endsWith("manualline");
         }
-        public static boolean FILTERED(String type) {
+
+        public static boolean FILTERED(final String type) {
             return type.endsWith("filtered");
         }
-        public static boolean SQ_CURVE(String type) {
-            if (type.equals(SQ_A_CURVE)
-                || type.equals(SQ_B_CURVE)
-                || type.equals(SQ_C_CURVE)
-                || type.equals(SQ_D_CURVE)
-                || type.equals(SQ_E_CURVE)
-                || type.equals(SQ_F_CURVE)
-                || type.equals(SQ_G_CURVE)
-                || type.equals(SQ_A_OUTLIER_CURVE)
-                || type.equals(SQ_B_OUTLIER_CURVE)
-                || type.equals(SQ_C_OUTLIER_CURVE)
-                || type.equals(SQ_D_OUTLIER_CURVE)
-                || type.equals(SQ_E_OUTLIER_CURVE)
-                || type.equals(SQ_F_OUTLIER_CURVE)
-                || type.equals(SQ_G_OUTLIER_CURVE)
-                || type.equals(SQ_A_CURVE_OV)
-                || type.equals(SQ_B_CURVE_OV)
-                || type.equals(SQ_C_CURVE_OV)
-                || type.equals(SQ_D_CURVE_OV)
-                || type.equals(SQ_E_CURVE_OV)
-                || type.equals(SQ_F_CURVE_OV)
-                || type.equals(SQ_G_CURVE_OV)
-                || type.equals(SQ_A_OUTLIER_CURVE_OV)
-                || type.equals(SQ_B_OUTLIER_CURVE_OV)
-                || type.equals(SQ_C_OUTLIER_CURVE_OV)
-                || type.equals(SQ_D_OUTLIER_CURVE_OV)
-                || type.equals(SQ_E_OUTLIER_CURVE_OV)
-                || type.equals(SQ_F_OUTLIER_CURVE_OV)
-                || type.equals(SQ_G_OUTLIER_CURVE_OV)
-                )
-            {
+
+        public static boolean SQ_CURVE(final String type) {
+            if (type.equals(SQ_A_CURVE) || type.equals(SQ_B_CURVE) || type.equals(SQ_C_CURVE) || type.equals(SQ_D_CURVE) || type.equals(SQ_E_CURVE)
+                    || type.equals(SQ_F_CURVE) || type.equals(SQ_G_CURVE) || type.equals(SQ_A_OUTLIER_CURVE) || type.equals(SQ_B_OUTLIER_CURVE)
+                    || type.equals(SQ_C_OUTLIER_CURVE) || type.equals(SQ_D_OUTLIER_CURVE) || type.equals(SQ_E_OUTLIER_CURVE) || type.equals(SQ_F_OUTLIER_CURVE)
+                    || type.equals(SQ_G_OUTLIER_CURVE) || type.equals(SQ_A_CURVE_OV) || type.equals(SQ_B_CURVE_OV) || type.equals(SQ_C_CURVE_OV)
+                    || type.equals(SQ_D_CURVE_OV) || type.equals(SQ_E_CURVE_OV) || type.equals(SQ_F_CURVE_OV) || type.equals(SQ_G_CURVE_OV)
+                    || type.equals(SQ_A_OUTLIER_CURVE_OV) || type.equals(SQ_B_OUTLIER_CURVE_OV) || type.equals(SQ_C_OUTLIER_CURVE_OV)
+                    || type.equals(SQ_D_OUTLIER_CURVE_OV) || type.equals(SQ_E_OUTLIER_CURVE_OV) || type.equals(SQ_F_OUTLIER_CURVE_OV)
+                    || type.equals(SQ_G_OUTLIER_CURVE_OV)) {
                 return true;
             }
 
             return false;
         }
-        public static boolean SQ_MEASUREMENT(String type) {
-            if (type.equals(SQ_A_MEASUREMENT)
-                || type.equals(SQ_B_MEASUREMENT)
-                || type.equals(SQ_C_MEASUREMENT)
-                || type.equals(SQ_D_MEASUREMENT)
-                || type.equals(SQ_E_MEASUREMENT)
-                || type.equals(SQ_F_MEASUREMENT)
-                || type.equals(SQ_G_MEASUREMENT)
-                || type.equals(SQ_A_OUTLIER_MEASUREMENT)
-                || type.equals(SQ_B_OUTLIER_MEASUREMENT)
-                || type.equals(SQ_C_OUTLIER_MEASUREMENT)
-                || type.equals(SQ_D_OUTLIER_MEASUREMENT)
-                || type.equals(SQ_E_OUTLIER_MEASUREMENT)
-                || type.equals(SQ_F_OUTLIER_MEASUREMENT)
-                || type.equals(SQ_G_OUTLIER_MEASUREMENT)
-                || type.equals(SQ_A_MEASUREMENT_OV)
-                || type.equals(SQ_B_MEASUREMENT_OV)
-                || type.equals(SQ_C_MEASUREMENT_OV)
-                || type.equals(SQ_D_MEASUREMENT_OV)
-                || type.equals(SQ_E_MEASUREMENT_OV)
-                || type.equals(SQ_F_MEASUREMENT_OV)
-                || type.equals(SQ_G_MEASUREMENT_OV)
-                || type.equals(SQ_A_OUTLIER_MEASUREMENT_OV)
-                || type.equals(SQ_B_OUTLIER_MEASUREMENT_OV)
-                || type.equals(SQ_C_OUTLIER_MEASUREMENT_OV)
-                || type.equals(SQ_D_OUTLIER_MEASUREMENT_OV)
-                || type.equals(SQ_E_OUTLIER_MEASUREMENT_OV)
-                || type.equals(SQ_F_OUTLIER_MEASUREMENT_OV)
-                || type.equals(SQ_G_OUTLIER_MEASUREMENT_OV)
-                )
-            {
+
+        public static boolean SQ_MEASUREMENT(final String type) {
+            if (type.equals(SQ_A_MEASUREMENT) || type.equals(SQ_B_MEASUREMENT) || type.equals(SQ_C_MEASUREMENT) || type.equals(SQ_D_MEASUREMENT)
+                    || type.equals(SQ_E_MEASUREMENT) || type.equals(SQ_F_MEASUREMENT) || type.equals(SQ_G_MEASUREMENT) || type.equals(SQ_A_OUTLIER_MEASUREMENT)
+                    || type.equals(SQ_B_OUTLIER_MEASUREMENT) || type.equals(SQ_C_OUTLIER_MEASUREMENT) || type.equals(SQ_D_OUTLIER_MEASUREMENT)
+                    || type.equals(SQ_E_OUTLIER_MEASUREMENT) || type.equals(SQ_F_OUTLIER_MEASUREMENT) || type.equals(SQ_G_OUTLIER_MEASUREMENT)
+                    || type.equals(SQ_A_MEASUREMENT_OV) || type.equals(SQ_B_MEASUREMENT_OV) || type.equals(SQ_C_MEASUREMENT_OV)
+                    || type.equals(SQ_D_MEASUREMENT_OV) || type.equals(SQ_E_MEASUREMENT_OV) || type.equals(SQ_F_MEASUREMENT_OV)
+                    || type.equals(SQ_G_MEASUREMENT_OV) || type.equals(SQ_A_OUTLIER_MEASUREMENT_OV) || type.equals(SQ_B_OUTLIER_MEASUREMENT_OV)
+                    || type.equals(SQ_C_OUTLIER_MEASUREMENT_OV) || type.equals(SQ_D_OUTLIER_MEASUREMENT_OV) || type.equals(SQ_E_OUTLIER_MEASUREMENT_OV)
+                    || type.equals(SQ_F_OUTLIER_MEASUREMENT_OV) || type.equals(SQ_G_OUTLIER_MEASUREMENT_OV)) {
                 return true;
             }
 
             return false;
         }
-        public static boolean SQ_OUTLIER(String type) {
-            if (type.equals(SQ_A_OUTLIER)
-                || type.equals(SQ_B_OUTLIER)
-                || type.equals(SQ_C_OUTLIER)
-                || type.equals(SQ_D_OUTLIER)
-                || type.equals(SQ_E_OUTLIER)
-                || type.equals(SQ_F_OUTLIER)
-                || type.equals(SQ_G_OUTLIER)
-                || type.equals(SQ_A_OUTLIER_OV)
-                || type.equals(SQ_B_OUTLIER_OV)
-                || type.equals(SQ_C_OUTLIER_OV)
-                || type.equals(SQ_D_OUTLIER_OV)
-                || type.equals(SQ_E_OUTLIER_OV)
-                || type.equals(SQ_F_OUTLIER_OV)
-                || type.equals(SQ_G_OUTLIER_OV))
-            {
+
+        public static boolean SQ_OUTLIER(final String type) {
+            if (type.equals(SQ_A_OUTLIER) || type.equals(SQ_B_OUTLIER) || type.equals(SQ_C_OUTLIER) || type.equals(SQ_D_OUTLIER) || type.equals(SQ_E_OUTLIER)
+                    || type.equals(SQ_F_OUTLIER) || type.equals(SQ_G_OUTLIER) || type.equals(SQ_A_OUTLIER_OV) || type.equals(SQ_B_OUTLIER_OV)
+                    || type.equals(SQ_C_OUTLIER_OV) || type.equals(SQ_D_OUTLIER_OV) || type.equals(SQ_E_OUTLIER_OV) || type.equals(SQ_F_OUTLIER_OV)
+                    || type.equals(SQ_G_OUTLIER_OV)) {
                 return true;
             }
 
             return false;
         }
-    };
+    }
 
-    /** Available diagram/chart-types.  This enum is evaluated at certain
+    /**
+     * Available diagram/chart-types. This enum is evaluated at certain
      * places to iterate over chart-types to e.g. dynamically generate
-     * Facet-names (ManualPoints for example). */
+     * Facet-names (ManualPoints for example).
+     */
     public enum ChartType {
-        FD("fix_derivate_curve"),
-        LS("longitudinal_section"),
-        CS("cross_section"),
-        DLS("discharge_longitudinal_section"),
-        CDC("computed_discharge_curve"),
-        DUC("duration_curve"),
-        DIC("discharge_curve"),
-        RC("reference_curve"),
-        RCN("reference_curve_normalized"),
-        WD("wdifferences"),
-        BHDY("bedheight_difference_height_year"),
-        BDY("bed_difference_year"),
-        FWQC("fix_wq_curve"),
-        FDWC("fix_deltawt_curve"),
-        FLSC("fix_longitudinal_section_curve"),
-        FDC("fix_derivate_curve"),
-        EWQ("extreme_wq_curve"),
-        BHM("bedheight_middle"),
-        BLS("bed_longitudinal_section"),
-        SLS("sedimentload_ls"),
-        FV("flow_velocity"),
-        SQA("sq_relation_a"),
-        SQB("sq_relation_b"),
-        W_D("w_differences"),
-        SQC("sq_relation_c"),
-        SQD("sq_relation_d"),
-        SQE("sq_relation_e"),
-        SQF("sq_relation_f"),
-        HD("historical_discharge"),
-        HDWQ("historical_discharge_wq");
+        FD("fix_derivate_curve"), //
+        LS("longitudinal_section"), //
+        CS("cross_section"), //
+        DLS("discharge_longitudinal_section"), //
+        CDC("computed_discharge_curve"), //
+        DUC("duration_curve"), //
+        DIC("discharge_curve"), //
+        RC("reference_curve"), //
+        RCN("reference_curve_normalized"), //
+        WD("wdifferences"), //
+        BHDY("bedheight_difference_height_year"), //
+        BDY("bed_difference_year"), //
+        FWQC("fix_wq_curve"), //
+        FDWC("fix_deltawt_curve"), //
+        FLSC("fix_longitudinal_section_curve"), //
+        FDC("fix_derivate_curve"), //
+        EWQ("extreme_wq_curve"), //
+        BHM("bedheight_middle"), //
+        BLS("bed_longitudinal_section"), //
+        SLS("sedimentload_ls"), //
+        FV("flow_velocity"), //
+        SQA("sq_relation_a"), //
+        SQB("sq_relation_b"), //
+        W_D("w_differences"), //
+        SQC("sq_relation_c"), //
+        SQD("sq_relation_d"), //
+        SQE("sq_relation_e"), //
+        SQF("sq_relation_f"), //
+        HD("historical_discharge"), //
+        HDWQ("historical_discharge_wq"), //
+        SFD("sinfo_flow_depth"), //
+        SFDMM("sinfo_flow_depth_minmax"), //
+        SFDD("sinfo_flow_depth_development"), //
+        SFDDPY("sinfo_flow_depth_development_peryear"), //
+        SC("sinfo_collision"), //
+        SFDUR("sinfo_flood_duration"), //
+        STKH("sinfo_tkk"), //
+        SFW("sinfo_flood_height"), //
+        SFDC("sinfo_floodduration_curve");
 
-        private String chartTypeString;
+        private final String chartTypeString;
 
-        ChartType(String description) {
+        ChartType(final String description) {
             this.chartTypeString = description;
         }
 
@@ -202,44 +162,43 @@
         }
     }
 
-    String AREA                        = "area";
-    String CROSS_SECTION_AREA          = "cross_section.area";
-    String LONGITUDINAL_SECTION_AREA   = "longitudinal_section.area";
+    String AREA = "area";
+    String CROSS_SECTION_AREA = "cross_section.area";
+    String LONGITUDINAL_SECTION_AREA = "longitudinal_section.area";
 
-    String FLOODMAP_WSPLGEN            = "floodmap.wsplgen";
-    String FLOODMAP_BARRIERS           = "floodmap.barriers";
-    String FLOODMAP_USERSHAPE          = "floodmap.usershape";
-    String FLOODMAP_RIVERAXIS          = "floodmap.riveraxis";
+    String FLOODMAP_WSPLGEN = "floodmap.wsplgen";
+    String FLOODMAP_BARRIERS = "floodmap.barriers";
+    String FLOODMAP_USERSHAPE = "floodmap.usershape";
+    String FLOODMAP_RIVERAXIS = "floodmap.riveraxis";
     @Deprecated
-    String FLOODMAP_WMSBACKGROUND      = "floodmap.wmsbackground";
-    String FLOODMAP_KMS                = "floodmap.kms";
-    String FLOODMAP_QPS                = "floodmap.qps";
-    String FLOODMAP_HWS_LINES          = "floodmap.hws_lines";
-    String FLOODMAP_HWS_POINTS         = "floodmap.hws_points";
-    String FLOODMAP_HYDR_BOUNDARY      = "floodmap.hydr_boundaries";
+    String FLOODMAP_WMSBACKGROUND = "floodmap.wmsbackground";
+    String FLOODMAP_KMS = "floodmap.kms";
+    String FLOODMAP_QPS = "floodmap.qps";
+    String FLOODMAP_HWS_LINES = "floodmap.hws_lines";
+    String FLOODMAP_HWS_POINTS = "floodmap.hws_points";
+    String FLOODMAP_HYDR_BOUNDARY = "floodmap.hydr_boundaries";
     String FLOODMAP_HYDR_BOUNDARY_POLY = "floodmap.hydr_boundaries_poly";
-    String FLOODMAP_CATCHMENT          = "floodmap.catchment";
-    String FLOODMAP_FLOODPLAIN         = "floodmap.floodplain";
-    String FLOODMAP_LINES              = "floodmap.lines";
-    String FLOODMAP_BUILDINGS          = "floodmap.buildings";
-    String FLOODMAP_FIXPOINTS          = "floodmap.fixpoints";
-    String FLOODMAP_FLOODMARKS         = "floodmap.floodmarks";
-    String FLOODMAP_FLOODMAPS          = "floodmap.floodmaps";
-    String FLOODMAP_GAUGE_LOCATION     = "floodmap.gauge_location";
-    String FLOODMAP_EXTERNAL_WMS       = "floodmap.externalwms";
-    String FLOODMAP_JETTIES            = "floodmap.jetties";
+    String FLOODMAP_CATCHMENT = "floodmap.catchment";
+    String FLOODMAP_FLOODPLAIN = "floodmap.floodplain";
+    String FLOODMAP_LINES = "floodmap.lines";
+    String FLOODMAP_BUILDINGS = "floodmap.buildings";
+    String FLOODMAP_FIXPOINTS = "floodmap.fixpoints";
+    String FLOODMAP_FLOODMARKS = "floodmap.floodmarks";
+    String FLOODMAP_FLOODMAPS = "floodmap.floodmaps";
+    String FLOODMAP_GAUGE_LOCATION = "floodmap.gauge_location";
+    String FLOODMAP_EXTERNAL_WMS = "floodmap.externalwms";
+    String FLOODMAP_EXTERNAL_WMS_INUNDATIONDUR = "floodmap.externalwms_";
+    String FLOODMAP_JETTIES = "floodmap.jetties";
 
     String DISCHARGE_LONGITUDINAL_W = "discharge_longitudinal_section.w";
     String DISCHARGE_LONGITUDINAL_Q = "discharge_longitudinal_section.q";
-    String DISCHARGE_LONGITUDINAL_Q_INFOLD =
-        "discharge_longitudinal_section.q.infolding";
-    String DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT =
-        "discharge_longitudinal_section.q.cutting";
+    String DISCHARGE_LONGITUDINAL_Q_INFOLD = "discharge_longitudinal_section.q.infolding";
+    String DISCHARGE_LONGITUDINAL_Q_INFOLD_CUT = "discharge_longitudinal_section.q.cutting";
     String DISCHARGE_LONGITUDINAL_C = "discharge_longitudinal_section.c";
 
     String LONGITUDINAL_W = "longitudinal_section.w";
     String LONGITUDINAL_Q = "longitudinal_section.q";
-    String LONGITUDINAL_ANNOTATION   = "longitudinal_section.annotations";
+    String LONGITUDINAL_ANNOTATION = "longitudinal_section.annotations";
     String LONGITUDINAL_MANUALPOINTS = "longitudinal_section.manualpoints";
 
     String W_DIFFERENCES = "w_differences";
@@ -265,17 +224,17 @@
     String MANUALPOINTS = "manualpoints";
     String MANUALLINE = "manualline";
 
-    String QSECTOR        = "qsectors";
+    String QSECTOR = "qsectors";
 
-    String STATIC_DELTA_W    = "other.delta_w";
-    String STATIC_DELTA_W_CMA= "other.delta_w_cma";
-    String STATIC_WQ         = "other.wq";
+    String STATIC_DELTA_W = "other.delta_w";
+    String STATIC_DELTA_W_CMA = "other.delta_w_cma";
+    String STATIC_WQ = "other.wq";
     String STATIC_WQ_ANNOTATIONS = "other.wq.annotations";
-    String STATIC_WKMS       = "other.wkms";
+    String STATIC_WKMS = "other.wkms";
     String STATIC_WKMS_MARKS = "other.wkms.marks";
-    String STATIC_WQKMS      = "other.wqkms";
-    String STATIC_WQKMS_W    = "other.wqkms.w";
-    String STATIC_WQKMS_Q    = "other.wqkms.q";
+    String STATIC_WQKMS = "other.wqkms";
+    String STATIC_WQKMS_W = "other.wqkms.w";
+    String STATIC_WQKMS_Q = "other.wqkms.q";
     String STATIC_WKMS_INTERPOL = "other.wkms.interpol";
     String STATIC_W_INTERPOL = "other.w.interpol";
 
@@ -283,74 +242,57 @@
 
     String CSV = "csv";
     String WST = "wst";
-    String AT  = "at";
+    String AT = "at";
     String PDF = "pdf";
 
     String REPORT = "report";
 
-    String HISTORICAL_DISCHARGE_Q      = "historical_discharge.historicalq";
-    String HISTORICAL_DISCHARGE_Q_DIFF =
-        "historical_discharge.historicalq.diff";
-    String HISTORICAL_DISCHARGE_W      = "historical_discharge.historicalw";
-    String HISTORICAL_DISCHARGE_W_DIFF =
-        "historical_discharge.historicalw.diff";
-    String HISTORICAL_DISCHARGE_WQ_Q   = "historical_discharge.wq.q";
-    String HISTORICAL_DISCHARGE_WQ_W   = "historical_discharge.wq.w";
+    String HISTORICAL_DISCHARGE_Q = "historical_discharge.historicalq";
+    String HISTORICAL_DISCHARGE_Q_DIFF = "historical_discharge.historicalq.diff";
+    String HISTORICAL_DISCHARGE_W = "historical_discharge.historicalw";
+    String HISTORICAL_DISCHARGE_W_DIFF = "historical_discharge.historicalw.diff";
+    String HISTORICAL_DISCHARGE_WQ_Q = "historical_discharge.wq.q";
+    String HISTORICAL_DISCHARGE_WQ_W = "historical_discharge.wq.w";
 
-    String REFERENCE_CURVE            = "reference_curve";
+    String REFERENCE_CURVE = "reference_curve";
     String REFERENCE_CURVE_NORMALIZED = "reference_curve_normalized";
 
-    String FLOW_VELOCITY_MAINCHANNEL           = "flow_velocity.mainchannel";
-    String FLOW_VELOCITY_TOTALCHANNEL          = "flow_velocity.totalchannel";
+    String FLOW_VELOCITY_MAINCHANNEL = "flow_velocity.mainchannel";
+    String FLOW_VELOCITY_TOTALCHANNEL = "flow_velocity.totalchannel";
     /** Also called SHEAR_STRESS. */
-    String FLOW_VELOCITY_TAU                   = "flow_velocity.tau";
-    String FLOW_VELOCITY_MAINCHANNEL_FILTERED  =
-        "flow_velocity.mainchannel.filtered";
-    String FLOW_VELOCITY_TOTALCHANNEL_FILTERED =
-        "flow_velocity.totalchannel.filtered";
-    String FLOW_VELOCITY_TAU_FILTERED          = "flow_velocity.tau.filtered";
-    String FLOW_VELOCITY_ANNOTATION            = "flow_velocity.annotation";
-    String FLOW_VELOCITY_MEASUREMENT           = "flow_velocity.measurement";
-    String FLOW_VELOCITY_DISCHARGE             = "flow_velocity.discharge";
-    String FLOW_VELOCITY_WATERLEVEL            = "flow_velocity.waterlevel";
+    String FLOW_VELOCITY_TAU = "flow_velocity.tau";
+    String FLOW_VELOCITY_MAINCHANNEL_FILTERED = "flow_velocity.mainchannel.filtered";
+    String FLOW_VELOCITY_TOTALCHANNEL_FILTERED = "flow_velocity.totalchannel.filtered";
+    String FLOW_VELOCITY_TAU_FILTERED = "flow_velocity.tau.filtered";
+    String FLOW_VELOCITY_ANNOTATION = "flow_velocity.annotation";
+    String FLOW_VELOCITY_MEASUREMENT = "flow_velocity.measurement";
+    String FLOW_VELOCITY_DISCHARGE = "flow_velocity.discharge";
+    String FLOW_VELOCITY_WATERLEVEL = "flow_velocity.waterlevel";
 
-    String MIDDLE_BED_HEIGHT_SINGLE     = "bedheight_middle.single";
+    String MIDDLE_BED_HEIGHT_SINGLE = "bedheight_middle.single";
     String MIDDLE_BED_HEIGHT_ANNOTATION = "bedheight_middle.annotation";
 
     String BED_QUALITY_DATA_FACET = "bed_longitudinal_section";
-    String BED_QUALITY_POROSITY_TOPLAYER =
-        BED_QUALITY_DATA_FACET + ".porosity.toplayer";
-    String BED_QUALITY_POROSITY_SUBLAYER =
-        BED_QUALITY_DATA_FACET + ".porosity.sublayer";
-    String BED_QUALITY_BED_DIAMETER_TOPLAYER =
-        BED_QUALITY_DATA_FACET + ".diameter.toplayer";
-    String BED_QUALITY_BED_DIAMETER_SUBLAYER =
-        BED_QUALITY_DATA_FACET + ".diameter.sublayer";
-    String BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER =
-        BED_QUALITY_DATA_FACET + ".density.toplayer";
-    String BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER =
-        BED_QUALITY_DATA_FACET + ".density.sublayer";
-    String BED_QUALITY_BEDLOAD_DIAMETER =
-        BED_QUALITY_DATA_FACET + ".diameter.bedload";
-    String BED_DIAMETER_DATA_TOP =
-        BED_QUALITY_DATA_FACET + ".diameter.toplayer.data";
-    String BED_DIAMETER_DATA_SUB =
-        BED_QUALITY_DATA_FACET + ".diameter.sublayer.data";
-    String BEDLOAD_DIAMETER_DATA =
-        BED_QUALITY_DATA_FACET + ".diameter.bedload.data";
+    String BED_QUALITY_POROSITY_TOPLAYER = BED_QUALITY_DATA_FACET + ".porosity.toplayer";
+    String BED_QUALITY_POROSITY_SUBLAYER = BED_QUALITY_DATA_FACET + ".porosity.sublayer";
+    String BED_QUALITY_BED_DIAMETER_TOPLAYER = BED_QUALITY_DATA_FACET + ".diameter.toplayer";
+    String BED_QUALITY_BED_DIAMETER_SUBLAYER = BED_QUALITY_DATA_FACET + ".diameter.sublayer";
+    String BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER = BED_QUALITY_DATA_FACET + ".density.toplayer";
+    String BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER = BED_QUALITY_DATA_FACET + ".density.sublayer";
+    String BED_QUALITY_BEDLOAD_DIAMETER = BED_QUALITY_DATA_FACET + ".diameter.bedload";
+    String BED_DIAMETER_DATA_TOP = BED_QUALITY_DATA_FACET + ".diameter.toplayer.data";
+    String BED_DIAMETER_DATA_SUB = BED_QUALITY_DATA_FACET + ".diameter.sublayer.data";
+    String BEDLOAD_DIAMETER_DATA = BED_QUALITY_DATA_FACET + ".diameter.bedload.data";
     String POROSITY = "porosity";
 
     String BED_DIFFERENCE_YEAR = "bedheight_difference.year";
     String BED_DIFFERENCE_YEAR_FILTERED = "bedheight_difference.year.filtered";
     String BED_DIFFERENCE_HEIGHT_YEAR = "bedheight_difference.height_year";
-    String BED_DIFFERENCE_HEIGHT_YEAR_FILTERED =
-        "bedheight_difference.height_year.filtered";
+    String BED_DIFFERENCE_HEIGHT_YEAR_FILTERED = "bedheight_difference.height_year.filtered";
     String BED_DIFFERENCE_YEAR_HEIGHT1 = "bedheight_difference.year.height1";
     String BED_DIFFERENCE_YEAR_HEIGHT2 = "bedheight_difference.year.height2";
-    String BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED =
-        "bedheight_difference.year.height1.filtered";
-    String BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED =
-        "bedheight_difference.year.height2.filtered";
+    String BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED = "bedheight_difference.year.height1.filtered";
+    String BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED = "bedheight_difference.year.height2.filtered";
 
     String MORPHOLOGIC_WIDTH = "morph-width";
 
@@ -358,88 +300,87 @@
 
     String SQ_OVERVIEW = "sq_overview";
 
-    String SQ_A_CURVE       = "sq_a_curve";
+    String SQ_A_CURVE = "sq_a_curve";
     String SQ_A_MEASUREMENT = "sq_a_measurement";
-    String SQ_A_OUTLIER     = "sq_a_outlier";
+    String SQ_A_OUTLIER = "sq_a_outlier";
     String SQ_A_OUTLIER_CURVE = "sq_a_outlier_curve";
     String SQ_A_OUTLIER_MEASUREMENT = "sq_a_outlier_measurement";
 
-    String SQ_B_CURVE       = "sq_b_curve";
+    String SQ_B_CURVE = "sq_b_curve";
     String SQ_B_MEASUREMENT = "sq_b_measurement";
-    String SQ_B_OUTLIER     = "sq_b_outlier";
-    String SQ_B_OUTLIER_CURVE  = "sq_b_outlier_curve";
-    String SQ_B_OUTLIER_MEASUREMENT  = "sq_b_outlier_measurement";
+    String SQ_B_OUTLIER = "sq_b_outlier";
+    String SQ_B_OUTLIER_CURVE = "sq_b_outlier_curve";
+    String SQ_B_OUTLIER_MEASUREMENT = "sq_b_outlier_measurement";
 
-    String SQ_C_CURVE       = "sq_c_curve";
+    String SQ_C_CURVE = "sq_c_curve";
     String SQ_C_MEASUREMENT = "sq_c_measurement";
-    String SQ_C_OUTLIER     = "sq_c_outlier";
+    String SQ_C_OUTLIER = "sq_c_outlier";
     String SQ_C_OUTLIER_CURVE = "sq_c_outlier_curve";
     String SQ_C_OUTLIER_MEASUREMENT = "sq_c_outlier_measurement";
 
-    String SQ_D_CURVE       = "sq_d_curve";
+    String SQ_D_CURVE = "sq_d_curve";
     String SQ_D_MEASUREMENT = "sq_d_measurement";
-    String SQ_D_OUTLIER     = "sq_d_outlier";
+    String SQ_D_OUTLIER = "sq_d_outlier";
     String SQ_D_OUTLIER_CURVE = "sq_d_outlier_curve";
     String SQ_D_OUTLIER_MEASUREMENT = "sq_d_outlier_measurement";
 
-    String SQ_E_CURVE       = "sq_e_curve";
+    String SQ_E_CURVE = "sq_e_curve";
     String SQ_E_MEASUREMENT = "sq_e_measurement";
-    String SQ_E_OUTLIER     = "sq_e_outlier";
+    String SQ_E_OUTLIER = "sq_e_outlier";
     String SQ_E_OUTLIER_CURVE = "sq_e_outlier_curve";
     String SQ_E_OUTLIER_MEASUREMENT = "sq_e_outlier_curve_measurement";
 
-    String SQ_F_CURVE       = "sq_f_curve";
+    String SQ_F_CURVE = "sq_f_curve";
     String SQ_F_MEASUREMENT = "sq_f_measurement";
-    String SQ_F_OUTLIER     = "sq_f_outlier";
+    String SQ_F_OUTLIER = "sq_f_outlier";
     String SQ_F_OUTLIER_CURVE = "sq_f_outlier_curve";
     String SQ_F_OUTLIER_MEASUREMENT = "sq_f_outlier_measurement";
 
-    String SQ_G_CURVE       = "sq_g_curve";
+    String SQ_G_CURVE = "sq_g_curve";
     String SQ_G_MEASUREMENT = "sq_g_measurement";
-    String SQ_G_OUTLIER     = "sq_g_outlier";
+    String SQ_G_OUTLIER = "sq_g_outlier";
     String SQ_G_OUTLIER_CURVE = "sq_g_outlier_curve";
     String SQ_G_OUTLIER_MEASUREMENT = "sq_g_outlier_measurement";
 
-    String SQ_A_CURVE_OV       = "sq_a_curve_overview";
+    String SQ_A_CURVE_OV = "sq_a_curve_overview";
     String SQ_A_MEASUREMENT_OV = "sq_a_measurement_overview";
-    String SQ_A_OUTLIER_OV     = "sq_a_outlier_overview";
+    String SQ_A_OUTLIER_OV = "sq_a_outlier_overview";
     String SQ_A_OUTLIER_CURVE_OV = "sq_a_outlier_curve_overview";
     String SQ_A_OUTLIER_MEASUREMENT_OV = "sq_a_outlier_measurement_overview";
 
-    String SQ_B_CURVE_OV       = "sq_b_curve_overview";
+    String SQ_B_CURVE_OV = "sq_b_curve_overview";
     String SQ_B_MEASUREMENT_OV = "sq_b_measurement_overview";
-    String SQ_B_OUTLIER_OV     = "sq_b_outlier_overview";
-    String SQ_B_OUTLIER_CURVE_OV  = "sq_b_outlier_curve_overview";
-    String SQ_B_OUTLIER_MEASUREMENT_OV  = "sq_b_outlier_measurement_overview";
+    String SQ_B_OUTLIER_OV = "sq_b_outlier_overview";
+    String SQ_B_OUTLIER_CURVE_OV = "sq_b_outlier_curve_overview";
+    String SQ_B_OUTLIER_MEASUREMENT_OV = "sq_b_outlier_measurement_overview";
 
-    String SQ_C_CURVE_OV       = "sq_c_curve_overview";
+    String SQ_C_CURVE_OV = "sq_c_curve_overview";
     String SQ_C_MEASUREMENT_OV = "sq_c_measurement_overview";
-    String SQ_C_OUTLIER_OV     = "sq_c_outlier_overview";
+    String SQ_C_OUTLIER_OV = "sq_c_outlier_overview";
     String SQ_C_OUTLIER_CURVE_OV = "sq_c_outlier_curve_overview";
     String SQ_C_OUTLIER_MEASUREMENT_OV = "sq_c_outlier_measurement_overview";
 
-    String SQ_D_CURVE_OV       = "sq_d_curve_overview";
+    String SQ_D_CURVE_OV = "sq_d_curve_overview";
     String SQ_D_MEASUREMENT_OV = "sq_d_measurement_overview";
-    String SQ_D_OUTLIER_OV     = "sq_d_outlier_overview";
+    String SQ_D_OUTLIER_OV = "sq_d_outlier_overview";
     String SQ_D_OUTLIER_CURVE_OV = "sq_d_outlier_curve_overview";
     String SQ_D_OUTLIER_MEASUREMENT_OV = "sq_d_outlier_measurement_overview";
 
-    String SQ_E_CURVE_OV       = "sq_e_curve_overview";
+    String SQ_E_CURVE_OV = "sq_e_curve_overview";
     String SQ_E_MEASUREMENT_OV = "sq_e_measurement_overview";
-    String SQ_E_OUTLIER_OV     = "sq_e_outlier_overview";
+    String SQ_E_OUTLIER_OV = "sq_e_outlier_overview";
     String SQ_E_OUTLIER_CURVE_OV = "sq_e_outlier_curve_overview";
-    String SQ_E_OUTLIER_MEASUREMENT_OV =
-        "sq_e_outlier_curve_measurement_overview";
+    String SQ_E_OUTLIER_MEASUREMENT_OV = "sq_e_outlier_curve_measurement_overview";
 
-    String SQ_F_CURVE_OV       = "sq_f_curve_overview";
+    String SQ_F_CURVE_OV = "sq_f_curve_overview";
     String SQ_F_MEASUREMENT_OV = "sq_f_measurement_overview";
-    String SQ_F_OUTLIER_OV     = "sq_f_outlier_overview";
+    String SQ_F_OUTLIER_OV = "sq_f_outlier_overview";
     String SQ_F_OUTLIER_CURVE_OV = "sq_f_outlier_curve_overview";
     String SQ_F_OUTLIER_MEASUREMENT_OV = "sq_f_outlier_measurement_overview";
 
-    String SQ_G_CURVE_OV       = "sq_g_curve_overview";
+    String SQ_G_CURVE_OV = "sq_g_curve_overview";
     String SQ_G_MEASUREMENT_OV = "sq_g_measurement_overview";
-    String SQ_G_OUTLIER_OV     = "sq_g_outlier_overview";
+    String SQ_G_OUTLIER_OV = "sq_g_outlier_overview";
     String SQ_G_OUTLIER_CURVE_OV = "sq_g_outlier_curve_overview";
     String SQ_G_OUTLIER_MEASUREMENT_OV = "sq_g_outlier_measurement_overview";
 
@@ -479,9 +420,9 @@
 
     String STATIC_BEDHEIGHT = "static_bedheight";
 
-    String BEDHEIGHT                = "bedheight";
+    String BEDHEIGHT = "bedheight";
     String BEDHEIGHT_SOUNDING_WIDTH = "bedheight_sounding_width";
-    String BEDHEIGHT_WIDTH          = "bedheight_width";
+    String BEDHEIGHT_WIDTH = "bedheight_width";
 
     String EXTREME_WQ_CURVE = "extreme_wq_curve";
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Module.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Module.java	Fri Jul 13 11:56:22 2018 +0200
@@ -15,12 +15,21 @@
  */
 public class Module {
 
-    private String name;
-    List<String> rivers;
-    private boolean selected;
+    private final String name;
 
-    public Module(String name, boolean selected, List<String> rivers) {
+    /** 
+     * Defines an (optional) group name for a module. Modules with the same group name are considered to be in the same group
+     * This can be uised to group modules in the front-end  
+     */
+    private final String group;
+
+    private final boolean selected;
+
+    private final List<String> rivers;
+
+    public Module(final String name, final boolean selected, final String group, final List<String> rivers) {
         this.name = name;
+        this.group = group;
         this.rivers = rivers;
         this.selected = selected;
     }
@@ -32,6 +41,10 @@
     public boolean isSelected() {
         return this.selected;
     }
+    
+    public String getGroup() {
+        return this.group;
+    }
 
     public List<String> getRivers() {
         return this.rivers;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticWQKmsCacheKey.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/StaticWQKmsCacheKey.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,6 +10,9 @@
 
 import java.io.Serializable;
 
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
 /**
  * Caching-Key object for 'static' wst- data.
  */
@@ -18,24 +21,48 @@
 {
     public static final String CACHE_NAME = "wst-wq-value-table-static";
 
-    private int column;
-    private int wst_id;
+    private final int column;
+    
+    private final int wst_id;
 
-    public StaticWQKmsCacheKey(int column, int wst_id) {
+    private double from;
+
+    private double to;
+
+    private int hash;
+
+    public StaticWQKmsCacheKey(final int column, final int wst_id, final double from, final double to) {
         this.wst_id  = wst_id;
         this.column  = column;
+        this.from = from;
+        this.to = to;
+        this.hash = new HashCodeBuilder().append(column).append(wst_id).append(false).append(to).toHashCode();
     }
 
+    @Override
     public int hashCode() {
-        return (wst_id << 8) | column;
+        return this.hash;
     }
 
-    public boolean equals(Object other) {
-        if (!(other instanceof StaticWQKmsCacheKey)) {
+    @Override
+    public boolean equals(final Object other) {
+        
+        if (other == null) 
             return false;
+        if( other == this) 
+            return true;
+        if (other.getClass() != getClass()) {
+          return false;
         }
-        StaticWQKmsCacheKey o = (StaticWQKmsCacheKey) other;
-        return this.wst_id == o.wst_id && this.column == o.column;
+        
+        final StaticWQKmsCacheKey rhs = (StaticWQKmsCacheKey) other;
+        
+        return new EqualsBuilder(). //
+                append(column, rhs.column). //
+                append(wst_id, rhs.wst_id). //
+                append(from, rhs.from). //
+                append(to, rhs.to). //
+                isEquals();
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsFactory.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -33,16 +33,22 @@
     private static Logger log = Logger.getLogger(WQKmsFactory.class);
 
     /** Query to get km and wqs for wst_id and column_pos. */
-    public static final String SQL_SELECT_WQS =
+    private static final String SQL_SELECT_WQS =
         "SELECT position, w, q FROM wst_value_table " +
         "WHERE wst_id = :wst_id AND column_pos = :column_pos";
+    /** Query to get km and wqs for wst_id and column_pos. */
 
+    private static final String SQL_SELECT_WQS_RANGE =
+            "SELECT position, w, q FROM wst_value_table " +
+            "WHERE wst_id = :wst_id AND column_pos = :column_pos " +
+            "AND position BETWEEN :kmfrom AND :kmto";
+    
     /** Get wst_id and position from wst_columns. */
-    public static final String SQL_SELECT_COLUMN =
+    private static final String SQL_SELECT_COLUMN =
         "SELECT wst_id, position FROM wst_columns WHERE id = :column_id";
 
     /** Query to get name for wst_id and column_pos. */
-    public static final String SQL_SELECT_NAME =
+    private static final String SQL_SELECT_NAME =
         "SELECT name " +
         "FROM wst_columns "+
         "WHERE id = :column_id";
@@ -56,14 +62,21 @@
     /**
      * Get WKms for given column (pos) and wst_id, caring about the cache.
      */
-    public static WQKms getWQKms(int columnPos, int wst_id) {
+    public static WQKms getWQKms(final int columnPos, final int wst_id) {
+        return getWQKms(columnPos, wst_id, Double.NaN, Double.NaN);
+    }
+
+    /**
+     * Get WKms for given column (pos) and wst_id, caring about the cache.
+     */
+    public static WQKms getWQKms(final int columnPos, final int wst_id, final double from, final double to) {
         log.debug("WQKmsFactory.getWQKms");
-        Cache cache = CacheFactory.getCache(StaticWQKmsCacheKey.CACHE_NAME);
+        final Cache cache = CacheFactory.getCache(StaticWQKmsCacheKey.CACHE_NAME);
 
-        StaticWQKmsCacheKey cacheKey;
+        final StaticWQKmsCacheKey cacheKey;
 
         if (cache != null) {
-            cacheKey = new StaticWQKmsCacheKey(wst_id, columnPos);
+            cacheKey = new StaticWQKmsCacheKey(wst_id, columnPos, from, to);
             Element element = cache.get(cacheKey);
             if (element != null) {
                 log.debug("Got static wst values from cache");
@@ -74,16 +87,16 @@
             cacheKey = null;
         }
 
-        WQKms values = getWQKmsUncached(columnPos, wst_id);
+        final WQKms values = getWQKmsUncached(columnPos, wst_id, from, to);
 
-        if (values != null && cacheKey != null) {
+        if (values != null && cache != null && cacheKey != null) {
             log.debug("Store static wst values in cache.");
-            Element element = new Element(cacheKey, values);
+            final Element element = new Element(cacheKey, values);
             cache.put(element);
         }
         return values;
     }
-
+    
     /**
      * Get WKms for given column (id), caring about the cache.
      */
@@ -94,7 +107,7 @@
         StaticWQKmsCacheKey cacheKey;
 
         if (cache != null) {
-            cacheKey = new StaticWQKmsCacheKey(-columnID, -columnID);
+            cacheKey = new StaticWQKmsCacheKey(-columnID, -columnID, Double.NaN, Double.NaN);
             Element element = cache.get(cacheKey);
             if (element != null) {
                 log.debug("Got static wst values from cache");
@@ -107,7 +120,7 @@
 
         int[] cInfo = getColumn(columnID);
         if (cInfo == null) return null;
-        WQKms values = getWQKmsUncached(cInfo[1], cInfo[0]);
+        WQKms values = getWQKmsUncached(cInfo[1], cInfo[0], Double.NaN, Double.NaN);
 
 
         if (values != null && cacheKey != null) {
@@ -125,27 +138,37 @@
      * @param wst_id database id of the wst
      * @return respective WQKms.
      */
-    public static WQKms getWQKmsUncached(int column, int wst_id) {
+    private static WQKms getWQKmsUncached(final int column, final int wst_id, final double from, final double to) {
 
         if (log.isDebugEnabled()) {
             log.debug("WQKmsFactory.getWQKmsUncached, column "
                 + column + ", wst_id " + wst_id);
         }
 
-        WQKms wqkms = new WQKms(WKmsFactory.getWKmsName(column, wst_id));
+        final WQKms wqkms = new WQKms(WKmsFactory.getWKmsName(column, wst_id));
 
-        Session session = SessionHolder.HOLDER.get();
-        SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WQS)
+        boolean hasRange = !Double.isNaN(from) && !Double.isNaN(to);
+
+        final String query = hasRange ? SQL_SELECT_WQS_RANGE : SQL_SELECT_WQS;
+        
+        final Session session = SessionHolder.HOLDER.get();
+        final SQLQuery sqlQuery = session.createSQLQuery(query)
             .addScalar("position", StandardBasicTypes.DOUBLE)
             .addScalar("w",  StandardBasicTypes.DOUBLE)
             .addScalar("q",  StandardBasicTypes.DOUBLE);
+
         sqlQuery.setInteger("wst_id",     wst_id);
         sqlQuery.setInteger("column_pos", column);
+        if( hasRange )
+        {
+            sqlQuery.setDouble("kmfrom", from);
+            sqlQuery.setDouble("kmto", to);
+        }
 
-        List<Object []> results = sqlQuery.list();
+        final List<Object []> results = sqlQuery.list();
 
         for (int i = 0, N = results.size(); i < N; i++) {
-            Object[] row = results.get(i);
+            final Object[] row = results.get(i);
             // add(w, q, km)
             if (row == null
                 || row[0] == null
@@ -184,6 +207,7 @@
 
         List<Object []> results = sqlQuery.list();
 
+        // FIXME: right? this will always return row[0]!
         for (int i = 0, N = results.size(); i < N; i++) {
             Object[] row = results.get(i);
             return new int[] {(Integer)row[0], (Integer)row[1]};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstColumnFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,41 @@
+/** 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.model;
+
+import java.util.List;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.Wst;
+import org.dive4elements.river.model.WstColumn;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * @author Gernot Belger
+ */
+public final class WstColumnFactory {
+    private WstColumnFactory() {
+        throw new UnsupportedOperationException("helper class");
+    }
+
+    public static WstColumn getWstColumn(final int wst_id, final int columnPosition) {
+        final Session session = SessionHolder.HOLDER.get();
+
+        final Wst wst = WstFactory.getWst(wst_id);
+
+        final Query query = session.createQuery("from WstColumn where wst=:wst_id and position = :position");
+        query.setParameter("wst_id", wst);
+        query.setInteger("position", columnPosition);
+
+        final List<WstColumn> columns = query.list();
+
+        return columns.isEmpty() ? null : columns.get(0);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstFactory.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -52,5 +52,17 @@
 
         return wsts.isEmpty() ? null : wsts.get(0);
     }
+
+
+    public static Wst getWst(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+
+        final Query query = session.createQuery("from Wst where id=:id");
+        query.setInteger("id", id);
+
+        final List<Wst> wsts = query.list();
+
+        return wsts.isEmpty() ? null : wsts.get(0);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,30 +8,6 @@
 
 package org.dive4elements.river.artifacts.model.fixings;
 
-import org.dive4elements.artifacts.common.utils.StringUtils;
-
-import org.dive4elements.river.artifacts.access.FixAccess;
-
-import org.dive4elements.river.artifacts.math.fitting.Function;
-import org.dive4elements.river.artifacts.math.fitting.FunctionFactory;
-
-import org.dive4elements.river.artifacts.model.Calculation;
-import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.FixingsColumn;
-import org.dive4elements.river.artifacts.model.FixingsColumnFactory;
-
-import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing.Filter;
-
-import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing;
-import org.dive4elements.river.artifacts.model.FixingsOverview.IdsFilter;
-
-import org.dive4elements.river.artifacts.model.FixingsOverview;
-import org.dive4elements.river.artifacts.model.FixingsOverviewFactory;
-import org.dive4elements.river.artifacts.model.Parameters;
-
-import org.dive4elements.river.utils.DoubleUtil;
-import org.dive4elements.river.utils.KMIndex;
-
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
@@ -39,99 +15,104 @@
 import java.util.Map;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.common.utils.StringUtils;
+import org.dive4elements.river.artifacts.access.FixAccess;
+import org.dive4elements.river.artifacts.math.fitting.Function;
+import org.dive4elements.river.artifacts.math.fitting.FunctionFactory;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.FixingsColumn;
+import org.dive4elements.river.artifacts.model.FixingsColumnFactory;
+import org.dive4elements.river.artifacts.model.FixingsOverview;
+import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing;
+import org.dive4elements.river.artifacts.model.FixingsOverview.Fixing.Filter;
+import org.dive4elements.river.artifacts.model.FixingsOverview.IdsFilter;
+import org.dive4elements.river.artifacts.model.FixingsOverviewFactory;
+import org.dive4elements.river.artifacts.model.Parameters;
+import org.dive4elements.river.utils.DoubleUtil;
+import org.dive4elements.river.utils.KMIndex;
 
 /** Calculation base class for fix. */
-public abstract class FixCalculation
-extends               Calculation
-{
+public abstract class FixCalculation extends Calculation {
     private static Logger log = Logger.getLogger(FixCalculation.class);
 
     public static final double EPSILON = 1e-4;
 
-    public static final String [] STANDARD_COLUMNS = {
-        "km", "chi_sqr", "max_q", "std-dev"
-    };
+    public static final String[] STANDARD_COLUMNS = { "km", "chi_sqr", "max_q", "std-dev" };
 
     protected static class FitResult {
 
-        protected Parameters      parameters;
-        protected KMIndex<QWD []> referenced;
-        protected KMIndex<QWI []> outliers;
+        protected Parameters parameters;
+        protected KMIndex<QWD[]> referenced;
+        protected KMIndex<QWI[]> outliers;
 
         public FitResult() {
         }
 
-        public FitResult(
-            Parameters      parameters,
-            KMIndex<QWD []> referenced,
-            KMIndex<QWI []> outliers
-        ) {
+        public FitResult(final Parameters parameters, final KMIndex<QWD[]> referenced, final KMIndex<QWI[]> outliers) {
             this.parameters = parameters;
             this.referenced = referenced;
-            this.outliers   = outliers;
+            this.outliers = outliers;
         }
 
         public Parameters getParameters() {
-            return parameters;
+            return this.parameters;
         }
 
-        public KMIndex<QWD []> getReferenced() {
-            return referenced;
+        public KMIndex<QWD[]> getReferenced() {
+            return this.referenced;
         }
 
-        public KMIndex<QWI []> getOutliers() {
-            return outliers;
+        public KMIndex<QWI[]> getOutliers() {
+            return this.outliers;
         }
     } // class FitResult
 
-    /** Helper class to bundle the meta information of a column
-     *  and the real data.
+    /**
+     * Helper class to bundle the meta information of a column
+     * and the real data.
      */
     protected static class Column {
 
         protected Fixing.Column meta;
         protected FixingsColumn data;
-        protected int           index;
+        protected int index;
 
         public Column() {
         }
 
-        public Column(Fixing.Column meta, FixingsColumn data, int index) {
-            this.meta  = meta;
-            this.data  = data;
+        public Column(final Fixing.Column meta, final FixingsColumn data, final int index) {
+            this.meta = meta;
+            this.data = data;
             this.index = index;
         }
 
         public Date getDate() {
-            return meta.getStartTime();
+            return this.meta.getStartTime();
         }
 
         public String getDescription() {
-            return meta.getDescription();
+            return this.meta.getDescription();
         }
 
         public int getIndex() {
-            return index;
+            return this.index;
         }
 
         public int getId() {
-            return meta.getId();
+            return this.meta.getId();
         }
 
-        public boolean getQW(
-            double    km,
-            double [] qs,
-            double [] ws,
-            int       index
-        ) {
-            qs[index] = data.getQ(km);
-            return data.getW(km, ws, index);
+        public boolean getQW(final double km, final double[] qs, final double[] ws, final int index) {
+            qs[index] = this.data.getQ(km);
+            return this.data.getW(km, ws, index);
         }
 
-        public boolean getQW(double km, double [] wq) {
-            data.getW(km, wq, 0);
-            if (Double.isNaN(wq[0])) return false;
-            wq[1] = data.getQ(km);
+        public boolean getQW(final double km, final double[] wq) {
+            this.data.getW(km, wq, 0);
+            if (Double.isNaN(wq[0]))
+                return false;
+            wq[1] = this.data.getQ(km);
             return !Double.isNaN(wq[1]);
         }
     } // class Column
@@ -144,49 +125,46 @@
         protected Map<Integer, Column> columns;
 
         public ColumnCache() {
-            columns = new HashMap<Integer, Column>();
+            this.columns = new HashMap<>();
         }
 
-        public Column getColumn(Fixing.Column meta) {
-            Integer key = meta.getId();
-            Column column = columns.get(key);
+        public Column getColumn(final Fixing.Column meta) {
+            final Integer key = meta.getId();
+            Column column = this.columns.get(key);
             if (column == null) {
-                FixingsColumn data = FixingsColumnFactory
-                    .getInstance()
-                    .getColumnData(meta);
+                final FixingsColumn data = FixingsColumnFactory.getInstance().getColumnData(meta);
                 if (data != null) {
-                    column = new Column(meta, data, columns.size());
-                    columns.put(key, column);
+                    column = new Column(meta, data, this.columns.size());
+                    this.columns.put(key, column);
                 }
             }
             return column;
         }
     } // class ColumnCache
 
-
-    protected String  river;
-    protected double  from;
-    protected double  to;
-    protected double  step;
+    protected String river;
+    protected double from;
+    protected double to;
+    protected double step;
     protected boolean preprocessing;
-    protected String  function;
-    protected int []  events;
-    protected int     qSectorStart;
-    protected int     qSectorEnd;
+    protected String function;
+    protected int[] events;
+    protected int qSectorStart;
+    protected int qSectorEnd;
 
     public FixCalculation() {
     }
 
-    public FixCalculation(FixAccess access) {
-        String  river         = access.getRiverName();
-        Double  from          = access.getFrom();
-        Double  to            = access.getTo();
-        Double  step          = access.getStep();
-        String  function      = access.getFunction();
-        int []  events        = access.getEvents();
-        Integer qSectorStart  = access.getQSectorStart();
-        Integer qSectorEnd    = access.getQSectorEnd();
-        Boolean preprocessing = access.getPreprocessing();
+    public FixCalculation(final FixAccess access) {
+        final String river = access.getRiverName();
+        final Double from = access.getLowerKm();
+        final Double to = access.getUpperKm();
+        final Double step = access.getStep();
+        final String function = access.getFunction();
+        final int[] events = access.getEvents();
+        final Integer qSectorStart = access.getQSectorStart();
+        final Integer qSectorEnd = access.getQSectorEnd();
+        final Boolean preprocessing = access.getPreprocessing();
 
         if (river == null) {
             addProblem("fix.missing.river");
@@ -225,57 +203,51 @@
         }
 
         if (!hasProblems()) {
-            this.river         = river;
-            this.from          = from;
-            this.to            = to;
-            this.step          = step;
-            this.function      = function;
-            this.events        = events;
-            this.qSectorStart  = qSectorStart;
-            this.qSectorEnd    = qSectorEnd;
+            this.river = river;
+            this.from = from;
+            this.to = to;
+            this.step = step;
+            this.function = function;
+            this.events = events;
+            this.qSectorStart = qSectorStart;
+            this.qSectorEnd = qSectorEnd;
             this.preprocessing = preprocessing;
         }
     }
 
-    protected static String toString(
-        String [] parameterNames,
-        double [] values
-    ) {
-        StringBuilder sb = new StringBuilder();
+    protected static String toString(final String[] parameterNames, final double[] values) {
+        final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < parameterNames.length; ++i) {
-            if (i > 0) sb.append(", ");
+            if (i > 0)
+                sb.append(", ");
             sb.append(parameterNames[i]).append(": ").append(values[i]);
         }
         return sb.toString();
     }
 
-
-    /** Create filter to accept only the chosen events.
-     *  This factored out out to be overwritten.
+    /**
+     * Create filter to accept only the chosen events.
+     * This factored out out to be overwritten.
      */
     protected Filter createFilter() {
-        return new IdsFilter(events);
+        return new IdsFilter(this.events);
     }
 
-    protected List<Column> getEventColumns(
-        FixingsOverview overview,
-        ColumnCache     cc
-    ) {
-        FixingsColumnFactory fcf = FixingsColumnFactory.getInstance();
+    protected List<Column> getEventColumns(final FixingsOverview overview, final ColumnCache cc) {
+        final FixingsColumnFactory fcf = FixingsColumnFactory.getInstance();
 
-        Filter filter = createFilter();
-
-        List<Fixing.Column> metas = overview.filter(null, filter);
+        final Filter filter = createFilter();
 
-        List<Column> columns = new ArrayList<Column>(metas.size());
+        final List<Fixing.Column> metas = overview.filter(null, filter);
 
-        for (Fixing.Column meta: metas) {
+        final List<Column> columns = new ArrayList<>(metas.size());
 
-            Column data = cc.getColumn(meta);
+        for (final Fixing.Column meta : metas) {
+
+            final Column data = cc.getColumn(meta);
             if (data == null) {
                 addProblem("fix.cannot.load.data");
-            }
-            else {
+            } else {
                 columns.add(data);
             }
         }
@@ -284,12 +256,8 @@
     }
 
     // Fit a function to the given points from fixation.
-    protected FitResult doFitting(
-        FixingsOverview overview,
-        ColumnCache     cc,
-        Function        func
-    ) {
-        boolean debug = log.isDebugEnabled();
+    protected FitResult doFitting(final FixingsOverview overview, final ColumnCache cc, final Function func) {
+        final boolean debug = log.isDebugEnabled();
 
         final List<Column> eventColumns = getEventColumns(overview, cc);
 
@@ -298,26 +266,19 @@
             return null;
         }
 
-        final double  [] qs = new double[eventColumns.size()];
-        final double  [] ws = new double[qs.length];
-        final boolean [] interpolated = new boolean[ws.length];
+        final double[] qs = new double[eventColumns.size()];
+        final double[] ws = new double[qs.length];
+        final boolean[] interpolated = new boolean[ws.length];
 
-        Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() {
+        final Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() {
             @Override
-            public QWD create(double q, double w) {
+            public QWD create(final double q, final double w) {
                 // Check all the event columns for close match
                 // and take the description and the date from meta.
                 for (int i = 0; i < qs.length; ++i) {
-                    if (Math.abs(qs[i]-q) < EPSILON
-                    &&  Math.abs(ws[i]-w) < EPSILON) {
-                        Column column = eventColumns.get(i);
-                        return new QWD(
-                            qs[i], ws[i],
-                            column.getDescription(),
-                            column.getDate(),
-                            interpolated[i],
-                            0d,
-                            column.getId()); // Use database id here
+                    if (Math.abs(qs[i] - q) < EPSILON && Math.abs(ws[i] - w) < EPSILON) {
+                        final Column column = eventColumns.get(i);
+                        return new QWD(qs[i], ws[i], column.getDescription(), column.getDate(), interpolated[i], 0d, column.getId()); // Use database id here
                     }
                 }
                 log.warn("cannot find column for (" + q + ", " + w + ")");
@@ -325,35 +286,33 @@
             }
         };
 
-        Fitting fitting = new Fitting(func, qwdFactory, preprocessing);
+        final Fitting fitting = new Fitting(func, qwdFactory, this.preprocessing);
 
-        String [] parameterNames = func.getParameterNames();
+        final String[] parameterNames = func.getParameterNames();
 
-        Parameters results =
-            new Parameters(
-                StringUtils.join(STANDARD_COLUMNS, parameterNames));
+        final Parameters results = new Parameters(StringUtils.join(STANDARD_COLUMNS, parameterNames));
 
         boolean invalid = false;
 
-        double [] kms = DoubleUtil.explode(from, to, step / 1000.0);
+        final double[] kms = DoubleUtil.explode(this.from, this.to, this.step / 1000.0);
 
         if (debug) {
             log.debug("number of kms: " + kms.length);
         }
 
-        KMIndex<QWI []> outliers   = new KMIndex<QWI []>();
-        KMIndex<QWD []> referenced = new KMIndex<QWD []>(kms.length);
+        final KMIndex<QWI[]> outliers = new KMIndex<>();
+        final KMIndex<QWD[]> referenced = new KMIndex<>(kms.length);
 
-        int kmIndex             = results.columnIndex("km");
-        int chiSqrIndex         = results.columnIndex("chi_sqr");
-        int maxQIndex           = results.columnIndex("max_q");
-        int stdDevIndex         = results.columnIndex("std-dev");
-        int [] parameterIndices = results.columnIndices(parameterNames);
+        final int kmIndex = results.columnIndex("km");
+        final int chiSqrIndex = results.columnIndex("chi_sqr");
+        final int maxQIndex = results.columnIndex("max_q");
+        final int stdDevIndex = results.columnIndex("std-dev");
+        final int[] parameterIndices = results.columnIndices(parameterNames);
 
         int numFailed = 0;
 
-        for (int i = 0; i < kms.length; ++i) {
-            double km = kms[i];
+        for (final double km2 : kms) {
+            final double km = km2;
 
             // Fill Qs and Ws from event columns.
             for (int j = 0; j < ws.length; ++j) {
@@ -369,7 +328,7 @@
                 continue;
             }
 
-            QWD [] refs = fitting.referencedToArray();
+            final QWD[] refs = fitting.referencedToArray();
 
             referenced.add(km, refs);
 
@@ -377,17 +336,17 @@
                 outliers.add(km, fitting.outliersToArray());
             }
 
-            int row = results.newRow();
-            double [] values = fitting.getParameters();
+            final int row = results.newRow();
+            final double[] values = fitting.getParameters();
 
             results.set(row, kmIndex, km);
             results.set(row, chiSqrIndex, fitting.getChiSquare());
             results.set(row, stdDevIndex, fitting.getStandardDeviation());
-            results.set(row, maxQIndex,   fitting.getMaxQ());
+            results.set(row, maxQIndex, fitting.getMaxQ());
             invalid |= results.set(row, parameterIndices, values);
 
             if (debug) {
-                log.debug("km: "+km+" " + toString(parameterNames, values));
+                log.debug("km: " + km + " " + toString(parameterNames, values));
             }
         }
 
@@ -404,22 +363,17 @@
         outliers.sort();
         referenced.sort();
 
-        return new FitResult(
-            results,
-            referenced,
-            outliers);
+        return new FitResult(results, referenced, outliers);
     }
 
     public CalculationResult calculate() {
-        FixingsOverview overview =
-            FixingsOverviewFactory.getOverview(river);
+        final FixingsOverview overview = FixingsOverviewFactory.getOverview(this.river);
 
         if (overview == null) {
             addProblem("fix.no.overview.available");
         }
 
-        Function func = FunctionFactory.getInstance()
-            .getFunction(function);
+        final Function func = FunctionFactory.getInstance().getFunction(this.function);
 
         if (func == null) {
             addProblem("fix.invalid.function.name");
@@ -428,13 +382,13 @@
         if (hasProblems()) {
             return new CalculationResult(this);
         }
-        CalculationResult result = innerCalculate(overview, func);
+        final CalculationResult result = innerCalculate(overview, func);
 
         if (result != null) {
             // Workaraound to deal with same dates in data set
-            Object o = result.getData();
+            final Object o = result.getData();
             if (o instanceof FixResult) {
-                FixResult fr = (FixResult)o;
+                final FixResult fr = (FixResult) o;
                 fr.makeReferenceEventsDatesUnique();
                 fr.remapReferenceIndicesToRank();
             }
@@ -443,9 +397,6 @@
         return result;
     }
 
-    protected abstract CalculationResult innerCalculate(
-        FixingsOverview overview,
-        Function        function
-    );
+    protected abstract CalculationResult innerCalculate(FixingsOverview overview, Function function);
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixRealizingCalculationExtended.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,59 @@
+/** 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.model.fixings;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.dive4elements.river.artifacts.access.FixRealizingAccess;
+import org.dive4elements.river.artifacts.model.FixingsOverview;
+import org.dive4elements.river.artifacts.model.FixingsOverviewFactory;
+
+/**
+ * REMARK: this inheritance is only needed, beause changing the orignal calculation will probably break the
+ * serialization of the artifact....
+ *
+ * @author Gernot Belger
+ */
+public class FixRealizingCalculationExtended extends FixRealizingCalculation {
+    private static final long serialVersionUID = 1L;
+
+    public FixRealizingCalculationExtended(final FixRealizingAccess fixAccess) {
+        super(fixAccess);
+    }
+
+    public int determineMeanYear() {
+        final FixingsOverview overview = FixingsOverviewFactory.getOverview(this.river);
+        final ColumnCache cc = new ColumnCache();
+
+        final SortedSet<Integer> years = new TreeSet<>();
+
+        final Calendar cal = Calendar.getInstance();
+
+        final List<Column> columns = getEventColumns(overview, cc);
+        for (final Column column : columns) {
+            final Date date = column.getDate();
+            cal.setTime(date);
+
+            final int year = cal.get(Calendar.YEAR);
+            years.add(year);
+        }
+
+        final Integer first = years.first();
+        final Integer last = years.last();
+        if (first == null || last == null)
+            return -1;
+
+        return (first + last) / 2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightMinMaxFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,101 @@
+/* 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.model.minfo;
+
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.BedHeightAccess;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
+import org.dive4elements.river.model.BedHeightValueType;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * More or less the same as {@link BedHeightFacet}, but was necessary to copy because else we break the old
+ * serialization.
+ *
+ * @author Gernot Belger
+ */
+public class BedHeightMinMaxFacet extends BlackboardDataFacet implements FacetTypes {
+
+    private static final long serialVersionUID = 1L;
+
+    private final BedHeightValueType valueType;
+
+    public BedHeightMinMaxFacet(final String name, final String description, final BedHeightValueType valueType) {
+        super(0, name, description);
+
+        this.valueType = valueType;
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedheight_middle.section.yaxis.label");
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return the data.
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final BedHeightAccess access = new BedHeightAccess((D4EArtifact) artifact);
+
+        final BedHeight single = BedHeight.getBedHeightById(access.getHeightId());
+
+        final List<BedHeightValue> bedheightValues = BedHeightValue.getBedHeightValues(single, access.getFrom(true), access.getTo(true));
+
+        final TDoubleArrayList stations = new TDoubleArrayList(bedheightValues.size());
+        final TDoubleArrayList values = new TDoubleArrayList(bedheightValues.size());
+
+        for (final BedHeightValue bedheightValue : bedheightValues) {
+
+            final Double station = bedheightValue.getStation();
+            final Double value = this.valueType.getValue(bedheightValue);
+
+            if (station != null && value != null) {
+                stations.add(station);
+                values.add(value);
+            }
+        }
+
+        this.addMetaData(Resources.getMsg(context.getMeta(), "meta.bedheight.cur.elevation"), single.getCurElevationModel().getName());
+
+        if (single.getOldElevationModel() != null)
+            this.addMetaData(Resources.getMsg(context.getMeta(), "meta.bedheight.old.elevation"), single.getOldElevationModel().getName());
+
+        this.addMetaData(Resources.getMsg(context.getMeta(), "meta.bedheight.river.elevation"), access.getRiver().getWstUnit().getName());
+
+        return new double[][] { stations.toNativeArray(), values.toNativeArray() };
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public BedHeightMinMaxFacet deepCopy() {
+        final BedHeightMinMaxFacet copy = new BedHeightMinMaxFacet(this.name, this.description, this.valueType);
+        copy.set(this);
+        return copy;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/resources/Resources.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/resources/Resources.java	Fri Jul 13 11:56:22 2018 +0200
@@ -12,6 +12,7 @@
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
 
 import org.apache.log4j.Logger;
 
@@ -61,7 +62,7 @@
         // TODO IMPLEMENT ME
 
         locales = new Locale[2];
-        locales[0] = Locale.GERMANY;
+        locales[0] = Locale.GERMAN;
         locales[1] = Locale.ENGLISH;
     }
 
@@ -124,18 +125,18 @@
      * @return a translated string.
      */
     public static String getMsg(
-            CallMeta meta,
-            String   key,
-            String   def,
-            Object[] args)
+    		CallMeta meta,
+    		String   key,
+    		String   def,
+    		Object... args)
     {
-        String template = getMsg(meta, key, (String)null);
-
-        if (template == null) {
-            return def;
-        }
-
-        return format(meta, template, args);
+    	String template = getMsg(meta, key, (String)null);
+    	
+    	if (template == null) {
+    		return def;
+    	}
+    	
+    	return format(meta, template, args);
     }
 
     public static String format(
@@ -175,7 +176,7 @@
      * @return the translated message.
      */
     public static String getMsg(Locale locale, String key, String def) {
-        ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
+        ResourceBundle bundle = ResourceBundle.getBundle("messages", locale, Control.getNoFallbackControl(Control.FORMAT_DEFAULT));
 
         try {
             return bundle.getString(key);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/MetaDataService.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/MetaDataService.java	Fri Jul 13 11:56:22 2018 +0200
@@ -15,12 +15,14 @@
 import java.util.Map;
 import java.util.HashMap;
 
+import org.dive4elements.artifactdatabase.ArtifactCallContext;
+import org.dive4elements.artifactdatabase.ArtifactDatabaseImpl;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.artifacts.GlobalContext;
 import org.dive4elements.artifacts.ArtifactDatabase;
 import org.dive4elements.artifacts.ArtifactDatabaseException;
-
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.artifacts.common.utils.StringUtils;
 
@@ -97,8 +99,7 @@
         String parameters = XMLUtils.xpathString(
             data, XPATH_PARAMETERS, ArtifactNamespaceContext.INSTANCE);
 
-        return doService(
-            artifactId, userId, outs, parameters, globalContext);
+        return doService( artifactId, userId, outs, parameters, globalContext, callMeta);
     }
 
 
@@ -133,7 +134,8 @@
         String        userId,
         String        outsString,
         String        parameters,
-        GlobalContext globalContext
+        GlobalContext globalContext, 
+        CallMeta callMeta
     ) {
         Document result = XMLUtils.newDocument();
 
@@ -151,22 +153,19 @@
             return result;
         }
 
+        Object dbObject = (ArtifactDatabase)globalContext.get(ARTIFACT_DATA_BASE_KEY);
+        if (!(dbObject instanceof ArtifactDatabase)) {
+            log.error("Cannot find artifact database");
+            return result;
+        }
+        ArtifactDatabaseImpl db = (ArtifactDatabaseImpl)dbObject;
+        
         if (artifactId != null) {
             if (!StringUtils.checkUUID(artifactId)) {
                 log.warn("'" + artifactId + "' is not a UUID");
                 return result;
             }
 
-            Object dbObject =
-                (ArtifactDatabase)globalContext.get(ARTIFACT_DATA_BASE_KEY);
-
-            if (!(dbObject instanceof ArtifactDatabase)) {
-                log.error("Cannot find artifact database");
-                return result;
-            }
-
-            ArtifactDatabase db = (ArtifactDatabase)dbObject;
-
             Artifact artifact;
 
             try {
@@ -196,10 +195,16 @@
             ? new String [0]
             : outsString.split("\\s*,\\s*");
 
-        Recommendations rec = Recommendations.getInstance();
-        rec.recommend(
-            flysArtifact, userId, outs, data, result);
 
+        // REMARK: this is an ugly place to do it and should rather be done inside the ArtifactDatabase, from where this service is called.
+        // REMARK: at the moment we know that this is currently only used to transport the ArtifactDatabase
+        final ArtifactCallContext callContext = new ArtifactCallContext(db, CallContext.NOTHING, callMeta, null);
+            
+        final Recommendations rec = Recommendations.getInstance();
+        rec.recommend( flysArtifact, userId, outs, data, result, callContext );
+
+        callContext.postCall();
+        
         return result;
     }
 }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/ModuleService.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/ModuleService.java	Fri Jul 13 11:56:22 2018 +0200
@@ -30,6 +30,7 @@
 
     private static Logger log = Logger.getLogger(ModuleService.class);
 
+    @Override
     protected Document doProcess(
         Document      data,
         GlobalContext globalContext,
@@ -37,26 +38,25 @@
     ) {
         log.debug("ModuleService.process");
 
-        Document result = XMLUtils.newDocument();
+        final Document result = XMLUtils.newDocument();
 
-        XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
+        final XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
             result,
             ArtifactNamespaceContext.NAMESPACE_URI,
             ArtifactNamespaceContext.NAMESPACE_PREFIX);
 
-        Element em = ec.create("modules");
-        List<Module> modules = (List<Module>)globalContext.get(
-            RiverContext.MODULES);
+        final Element em = ec.create("modules");
+        final List<Module> modules = (List<Module>)globalContext.get( RiverContext.MODULES);
 
-        for (Module module : modules) {
-            Element m = ec.create("module");
+        for (final Module module : modules) {
+            final Element m = ec.create("module");
             ec.addAttr(m, "name", module.getName(), true);
-            String localname = Resources.getMsg(callMeta,
-                    MODULE + "." + module.getName(), module.getName());
+
+            final String localname = Resources.getMsg(callMeta, MODULE + "." + module.getName(), module.getName());
             ec.addAttr(m, "localname", localname, true);
 
-            for (String river : module.getRivers()) {
-                Element r = ec.create("river");
+            for (final String river : module.getRivers()) {
+                final Element r = ec.create("river");
                 r.setAttribute("uuid", river);
                 m.appendChild(r);
             }
@@ -64,6 +64,13 @@
                 ec.addAttr(m, "selected", "true", true);
             }
 
+            final String group = module.getGroup();
+            if( group != null ) {
+                final String groupLabel = Resources.getMsg(callMeta, group);
+                ec.addAttr(m, "groupId", group, true);
+                ec.addAttr(m, "groupLabel", groupLabel, true);
+            }
+
             em.appendChild(m);
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/CalculationSelectSinfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,77 @@
+/* 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+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.model.CollisionHibernateFactory;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.collision.CollisionAccess;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.model.sinfo.Collision;
+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);
+
+    @Override
+    protected Element[] createItems(final XMLUtils.ElementCreator cr, final Artifact artifact, final String name, final 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(final Artifact artifact) throws IllegalArgumentException {
+        log.debug("CalculationSelect.validate");
+
+        final SINFOArtifact sinfo = (SINFOArtifact) artifact;
+        /* throws an exception if calculation mode is invalid */
+        final String calcmode = sinfo.getCalculationMode().toString(); // "toString()" is important
+        if (calcmode.equals("sinfo_calc_collision")) {
+
+            final CollisionAccess access = new CollisionAccess((SINFOArtifact) artifact);
+
+            final List<Collision> list = CollisionHibernateFactory.getCollisionsByRiver(access.getRiver());
+
+            if (list.size() == 0) {
+                throw new IllegalArgumentException("error_no_data_for_river");
+            }
+        }
+
+        return true;
+    }
+
+}
\ 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/SINFOArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,137 @@
+/* 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.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.D50Processor;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthDevelopmentPerYearProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthDevelopmentProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.TauProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.VelocityProcessor;
+
+/**
+ * The default SINFO artifact.
+ *
+ * @author Gernot Belger
+ */
+public class SINFOArtifact extends D4EArtifact {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 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_RIVER = "river";
+
+    private static final String FIELD_MODE = "calculation_mode";
+
+    static {
+        // Active/deactivate facets.
+        // BEWARE: we can only define one activity for "sinfo", so we use the artifact as place for this
+        FacetActivity.Registry.getInstance().register("sinfo", new FacetActivity() {
+            @Override
+            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String output) {
+
+                final String name = facet.getName();
+
+                if ("sinfo_tkk".equals(output)) {
+                    if (FlowDepthProcessor.FACET_FLOW_DEPTH_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                    if (VelocityProcessor.FACET_TKH_VELOCITY_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                    if (TauProcessor.FACET_TKH_TAU_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                    if (D50Processor.FACET_TKH_D50_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                }
+
+                if ("sinfo_flow_depth_development".equals(output)) {
+                    if (FlowDepthProcessor.FACET_FLOW_DEPTH_CURRENT_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                    if (FlowDepthProcessor.FACET_FLOW_DEPTH_HISTORICAL_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                    if (FlowDepthDevelopmentProcessor.FACET_WATERLEVEL_DIFFERENCE_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                    if (FlowDepthDevelopmentProcessor.FACET_BEDHEIGHT_DIFFERENCE_FILTERED.equals(name))
+                        return Boolean.FALSE;
+                }
+
+                if (FlowDepthProcessor.FACET_FLOW_DEPTH_RAW.equals(name))
+                    return Boolean.FALSE;
+                if (FlowDepthProcessor.FACET_FLOW_DEPTH_TKH_RAW.equals(name))
+                    return Boolean.FALSE;
+                if (FlowDepthProcessor.FACET_FLOW_DEPTH_CURRENT_RAW.equals(name))
+                    return Boolean.FALSE;
+                if (FlowDepthProcessor.FACET_FLOW_DEPTH_HISTORICAL_RAW.equals(name))
+                    return Boolean.FALSE;
+                if (FlowDepthProcessor.FACET_FLOW_DEPTH_MIN_RAW.equals(name))
+                    return Boolean.FALSE;
+                if (FlowDepthProcessor.FACET_FLOW_DEPTH_MAX_RAW.equals(name))
+                    return Boolean.FALSE;
+
+                if (FlowDepthDevelopmentProcessor.FACET_FLOW_DEPTH_DEVELOPMENT_RAW.equals(name))
+                    return Boolean.FALSE;
+                if (FlowDepthDevelopmentPerYearProcessor.FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_RAW.equals(name))
+                    return Boolean.FALSE;
+
+                return null;
+            }
+        });
+    }
+
+    /**
+     * 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 (final Exception e) {
+            throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE, e);
+        }
+    }
+
+    public String getRiver() {
+        return getDataAsString(FIELD_RIVER);
+    }
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -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_collision,
+    sinfo_calc_transport_bodies_heights,
+    sinfo_calc_flood_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/collision/CollisionAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,77 @@
+/* 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.collision;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.common.EpochYearAccessHelper;
+import org.dive4elements.river.artifacts.model.DateRange;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.SinfoCalcMode;
+
+/**
+ * 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
+ */
+final public class CollisionAccess extends RangeAccess {
+
+    private final EpochYearAccessHelper helper;
+
+    /// Fields from state:
+
+    // calculation_mode (String), sollte sinfo_calc_collision sein
+    // ld_from, ld_to
+    // ye_select (String), mögliche werte: "state.sinfo.epoch" "state.sinfo.year"
+    // years (String)
+    // epochs (String)
+
+    public CollisionAccess(final SINFOArtifact artifact) {
+        super(artifact);
+
+        /* assert calculation mode */
+        final SinfoCalcMode calculationMode = artifact.getCalculationMode();
+        this.helper = new EpochYearAccessHelper(artifact);
+        assert (calculationMode == SinfoCalcMode.sinfo_calc_flow_depth);
+    }
+
+    public int[] getYears() {
+        return this.helper.getYears("state.sinfo.year", "years");
+    }
+
+    public List<DateRange> getEpochs() {
+        return this.helper.getEpochs("state.sinfo.epoch", "epochs");
+    }
+
+    /**
+     * String expression of the years or epoches collection, resp.
+     */
+    public String getYearsHeader() {
+        if (getYears() != null) {
+            final String ys = Arrays.toString(getYears());
+            return ys.substring(1, ys.length() - 1);
+        }
+        else {
+            String ys = "";
+            String sep = "";
+            for (final DateRange dr : getEpochs()) {
+                ys += String.format("%s%d-%d", sep, dr.getFromYear(), dr.getToYear());
+                sep = ", ";
+            }
+            return ys;
+        }
+    }
+}
\ 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/collision/CollisionArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,142 @@
+/** 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.collision;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.DefaultOutput;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactFactory;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.AbstractStaticStateArtifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.states.StaticState;
+import org.w3c.dom.Document;
+
+/**
+ * Display of a river bed collision data series loaded from database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class CollisionArtifact extends AbstractStaticStateArtifact implements FacetTypes {
+
+    private static final long serialVersionUID = 1L;
+
+    /** The log for this class. */
+    private static Logger log = Logger.getLogger(CollisionArtifact.class);
+
+    /** Artifact name. */
+    private static final String NAME = "collision";
+
+    static {
+        // TODO: Move to configuration.
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
+    }
+
+    public static final String STATIC_STATE_NAME = "state.collision.static";
+
+    /**
+     * Trivial Constructor.
+     */
+    public CollisionArtifact() {
+        log.debug("new CollisionArtifact");
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * Gets called from factory, to set things up.
+     */
+    @Override
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
+
+        log.debug("CollisionArtifact.setup");
+
+        if (log.isDebugEnabled()) {
+            log.debug(XMLUtils.toString(data));
+        }
+
+        final String code = getDatacageIDValue(data);
+        final String[] parts = code.split("-");
+        if (parts.length >= 2)
+            addStringData("collision_id", parts[1]);
+        if (parts.length >= 3)
+            addStringData("year", parts[2]);
+        else
+            addStringData("year", "jahr?");
+        String seriesName;
+        if (parts.length >= 4)
+            seriesName = parts[3];
+        else
+            seriesName = "name?";
+
+        // if different facet wanted, e.g. for each year use different facetIndex
+        // if multiple Result treated, get each Result from data
+        createFacets(callMeta, code, seriesName, getDataAsString("year"));
+
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
+
+    private void createFacets(final CallMeta callMeta, final String code, final String seriesName, final String yearForName) {
+        if (code == null)
+            return;
+
+        final String[] parts = code.split("-");
+        if (parts.length < 2) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
+        }
+        final ArrayList<Facet> facets = new ArrayList<>(1);
+        facets.add(CollisionCountProcessor.createFacet(0, callMeta, yearForName));
+        // facets.add(CollisionGaugeWProcessor.createFacet(callMeta, seriesName)); //REMARK gauge_w is the cm above gauge datum,
+        // therefore only useful with transformation to NHN
+        addFacets(STATIC_STATE_NAME, facets);
+    }
+
+    @Override
+    protected void initStaticState() {
+
+        log.debug("initStaticState " + getName() + " " + identifier());
+
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
+
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        output.addFacets(facets);
+        state.addOutput(output);
+
+        setStaticState(state);
+    }
+
+    @Override
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
+        // do not clone facets, etc. from master artifact
+
+        log.debug("initialize");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
+
+        log.debug("ld_from " + getDataAsString("ld_from"));
+        log.debug("ld_to " + getDataAsString("ld_to"));
+    }
+}
\ 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/collision/CollisionCalcDetailResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,110 @@
+/* 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.collision;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * Contains the results of a {@link FloodDurationCalculation}.
+ *
+ * @author Gernot Belger
+ */
+final class CollisionCalcDetailResult extends AbstractCalculationExportableResult {
+
+    private static final long serialVersionUID = 1L;
+    private static final String JASPER_FILE = "/jasper/templates/sinfo.collision.detail.jrxml";
+
+    public CollisionCalcDetailResult(final String label, final Collection<ResultRow> rows) {
+        super(label, rows);
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+
+        // do nothing so far
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final int colSize = 6;
+        exportContextCSV.writeTitleForTabs("sinfo.export.csv.title.collision.detail", 6); // Voraussetzung für Tabs ist, dass der Titel vor den Headern
+        // geschrieben wird.
+        // Das ist etwas doof.
+
+        final Collection<String> header = new ArrayList<>(colSize);
+
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.date));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.collisionGaugeW, SInfoResultType.collisionGaugeW.getUnit()));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.gaugeLabel));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.discharge, SInfoResultType.discharge.getUnit()));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.dischargeZone));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[colSize]));
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+        return formatRow(exportContextCSV, row);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextCSV, final ResultRow row) {
+        /*
+         * final Collection<String> lines = new ArrayList<>(6);
+         * lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.station));
+         * return lines.toArray(new String[lines.size()]);
+         */
+        return formatRow(exportContextCSV, row);
+    }
+
+    private String[] formatRow(final IExportContext exportContext, final ResultRow row) {
+
+        final Collection<String> lines = new ArrayList<>(6);
+
+        lines.add(exportContext.formatRowValue(row, GeneralResultType.station));
+        lines.add(exportContext.formatRowValue(row, GeneralResultType.date));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.collisionGaugeW));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.gaugeLabel));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.discharge));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.dischargeZone));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    @Override
+    protected String getJasperFile() {
+        return JASPER_FILE;
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContextCSV, final MetaAndTableJRDataSource source) {
+
+        /* column headings */
+        exportContextCSV.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContextCSV.addJRMetadata(source, "date_header", GeneralResultType.date);
+        exportContextCSV.addJRMetadata(source, "gaugew_header", SInfoResultType.collisionGaugeW);
+        exportContextCSV.addJRMetadata(source, "gauge_header", SInfoResultType.gaugeLabel);
+        exportContextCSV.addJRMetadata(source, "discharge_header", SInfoResultType.discharge);
+        exportContextCSV.addJRMetadata(source, "dischargezone_header", SInfoResultType.dischargeZone);
+    }
+}
\ 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/collision/CollisionCalcFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,56 @@
+/** 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.collision;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+/**
+ * Facet for calculated river bed collision counts
+ *
+ * @author Matthias Schäfer
+ */
+public class CollisionCalcFacet extends SInfoResultFacet {
+
+    private static final long serialVersionUID = 1;
+    private int year;
+
+    private CollisionCalcFacet() {
+        super();
+        // required for clone operation deepCopy()
+    }
+
+    public CollisionCalcFacet(final int facetIndex, final int resultIndex, final int year, final String name, final String description,
+            final String yAxisLabelKey, final ComputeType type, final String hash, final String stateId) {
+        super(facetIndex, resultIndex, name, description, yAxisLabelKey, type, stateId, hash);
+
+        this.year = year;
+    }
+
+    public int getYear() {
+        return this.year;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        // FIXME: why not simply use the full constructor instead?
+        final CollisionCalcFacet copy = new CollisionCalcFacet();
+        // FIXME: why does DataFacet does not override set? Bad access to variables of parent!
+        copy.set(this);
+        copy.type = this.type;
+        copy.hash = this.hash;
+        copy.stateId = this.stateId;
+        copy.year = this.year;
+        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/collision/CollisionCalcOverviewResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,131 @@
+/* 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.collision;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IResultType;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Contains the results of a {@link CollisionCalculation}.
+ *
+ * @author Gernot Belger
+ */
+final public class CollisionCalcOverviewResult extends AbstractCalculationExportableResult {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String JASPER_FILE = "/jasper/templates/sinfo.collision.overview.jrxml";
+
+    private final int[] singleYears;
+
+    public CollisionCalcOverviewResult(final String label, final int[] singleYears, final Collection<ResultRow> rows) {
+        super(label, rows);
+        this.singleYears = singleYears;
+    }
+
+    public int[] getSingleYears() {
+        return this.singleYears;
+    }
+
+    public double[][] getStationPointsByYear(final IResultType type, final int year) {
+
+        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
+        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
+
+        for (final ResultRow row : this.rows) {
+
+            if ((this.singleYears == null) || (Integer.valueOf(row.getValue(SInfoResultType.years).toString()) == year)) {
+
+                final double station = row.getDoubleValue(GeneralResultType.station);
+                final double value = row.getDoubleValue(type);
+
+                xPoints.add(station);
+                yPoints.add(value);
+            }
+        }
+
+        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        // do nothing so far
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+        final int colSize = 3;
+        exportContextCSV.writeTitleForTabs("sinfo.export.csv.title.collison.overview", 3); // Voraussetzung für Tabs ist, dass der Titel vor den Headern
+        // geschrieben wird.
+        // Das ist etwas doof.
+
+        final Collection<String> header = new ArrayList<>(colSize);
+
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.years));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.collisionCount));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[colSize]));
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+        return formatRow(exportContextCSV, row);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) {
+
+        final Collection<String> lines = new ArrayList<>(3);
+
+        lines.add(exportContextPDF.formatRowValue(row, GeneralResultType.station));
+        lines.add(exportContextPDF.formatRowValue(row, SInfoResultType.years));
+        lines.add(exportContextPDF.formatRowValue(row, SInfoResultType.collisionCount));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    private String[] formatRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        final Collection<String> lines = new ArrayList<>(3);
+
+        lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.station));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.years));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.collisionCount));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    @Override
+    protected String getJasperFile() {
+        return JASPER_FILE;
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+
+        /* column headings */
+        exportContext.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContext.addJRMetadata(source, "collision_years_header", SInfoResultType.years);
+        exportContext.addJRMetadata(source, "collision_count_header", SInfoResultType.collisionCount);
+    }
+}
\ 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/collision/CollisionCalcProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,89 @@
+/** 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.collision;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.common.AbstractSInfoProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate the facet and data series of calculated bed collision counts
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class CollisionCalcProcessor extends AbstractSInfoProcessor {
+
+    public static final String FACET_COLLISION_CALC_COUNT = "sinfo_facet_collision_calc_count";
+
+    public static final String FACET_COLLISION_CALC_COUNT_2 = "sinfo_facet_collision_calc_count.2";
+
+    public static final String FACET_COLLISION_CALC_COUNT_3 = "sinfo_facet_collision_calc_count.3";
+
+    private static final String[] COLLISION_FACETS = new String[] { FACET_COLLISION_CALC_COUNT, FACET_COLLISION_CALC_COUNT_2, FACET_COLLISION_CALC_COUNT_3 };
+
+    private static final String I18N_AXIS_LABEL = "chart.collision_count.section.yaxis.label";
+
+    private static final String I18N_SERIES_NAME_PATTERN = "collision.count.title";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_COLLISION_CALC_COUNT);
+        HANDLED_FACET_TYPES.add(FACET_COLLISION_CALC_COUNT_2);
+        HANDLED_FACET_TYPES.add(FACET_COLLISION_CALC_COUNT_3);
+    }
+
+    public CollisionCalcProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        final CollisionCalcFacet facet = (CollisionCalcFacet) bundle.getFacet();
+        final int year = facet.getYear();
+
+        final CollisionCalcOverviewResult result = (CollisionCalcOverviewResult) getResult(generator, bundle);
+
+        final double[][] points = result.getStationPointsByYear(SInfoResultType.collisionCount, year);
+
+        return buildSeriesForType(points, generator, bundle, theme, visible, null);
+    }
+
+    public static final Facet createFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int resultIndex, final int year, final int themeCount) {
+
+        // REMARK: we are using themeCount as facet index, because we get several lines (with the same facet name) for the same
+        // result index; however name and index are used on client side as unique id.
+
+        final CollisionCalcOverviewResult ccoResult = (CollisionCalcOverviewResult) result;
+        if (ccoResult.getSingleYears() == null) {
+            final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, result.getLabel());
+            return new CollisionCalcFacet(themeCount, resultIndex, -1, FACET_COLLISION_CALC_COUNT, facetDescription, I18N_AXIS_LABEL, ComputeType.ADVANCE, hash,
+                    id);
+        } else {
+            final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, Integer.toString(year));
+            return new CollisionCalcFacet(themeCount, resultIndex, year, COLLISION_FACETS[themeCount % 3], facetDescription, I18N_AXIS_LABEL,
+                    ComputeType.ADVANCE, hash, id);
+        }
+    }
+}
\ 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/collision/CollisionCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,138 @@
+/* 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.collision;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DateRange;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.GaugeDischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.common.GaugeMainValueFinder;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.CollisionAggregateValue;
+import org.dive4elements.river.model.sinfo.CollisionValue;
+
+class CollisionCalculation {
+
+    // private static Logger log = Logger.getLogger(FloodDurationCalculation.class);
+
+    private final CallContext context;
+
+    public CollisionCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+
+        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
+
+        // access input data
+        final CollisionAccess access = new CollisionAccess(sinfo);
+        final River river = access.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+
+        final DoubleRange calcRange = access.getRange();
+
+        // calculate results for each year or epoch
+        final Calculation problems = new Calculation();
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
+
+        final CollisionCalculationResults results = new CollisionCalculationResults(calcModeLabel, user, riverInfo, calcRange, access.getYearsHeader());
+
+        final Collection<ResultRow> overViewRows = new ArrayList<>();
+
+        if (access.getYears() != null) {
+            for (final int year : access.getYears())
+                calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), year, year, false);
+        }
+        else {
+            for (final DateRange dr : access.getEpochs())
+                calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), true);
+        }
+        final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), access.getYears(), overViewRows);
+        results.addResult(overviewResult, problems);
+
+        // create q-for-w-finders for all gauges of the calculation km range
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+        final Map<Gauge, GaugeDischargeValuesFinder> qFinders = new HashMap<>();
+        final Map<Gauge, GaugeMainValueFinder> zoneFinders = new HashMap<>();
+        for (final Gauge gauge : river.determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble())) {
+            qFinders.put(gauge, GaugeDischargeValuesFinder.loadValues(gauge, problems));
+            zoneFinders.put(gauge, GaugeMainValueFinder.loadValues(MainValueTypeKey.Q, gauge, problems));
+        }
+        final Collection<ResultRow> detailsRows = new ArrayList<>();
+
+        // calculate secondary results for each year or epoch
+        if (access.getYears() != null) {
+            for (final int year : access.getYears())
+                calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, year, qFinders, zoneFinders);
+        }
+        else {
+            for (final DateRange dr : access.getEpochs())
+                calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), qFinders, zoneFinders);
+        }
+        final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows);
+        results.addResult(detailResult, problems);
+
+        return new CalculationResult(results, problems);
+    }
+
+    /**
+     * Calculates the collision counts for a km range of a river and a year or year range (epoch),
+     * and adds them to a ResultRow collection
+     */
+    private void calculateOverview(final Collection<ResultRow> rows, final River river, final double fromKm, final double toKm, final int fromYear,
+            final int toYear, final boolean isEpoch) {
+        for (final CollisionAggregateValue aggregate : CollisionAggregateValue.getValuesByKm(river, fromKm, toKm, fromYear, toYear)) {
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, aggregate.getStation())
+                    .putValue(SInfoResultType.years, (isEpoch? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear)))
+                    .putValue(SInfoResultType.collisionCount, aggregate.getCount()));
+        }
+    }
+
+    /**
+     * Calculates the collision details for a km range of a river and a year or year range (epoch),
+     * and adds them to a ResultRow collection
+     */
+    private void calculateDetails(final Collection<ResultRow> rows, final RiverInfoProvider riverInfo, final double fromKm, final double toKm,
+            final int fromYear, final int toYear, final Map<Gauge, GaugeDischargeValuesFinder> qFinders,
+            final Map<Gauge, GaugeMainValueFinder> zoneFinders) {
+        for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(fromYear),
+                DateUtil.getEndDateFromYear(toYear))) {
+            final Gauge gauge = riverInfo.getGauge(collision.getStation(), true);
+            final double q = qFinders.get(gauge).getDischarge(collision.getGaugeW());
+            final double qOut = Double.isInfinite(q) ? Double.NaN : q;
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, collision.getStation())
+                    .putValue(GeneralResultType.date, collision.getEventDate())
+                    .putValue(SInfoResultType.collisionGaugeW, collision.getGaugeW())
+                    .putValue(SInfoResultType.gaugeLabel, collision.getGaugeName())
+                    .putValue(SInfoResultType.discharge, qOut)
+                    .putValue(SInfoResultType.dischargeZone, zoneFinders.get(gauge).findZoneName(q)));
+        }
+    }
+}
\ 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/collision/CollisionCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,35 @@
+/** 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.collision;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Gernot Belger
+ */
+final class CollisionCalculationResults extends AbstractCalculationResults<AbstractCalculationExportableResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String yearsHeader;
+
+    public CollisionCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange,
+            final String yearsHeader) {
+        super(calcModeLabel, user, river, calcRange);
+        this.yearsHeader = yearsHeader;
+    }
+
+    public String getYearsHeader() {
+        return this.yearsHeader;
+    }
+}
\ 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/collision/CollisionCountProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,59 @@
+/** 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.collision;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.common.AbstractSInfoProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for bed collision count data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class CollisionCountProcessor extends AbstractSInfoProcessor {
+
+    public static final String FACET_COLLISION_COUNT = "sinfo_facet_collision_count";
+
+    private static final String I18N_AXIS_LABEL = "chart.collision_count.section.yaxis.label";
+
+    private static final String I18N_SERIES_NAME_PATTERN = "collision.count.title";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_COLLISION_COUNT);
+    }
+
+    public CollisionCountProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    public static Facet createFacet(final int facetIndex, final CallMeta callMeta, final String year) {
+        return new CollisionFacet(facetIndex, FACET_COLLISION_COUNT, Resources.getMsg(callMeta, I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, year),
+                I18N_AXIS_LABEL);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, SInfoResultType.collisionCount, null);
+    }
+}
\ 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/collision/CollisionDbAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,52 @@
+/** 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.collision;
+
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+
+/**
+ * Access to the database loaded river bed collision artifact data
+ *
+ * @author Matthias Schäfer
+ */
+final class CollisionDbAccess extends RangeAccess {
+
+    /***** FIELDS *****/
+
+    private Integer id;
+
+    private String name;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public CollisionDbAccess(final D4EArtifact artifact) {
+        super(artifact);
+    }
+
+
+    /***** METHODS *****/
+
+    public Integer getId() {
+        if (this.id == null) {
+            this.id = getInteger("collision_id");
+        }
+        return this.id;
+    }
+
+    public String getName() {
+        if (this.name == null) {
+            this.name = getString("name");
+        }
+        return this.name;
+    }
+}
\ 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/collision/CollisionExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,36 @@
+/** 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.collision;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoI18NStrings;
+
+/**
+ * @author Gernot Belger
+ */
+public final class CollisionExporter extends AbstractCommonExporter<AbstractCalculationExportableResult, CollisionCalculationResults> {
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final CollisionCalculationResults results) {
+
+        exportContext.writeCSVGlobalMetadataDefaults();
+
+        exportContext.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_YEARS, results.getYearsHeader());
+    }
+
+    @Override
+    protected void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+    }
+}
\ 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/collision/CollisionFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,87 @@
+/** 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.collision;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.DefaultCalculationResult;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.dive4elements.river.model.sinfo.CollisionAggregateValue;
+
+/**
+ * Facet for a river bed collision value series loaded from the database
+ *
+ * @author Matthias Schäfer
+ */
+public class CollisionFacet extends BlackboardDataFacet {
+
+    private static final long serialVersionUID = 1;
+
+    public CollisionFacet(final int facetIndex, final String name, final String description, final String yAxisLabel) {
+        super(facetIndex, name, description);
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", yAxisLabel);
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return
+     *         the data as CollisionQueryCalculationResult
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final CollisionDbAccess access = new CollisionDbAccess((D4EArtifact) artifact);
+        final Collision series = Collision.getSeries(access.getId());
+        final List<CollisionAggregateValue> values = CollisionAggregateValue.getValuesByKm(series, access.getFrom(true), access.getTo(true));
+        final Collection<ResultRow> rows = new ArrayList<>();
+        for (final CollisionAggregateValue value : values) {
+
+            final ResultRow row = ResultRow.create();
+
+            row.putValue(GeneralResultType.station, value.getStation());
+            // Not needed: row.putValue(SInfoResultType.years, series.getYear());
+            row.putValue(SInfoResultType.collisionCount, value.getCount());
+            row.putValue(SInfoResultType.collisionGaugeW, value.getGaugeW());
+
+            rows.add(row);
+        }
+        return new DefaultCalculationResult(series.getFilename(), rows);
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public CollisionFacet deepCopy() {
+        final CollisionFacet copy = new CollisionFacet(this.index, this.name, this.description, this.metaData.get("Y"));
+        copy.set(this);
+        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/collision/CollisionState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,119 @@
+/* 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.collision;
+
+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.common.AbstractCalculationExportableResult;
+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.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.states.DefaultState;
+
+/**
+ * State in which a collision count has been calculated.
+ */
+public class CollisionState extends DefaultState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(CollisionState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 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) {
+        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 = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+        //
+        final CollisionCalculationResults results = (CollisionCalculationResults) res.getData();
+
+        /* add themes for chart, for each result */
+        final List<AbstractCalculationExportableResult> resultList = results.getResults();
+        int themeCount = 0;
+        for (int index = 0; index < resultList.size(); index++) {
+            if (resultList.get(index) instanceof CollisionCalcOverviewResult) {
+                final CollisionCalcOverviewResult result = (CollisionCalcOverviewResult) resultList.get(index);
+
+                final int[] singleYears = result.getSingleYears();
+
+                if (singleYears == null)
+                    facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, -1, themeCount++));
+                else {
+                    for (final int singleYear : singleYears)
+                        facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, singleYear, themeCount++));
+                }
+            }
+        }
+
+        if (!resultList.isEmpty()) {
+            final Facet csv = new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id);
+            final Facet pdf = new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id);
+
+            facets.add(csv);
+            facets.add(pdf);
+        }
+
+        final Calculation report = res.getReport();
+
+        if (report.hasProblems()) {
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+        }
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final SINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new CollisionCalculation(context).calculate(sinfo);
+    }
+}
\ 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/collision/GaugeDischargeZoneFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,106 @@
+/** 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.collision;
+
+import java.util.Map.Entry;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+
+/**
+ * Loading and search the discharge zones of a gauge
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class GaugeDischargeZoneFinder {
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(GaugeDischargeZoneFinder.class);
+
+    private final Gauge gauge;
+
+    private final Calculation problems;
+
+    private final NavigableMap<Double, MainValue> qZones;
+
+    private final String approxPrefix = "\u2248";// "ca.";
+
+    /***** CONSTRUCTORS *****/
+
+    private GaugeDischargeZoneFinder(final Gauge gauge, final Calculation problems) {
+        this.gauge = gauge;
+        this.problems = problems;
+        this.qZones = new TreeMap<>();
+        for (final MainValue mainValue : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.Q))
+            this.qZones.put(Double.valueOf(mainValue.getValue().doubleValue()), mainValue);
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the the main discharge table of a gauge (GAUGE.at)
+     *
+     * @return The discharge table values finder of the gauge, or null
+     */
+    public static GaugeDischargeZoneFinder loadValues(final Gauge gauge, final Calculation problems) {
+        return new GaugeDischargeZoneFinder(gauge, problems);
+    }
+
+    /**
+     * If this provider may return valid data at all.
+     */
+    public boolean isValid() {
+        return (this.qZones != null);
+    }
+
+    /**
+     * Discharge zone for a Q.
+     */
+    public String getDischargeZone(final double q) {
+        if (Double.isNaN(q))
+            return "";
+
+        // Exact match
+        if (this.qZones.containsKey(Double.valueOf(q)))
+            return this.qZones.get(Double.valueOf(q)).getMainValue().getName();
+
+        // Clearly below or just (max. 10%) below lowest named discharge
+        final Entry<Double, MainValue> lowerZone = this.qZones.floorEntry(Double.valueOf(q));
+        if (lowerZone == null) {
+            if (q >= this.qZones.firstKey().doubleValue() * 0.9)
+                return this.approxPrefix + this.qZones.firstEntry().getValue().getMainValue().getName();
+            else
+                return "<" + this.qZones.firstEntry().getValue().getMainValue().getName();
+        }
+
+        // Clearly above or just (max. 10%) above highest named discharge
+        final Entry<Double, MainValue> higherZone = this.qZones.ceilingEntry(Double.valueOf(q));
+        if (higherZone == null) {
+            if (q <= this.qZones.lastKey().doubleValue() * 1.1)
+                return this.approxPrefix + this.qZones.lastEntry().getValue().getMainValue().getName();
+            else
+                return ">" + this.qZones.lastEntry().getValue().getMainValue().getName();
+        }
+
+        // Near (10%) one of the borders of a zone interval, or clearly within a zone
+        if (q <= lowerZone.getKey().doubleValue() * 1.1)
+            return this.approxPrefix + lowerZone.getValue().getMainValue().getName();
+        else if (q >= higherZone.getKey().doubleValue() * 0.9)
+            return this.approxPrefix + higherZone.getValue().getMainValue().getName();
+        else
+            return lowerZone.getValue().getMainValue().getName() + "-" + higherZone.getValue().getMainValue().getName();
+    }
+}
\ 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/collision/LoadMultipleEpochSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,70 @@
+/* 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.collision;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.model.CollisionHibernateFactory;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.states.AddTableDataHelper;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.w3c.dom.Element;
+
+public class LoadMultipleEpochSelectState extends DefaultState {
+    /** The log used in this class. */
+    private static Logger log = Logger.getLogger(LoadMultipleEpochSelectState.class);
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadMultipleEpochSelectState() {
+    }
+
+    @Override
+    protected String getUIProvider() {
+        return "sinfo.collision.load_epoch_select";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+        final String datakey = "epochs";
+        try {
+            if (datakey.equals(name)) {
+
+                final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta());
+
+                helper.addColumn(0, "pinfrom", "40", "common.client.ui.from", "ICON", "CENTER", "from");
+                helper.addColumn(1, "pinto", "40", "common.client.ui.to", "ICON", "CENTER", "to");
+                helper.addColumn(2, "year", "60", "year", "INTEGER", "LEFT", null);
+
+                final CollisionAccess access = new CollisionAccess((SINFOArtifact) artifact); // Der River wurde im vorigen State bereits gesetzt
+
+                final List<Collision> collisions = CollisionHibernateFactory.getCollisionsByRiver(access.getRiver());
+                for (final Collision coll : collisions) { // TODO: Filter on Range (?)
+                    final Integer year = coll.getYear();
+                    final Map<String, String> row = new HashMap<>();
+                    row.put("year", year.toString()); // Nullpointer?
+                    helper.addRow(row);
+
+                }
+                helper.submitMapToXml();
+            }
+        }
+        catch (final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/LoadMultipleYearSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,87 @@
+/* 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.collision;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.states.AddTableDataHelper;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.w3c.dom.Element;
+
+/** State in which to fetch years for sedminent load calculation. */
+public class LoadMultipleYearSelectState extends DefaultState {
+    private static final long serialVersionUID = 1L;
+    /** The log used in this class. */
+    private static Logger log = Logger.getLogger(LoadMultipleYearSelectState.class);
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadMultipleYearSelectState() {
+    }
+
+    /** Year Select Widget. */
+    @Override
+    protected String getUIProvider() {
+        return "sinfo.collision.load_year_select";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+
+        try {
+            final String dataKeyofState = "years";// siehe sinfo.xml
+            if (dataKeyofState.equals(name)) {
+
+                final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta()); // "year" not to be confused with datakey
+
+                helper.addColumn(0, "pinfrom", "60", "common.client.ui.selection", "ICON", "CENTER", "from");
+                helper.addColumn(1, "year", "60", "year", "INTEGER", "LEFT", null);
+
+                final CollisionAccess access = new CollisionAccess((SINFOArtifact) artifact); // Der River wurde im vorigen State bereits gesetzt
+
+                // final List<Collision> collisions = CollisionHibernateFactory.getCollisionsByRiver(access.getRiver());
+                // for (final Collision coll : collisions) {
+                for (final Integer year : Collision.getYearsOfRiver(access.getRiver())) {
+                    // final Integer year = coll.getYear();
+                    final Map<String, String> row = new HashMap<>();
+                    row.put("year", year.toString()); // Nullpointer?
+                    helper.addRow(row);
+                }
+                helper.submitMapToXml();
+            }
+        }
+        catch (final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+
+    @Override
+    public void validate(final Artifact artifact, final CallContext cc) throws IllegalArgumentException {
+        // TODO: check verstehen
+
+        final CollisionAccess access = new CollisionAccess((SINFOArtifact) artifact);
+
+        // Second year should be later than first.
+
+        // if (access.getYears() == null || access.getYears().length == 0)
+        // return true;
+        // throw new IllegalArgumentException("error_years_wrong");
+
+        // 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/collision/YearChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,35 @@
+/* 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.collision;
+
+import java.util.LinkedHashMap;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.states.RadioSelect;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class YearChoice extends RadioSelect {
+    private static final long serialVersionUID = 1L;
+
+    public YearChoice() {
+        super();
+    }
+
+    @Override
+    protected LinkedHashMap<String, String> makeEntries(final CallMeta meta, final Artifact artifact) {
+        final LinkedHashMap<String, String> entries = new LinkedHashMap<>();
+        entries.put("state.sinfo.year", null);
+        entries.put("state.sinfo.epoch", null);
+        return entries;
+    }
+
+}
\ 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/common/AbstractSInfoProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,227 @@
+/* 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.common;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+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.access.RiverAccess;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.common.IResultType;
+import org.dive4elements.river.artifacts.context.RiverContext;
+import org.dive4elements.river.artifacts.math.MovingAverage;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.model.ZoomScale;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.exports.StyledSeriesBuilder;
+import org.dive4elements.river.exports.process.DefaultProcessor;
+import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
+import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Abstraction for some processor implementation within S-INFO. Probably this abstraction could also be used for other
+ * cases as well.
+ *
+ * @author Gernot Belger
+ *
+ */
+public abstract class AbstractSInfoProcessor extends DefaultProcessor {
+
+    protected static final double GAP_DISTANCE = 0.101;
+
+    private final static Logger log = Logger.getLogger(AbstractSInfoProcessor.class);
+
+    private String yAxisLabel;
+
+    private final Set<String> handled_facet_types;
+
+    private final String i18n_axis_label;
+
+    public AbstractSInfoProcessor(final String i18n_axis_label, final Set<String> handled_facet_types) {
+        this.i18n_axis_label = i18n_axis_label;
+        this.handled_facet_types = handled_facet_types;
+    }
+
+    @Override
+    public final void doOut(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+        try {
+            this.yAxisLabel = generateSeries(generator, bundle, theme, visible);
+        }
+        catch (final Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    protected static final AbstractCalculationResult getResult(final DiagramGenerator generator, final ArtifactAndFacet bundle) {
+        final CallContext context = generator.getContext();
+        final AbstractCalculationResult data = (AbstractCalculationResult) bundle.getData(context);
+        if (data == null) {
+            // Check has been here before so we keep it for security reasons
+            // this should never happen though.
+            final String facetName = bundle.getFacetName();
+            throw new IllegalStateException("Data is null for facet: " + facetName);
+        }
+
+        return data;
+    }
+
+    /**
+     * @return The axis label
+     */
+    protected abstract String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible);
+
+    protected final String buildSeriesForType(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible,
+            final IResultType resultType, final Double gapDistance) {
+
+        final AbstractCalculationResult data = getResult(generator, bundle);
+
+        final double[][] points = data.getStationPoints(resultType);
+
+        return buildSeriesForType(points, generator, bundle, theme, visible, gapDistance);
+    }
+
+    protected final String buildSeriesForType(final double[][] points, final DiagramGenerator generator, final ArtifactAndFacet bundle,
+            final ThemeDocument theme, final boolean visible, final Double gapDistance) {
+        final CallContext context = generator.getContext();
+        final Map<String, String> metaData = bundle.getFacet().getMetaData();
+
+        final Artifact artifact = bundle.getArtifact();
+
+        final StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+        series.putMetaData(metaData, artifact, context);
+
+        final String facetName = bundle.getFacetName();
+
+        final double[][] filteredPoints = filterPoints(points, context, artifact, facetName);
+
+        if (gapDistance == null)
+            StyledSeriesBuilder.addPoints(series, filteredPoints, true);
+        else
+            StyledSeriesBuilder.addPoints(series, filteredPoints, true, gapDistance);
+
+        generator.addAxisSeries(series, getAxisName(), visible);
+
+        return metaData.get("Y");
+    }
+
+    protected final String buildStepLineSeriesForType(final double[][] points, final DiagramGenerator generator, final ArtifactAndFacet bundle,
+            final ThemeDocument theme, final boolean visible) {
+
+        final CallContext context = generator.getContext();
+        final Map<String, String> metaData = bundle.getFacet().getMetaData();
+
+        final Artifact artifact = bundle.getArtifact();
+
+        final StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+        series.putMetaData(metaData, artifact, context);
+
+        final String facetName = bundle.getFacetName();
+
+        // Create WQKms to use the step points method
+        // REMARK: must have any values in w array; not sure whether the name is needed
+        final WQKms wqkms = new WQKms(points[0], points[1], points[1], facetName);
+
+        StyledSeriesBuilder.addStepPointsKmQ(series, wqkms);
+
+        generator.addAxisSeries(series, getAxisName(), visible);
+
+        return metaData.get("Y");
+    }
+
+    protected final String buildSeriesForTkh(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme,
+            final boolean visible) {
+
+        final AbstractTkhCalculationResult data = (AbstractTkhCalculationResult) getResult(generator, bundle);
+
+        final StyledXYSeries seriesUp = new StyledXYSeries(bundle.getFacetDescription(), theme);
+        final double[][] pointsUp = data.getTkhUpPoints();
+        StyledSeriesBuilder.addPoints(seriesUp, pointsUp, true);
+
+        // REMARK: we add " " because the description is misused as id, which must be unique.
+        final StyledXYSeries seriesDown = new StyledXYSeries(bundle.getFacetDescription() + " ", theme);
+        final double[][] pointsDown = data.getTkhDownPoints();
+        StyledSeriesBuilder.addPoints(seriesDown, pointsDown, true);
+
+        final StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(theme);
+        area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN);
+        area.addSeries(seriesUp);
+        area.addSeries(seriesDown);
+
+        generator.addAreaSeries(area, getAxisName(), visible);
+
+        return null;
+    }
+
+    private Double findRadius(final CallContext context, final Artifact artifact) {
+        final Double start = (Double) context.getContextValue("startkm");
+        final Double end = (Double) context.getContextValue("endkm");
+
+        if (start == null || end == null)
+            return null;
+
+        final RiverContext fc = (RiverContext) context.globalContext();
+        final ZoomScale scales = (ZoomScale) fc.get("zoomscale");
+        final RiverAccess access = new RiverAccess((D4EArtifact) artifact);
+        final String river = access.getRiverName();
+
+        return scales.getRadius(river, start, end);
+    }
+
+    private double[][] filterPoints(final double[][] points, final CallContext context, final Artifact artifact, final String facetName) {
+
+        if (facetName.endsWith(".filtered")) {
+            final Double radius = findRadius(context, artifact);
+            return movingAverage(radius, points);
+        }
+
+        return points;
+    }
+
+    private double[][] movingAverage(final Double radius, final double[][] points) {
+
+        if (radius == null)
+            return points;
+
+        return MovingAverage.weighted(points, radius);
+    }
+
+    @Override
+    public final boolean canHandle(final String facettype) {
+        return this.handled_facet_types.contains(facettype);
+    }
+
+    @Override
+    public final String getAxisLabel(final DiagramGenerator generator) {
+        if (this.yAxisLabel != null && !this.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
+            // TODO: 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(this.yAxisLabel, this.yAxisLabel);
+        }
+        return generator.msg(this.i18n_axis_label, "MISSING");
+    }
+
+    protected static final Facet createFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int resultIndex, final String axisLabel, final String facetId, final String description) {
+        final String facetFlowDepthFilteredDescription = Resources.getMsg(context.getMeta(), description, description, result.getLabel());
+        return new SInfoResultFacet(resultIndex, facetId, facetFlowDepthFilteredDescription, axisLabel, ComputeType.ADVANCE, id, hash);
+    }
+}
\ 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/common/AbstractTkhCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,110 @@
+/** 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.common;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.SoilKind;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * @author Gernot Belger
+ */
+
+public abstract class AbstractTkhCalculationResult extends AbstractCalculationExportableResult {
+
+    private static final long serialVersionUID = 1L;
+
+    private final boolean hasTkh;
+    private final WstInfo wst;
+
+    public AbstractTkhCalculationResult(final String label, final WstInfo wst, final boolean hasTkh, final Collection<ResultRow> rows) {
+        super(label, rows);
+        this.wst = wst;
+        this.hasTkh = hasTkh;
+    }
+
+    public final boolean hasTkh() {
+        return this.hasTkh;
+    }
+
+    public final double[][] getTkhUpPoints() {
+
+        final double[][] points = getStationPoints(SInfoResultType.tkhup);
+        final List<SoilKind> kinds = getValues(SInfoResultType.soilkind);
+
+        final double[] xPoints = points[0];
+        final double[] yPoints = points[1];
+
+        return adjustTkhVisualization(xPoints, yPoints, kinds);
+    }
+
+    public final double[][] getTkhDownPoints() {
+
+        final double[][] points = getStationPoints(SInfoResultType.tkhdown);
+        final List<SoilKind> kinds = getValues(SInfoResultType.soilkind);
+
+        final double[] xPoints = points[0];
+        final double[] yPoints = points[1];
+
+        return adjustTkhVisualization(xPoints, yPoints, kinds);
+    }
+
+    /**
+     * the up and down points must be further adjusted for visualization, see Mail Hr. Reiß
+     * basically we need to introduce extra points when the kind changes, so we get vertical lines in that case
+     */
+    private double[][] adjustTkhVisualization(final double[] xPoints, final double[] yPoints, final List<SoilKind> kinds) {
+
+        final TDoubleArrayList adjustedX = new TDoubleArrayList(xPoints.length);
+        final TDoubleArrayList adjustedY = new TDoubleArrayList(yPoints.length);
+
+        adjustedX.add(xPoints[0]);
+        adjustedY.add(yPoints[0]);
+
+        for (int i = 1; i < xPoints.length; i++) {
+
+            final SoilKind kind1 = kinds.get(i - 1);
+            final SoilKind kind2 = kinds.get(i);
+
+            if (kind1 != kind2) {
+                /* introduce two extra points in order to create a vertical line in the middle of the two adjacent points */
+                final double x1 = xPoints[i - 1];
+                final double y1 = yPoints[i - 1];
+                final double x2 = xPoints[i];
+                final double y2 = yPoints[i];
+
+                final double middleX = (x1 + x2) / 2;
+
+                // REMARK: we can't produce a 100% vertical line, as the area-renderer will not work correctly
+                adjustedX.add(middleX - 0.0001);
+                adjustedY.add(y1);
+
+                adjustedX.add(middleX + 0.0001);
+                adjustedY.add(y2);
+            }
+
+            /* always add the real point now */
+            adjustedX.add(xPoints[i]);
+            adjustedY.add(yPoints[i]);
+        }
+
+        return new double[][] { adjustedX.toNativeArray(), adjustedY.toNativeArray() };
+    }
+
+    public final WstInfo getWst() {
+        return this.wst; // TODO: Meta-Data export hier hin
+    }
+}
\ 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/common/D50Processor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,58 @@
+/* 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class D50Processor extends AbstractSInfoProcessor {
+
+    public static final String FACET_TKH_D50_FILTERED = "sinfo_facet_d50";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.tkh_d50.section.yaxis.label";
+
+    private static final String SINFO_CHART_D50_YAXIS_LABEL = "sinfo.chart.tkh_d50.yaxis.label";
+
+    private static final String I18N_FACET_TKH_D50_FILTERED_DESCRIPTION = "sinfo.facet.tkh_d50.description";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_TKH_D50_FILTERED);
+    }
+
+    public D50Processor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        final String facetName = bundle.getFacetName();
+        if (FACET_TKH_D50_FILTERED.contentEquals(facetName))
+            return buildSeriesForType(generator, bundle, theme, visible, SInfoResultType.d50, GAP_DISTANCE);
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    public static Facet createD50Facet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_D50_YAXIS_LABEL, FACET_TKH_D50_FILTERED,
+                I18N_FACET_TKH_D50_FILTERED_DESCRIPTION);
+    }
+}
\ 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/common/DatacagePairSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,117 @@
+/* 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.common;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.ProtocolUtils;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.artifacts.states.WaterlevelPairSelectState;
+import org.w3c.dom.Element;
+
+/**
+ * Copy of {@link WaterlevelPairSelectState}. We must copy instead of crate an abstraction, else we break the
+ * serialization of {@link WaterlevelPairSelectState}.
+ * State in which the user selects 1 to n pairs of Waterlevels and alikes.
+ */
+public abstract class DatacagePairSelectState extends DefaultState implements FacetTypes {
+
+    private static final long serialVersionUID = 1L;
+
+    /** The log that is used in this state. */
+    private static Logger log = Logger.getLogger(DatacagePairSelectState.class);
+
+    private final String dataId;
+
+    private final String uiProvider;
+
+    /**
+     * Name of the state data this state is responsible for.
+     */
+    public DatacagePairSelectState(final String uiProvider, final String dataId) {
+        this.uiProvider = uiProvider;
+        this.dataId = dataId;
+    }
+
+    /** Specify to display a datacage_twin_panel. */
+    @Override
+    protected final String getUIProvider() {
+        return this.uiProvider;
+    }
+
+    /**
+     * Overridden to do nothing.
+     */
+    @Override
+    public final Object computeAdvance(final D4EArtifact artifact, final String hash, final CallContext context, final List<Facet> facets, final Object old) {
+        // Get data and do stuff, do not calculate
+        return "";
+    }
+
+    /**
+     * Create elements for document (prepopulated with data, if any).
+     *
+     * @param artifact
+     *            D4EArtifact to get data from.
+     * @param name
+     *            DataName, expceted to be dataId given in constructor.
+     */
+    @Override
+    protected final Element[] createItems(final ElementCreator cr, final Artifact artifact, final String name, final CallContext context) {
+        log.debug("createItems: " + name);
+
+        if (name.equals(this.dataId)) {
+            final Element item = ProtocolUtils.createArtNode(cr, "item", null, null);
+            final Element label = ProtocolUtils.createArtNode(cr, "label", null, null);
+            final Element value = ProtocolUtils.createArtNode(cr, "value", null, null);
+
+            final D4EArtifact flys = (D4EArtifact) artifact;
+
+            final String s = flys.getDataAsString(name);
+            value.setTextContent(s);
+            item.appendChild(label);
+            item.appendChild(value);
+            return new Element[] { item };
+        }
+
+        return new Element[] {};
+    }
+
+    /**
+     * Creates the data element used for the static part of DESCRIBE document.
+     */
+    @Override
+    protected final Element createStaticData(final D4EArtifact flys, final ElementCreator creator, final CallContext cc, final String name, final String value,
+            final String type) {
+        final Element dataElement = creator.create("data");
+        creator.addAttr(dataElement, "name", name, true);
+        creator.addAttr(dataElement, "type", type, true);
+
+        final Element itemElement = creator.create("item");
+        creator.addAttr(itemElement, "value", value, true);
+
+        final String[] labels = WaterlevelPairSelectState.getLabels(cc, value);
+        final Object[] obj = new Object[] { labels[0] };
+
+        final String attrValue = Resources.getMsg(cc.getMeta(), "wsp.selected.string", "wsp.selected.string", obj);
+
+        creator.addAttr(itemElement, "label", attrValue, true);
+        dataElement.appendChild(itemElement);
+
+        return dataElement;
+    }
+}
\ 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/common/FlowDepthDevelopmentPerYearProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,81 @@
+/* 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class FlowDepthDevelopmentPerYearProcessor extends AbstractSInfoProcessor {
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flow_depth_development_per_year.section.yaxis.label";
+
+    private static final String SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_YAXIS_LABEL = "sinfo.chart.flow_depth_development_per_year.yaxis.label";
+
+    /* Theme name, usually defined in 'FacetTypes', but that is soooo bad dependencies... */
+    // REMARK: these must end with 'filtered' so extra handling happens in chart: point are always recalculated, because
+    // data
+    // changes depending on zoom state
+
+    public static final String FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_FILTERED = "sinfo_facet_flow_depth_development_per_year.filtered";
+
+    private static final String FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth_development_per_year.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_RAW = "sinfo_facet_flow_depth_development_per_year";
+
+    private static final String FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_RAW_DESCRIPTION = "sinfo.facet.flow_depth_development_per_year.raw.description";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_RAW);
+    }
+
+    public FlowDepthDevelopmentPerYearProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    protected SInfoResultType doGetType(final String facetName) {
+
+        if (FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepthDevelopmentPerYear;
+        if (FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepthDevelopmentPerYear;
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    public static Facet createFlowDepthDevelopmentFilteredFacet(final CallContext context, final String hash, final String id,
+            final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_YAXIS_LABEL,
+                FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_FILTERED, FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthDevelopmentRawFacet(final CallContext context, final String hash, final String id,
+            final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_YAXIS_LABEL,
+                FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_RAW, FACET_FLOW_DEPTH_DEVELOPMENT_PER_YEAR_RAW_DESCRIPTION);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), GAP_DISTANCE);
+    }
+}
\ 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/common/FlowDepthDevelopmentProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,114 @@
+/* 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class FlowDepthDevelopmentProcessor extends AbstractSInfoProcessor {
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flow_depth_development.section.yaxis.label";
+
+    private static final String SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_YAXIS_LABEL = "sinfo.chart.flow_depth_development.yaxis.label";
+
+    /* Theme name, usually defined in 'FacetTypes', but that is soooo bad dependencies... */
+    // REMARK: these must end with 'filtered' so extra handling happens in chart: point are always recalculated, because
+    // data changes depending on zoom state
+    public static final String FACET_FLOW_DEPTH_DEVELOPMENT_FILTERED = "sinfo_facet_flow_depth_development.filtered";
+
+    private static final String FACET_FLOW_DEPTH_DEVELOPMENT_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth_development.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_DEVELOPMENT_RAW = "sinfo_facet_flow_depth_development";
+
+    private static final String FACET_FLOW_DEPTH_DEVELOPMENT_RAW_DESCRIPTION = "sinfo.facet.flow_depth_development.raw.description";
+
+    public static final String FACET_WATERLEVEL_DIFFERENCE_FILTERED = "sinfo_facet_waterlevel_difference.filtered";
+
+    private static final String FACET_WATERLEVEL_DIFFERENCE_FILTERED_DESCRIPTION = "sinfo.facet.waterlevel_difference.filtered.description";
+
+    public static final String FACET_BEDHEIGHT_DIFFERENCE_FILTERED = "sinfo_facet_bedheight_difference.filtered";
+
+    private static final String FACET_BEDHEIGHT_DIFFERENCE_FILTERED_DESCRIPTION = "sinfo.facet.bedheight_difference.filtered.description";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_DEVELOPMENT_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_DEVELOPMENT_RAW);
+        HANDLED_FACET_TYPES.add(FACET_WATERLEVEL_DIFFERENCE_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_BEDHEIGHT_DIFFERENCE_FILTERED);
+    }
+
+    public FlowDepthDevelopmentProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    protected SInfoResultType doGetType(final String facetName) {
+
+        if (FACET_FLOW_DEPTH_DEVELOPMENT_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepthDevelopment;
+        if (FACET_FLOW_DEPTH_DEVELOPMENT_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepthDevelopment;
+
+        if (FACET_WATERLEVEL_DIFFERENCE_FILTERED.contentEquals(facetName))
+            return SInfoResultType.waterlevelDifference;
+
+        if (FACET_BEDHEIGHT_DIFFERENCE_FILTERED.contentEquals(facetName))
+            return SInfoResultType.bedHeightDifference;
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    public static Facet createFlowDepthDevelopmentFilteredFacet(final CallContext context, final String hash, final String id,
+            final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_YAXIS_LABEL,
+                FACET_FLOW_DEPTH_DEVELOPMENT_FILTERED, FACET_FLOW_DEPTH_DEVELOPMENT_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthDevelopmentRawFacet(final CallContext context, final String hash, final String id,
+            final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_YAXIS_LABEL,
+                FACET_FLOW_DEPTH_DEVELOPMENT_RAW, FACET_FLOW_DEPTH_DEVELOPMENT_RAW_DESCRIPTION);
+    }
+
+    public static Facet createWaterlevelDifferenceFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        final String facetFlowDepthTkhFilteredDescription = Resources.getMsg(context.getMeta(), FACET_WATERLEVEL_DIFFERENCE_FILTERED_DESCRIPTION,
+                FACET_WATERLEVEL_DIFFERENCE_FILTERED_DESCRIPTION, result.getLabel());
+        return new SInfoResultFacet(index, FACET_WATERLEVEL_DIFFERENCE_FILTERED, facetFlowDepthTkhFilteredDescription,
+                SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_YAXIS_LABEL, ComputeType.ADVANCE, id, hash);
+    }
+
+    public static Facet createBedHeightDifferenceFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+
+        final String facetFlowDepthFilteredDescription = Resources.getMsg(context.getMeta(), FACET_BEDHEIGHT_DIFFERENCE_FILTERED_DESCRIPTION,
+                FACET_BEDHEIGHT_DIFFERENCE_FILTERED_DESCRIPTION, result.getLabel());
+        return new SInfoResultFacet(index, FACET_BEDHEIGHT_DIFFERENCE_FILTERED, facetFlowDepthFilteredDescription,
+                SINFO_CHART_FLOW_DEPTH_DEVELOPMENT_YAXIS_LABEL, ComputeType.ADVANCE, id, hash);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), null);
+    }
+}
\ 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/common/FlowDepthProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,221 @@
+/* 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class FlowDepthProcessor extends AbstractSInfoProcessor {
+
+    private static final String AXIS_LABEL = "sinfo.chart.flow_depth.section.yaxis.label";
+
+    private static final String SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL = "sinfo.chart.flow_depth.yaxis.label";
+
+    /* Theme name, usually defined in 'FacetTypes', but that is soooo bad dependencies... */
+    // REMARK: these mustend with 'filtered' so extra handling happens in chart: point are always recalculated, because data
+    // changes depending on zoom state
+
+    /* flow depth */
+    public static final String FACET_FLOW_DEPTH_FILTERED = "sinfo_facet_flow_depth.filtered";
+
+    private static final String FACET_FLOW_DEPTH_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_RAW = "sinfo_facet_flow_depth";
+
+    private static final String FACET_FLOW_DEPTH_RAW_DESCRIPTION = "sinfo.facet.flow_depth.raw.description";
+
+    /* flow depth with tkh */
+    private static final String FACET_FLOW_DEPTH_TKH_FILTERED = "sinfo_facet_flow_depth_with_tkh.filtered";
+
+    private static final String FACET_FLOW_DEPTH_TKH_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth_with_tkh.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_TKH_RAW = "sinfo_facet_flow_depth_with_tkh";
+
+    private static final String FACET_FLOW_DEPTH_TKH_RAW_DESCRIPTION = "sinfo.facet.flow_depth_with_tkh.raw.description";
+
+    /* minimal flow depth */
+    public static final String FACET_FLOW_DEPTH_MIN_FILTERED = "sinfo_facet_flow_depth_min.filtered";
+
+    private static final String FACET_FLOW_DEPTH_MIN_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth_min.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_MIN_RAW = "sinfo_facet_flow_depth_min";
+
+    private static final String FACET_FLOW_DEPTH_MIN_RAW_DESCRIPTION = "sinfo.facet.flow_depth_min.raw.description";
+
+    /* maximal flow depth */
+    public static final String FACET_FLOW_DEPTH_MAX_FILTERED = "sinfo_facet_flow_depth_max.filtered";
+
+    private static final String FACET_FLOW_DEPTH_MAX_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth_max.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_MAX_RAW = "sinfo_facet_flow_depth_max";
+
+    private static final String FACET_FLOW_DEPTH_MAX_RAW_DESCRIPTION = "sinfo.facet.flow_depth_max.raw.description";
+
+    /* current flow depth */
+    public static final String FACET_FLOW_DEPTH_CURRENT_FILTERED = "sinfo_facet_flow_depth_current.filtered";
+
+    private static final String FACET_FLOW_DEPTH_CURRENT_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth_current.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_CURRENT_RAW = "sinfo_facet_flow_depth_current";
+
+    private static final String FACET_FLOW_DEPTH_CURRENT_RAW_DESCRIPTION = "sinfo.facet.flow_depth_current.raw.description";
+
+    /* historical flow depth */
+    public static final String FACET_FLOW_DEPTH_HISTORICAL_FILTERED = "sinfo_facet_flow_depth_historical.filtered";
+
+    private static final String FACET_FLOW_DEPTH_HISTORICAL_FILTERED_DESCRIPTION = "sinfo.facet.flow_depth_historical.filtered.description";
+
+    public static final String FACET_FLOW_DEPTH_HISTORICAL_RAW = "sinfo_facet_flow_depth_historical";
+
+    private static final String FACET_FLOW_DEPTH_HISTORICAL_RAW_DESCRIPTION = "sinfo.facet.flow_depth_historical.raw.description";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_RAW);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_TKH_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_TKH_RAW);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_MIN_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_MIN_RAW);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_MAX_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_MAX_RAW);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_CURRENT_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_CURRENT_RAW);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_HISTORICAL_FILTERED);
+        HANDLED_FACET_TYPES.add(FACET_FLOW_DEPTH_HISTORICAL_RAW);
+    }
+
+    public FlowDepthProcessor() {
+        super(AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    protected SInfoResultType doGetType(final String facetName) {
+
+        if (FACET_FLOW_DEPTH_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepth;
+        if (FACET_FLOW_DEPTH_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepth;
+
+        if (FACET_FLOW_DEPTH_TKH_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepthtkh;
+        if (FACET_FLOW_DEPTH_TKH_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepthtkh;
+
+        if (FACET_FLOW_DEPTH_MIN_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepthmin;
+        if (FACET_FLOW_DEPTH_MIN_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepthmin;
+
+        if (FACET_FLOW_DEPTH_MAX_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepthmax;
+        if (FACET_FLOW_DEPTH_MAX_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepthmax;
+
+        if (FACET_FLOW_DEPTH_CURRENT_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepthCurrent;
+        if (FACET_FLOW_DEPTH_CURRENT_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepthCurrent;
+
+        if (FACET_FLOW_DEPTH_HISTORICAL_FILTERED.contentEquals(facetName))
+            return SInfoResultType.flowdepthHistorical;
+        if (FACET_FLOW_DEPTH_HISTORICAL_RAW.contentEquals(facetName))
+            return SInfoResultType.flowdepthHistorical;
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    public static Facet createFlowDepthFilteredFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_FILTERED,
+                FACET_FLOW_DEPTH_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthRawFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_RAW,
+                FACET_FLOW_DEPTH_RAW_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthTkhFilteredFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_TKH_FILTERED,
+                FACET_FLOW_DEPTH_TKH_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthTkhRawFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_TKH_RAW,
+                FACET_FLOW_DEPTH_TKH_RAW_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthMinFilteredFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_MIN_FILTERED,
+                FACET_FLOW_DEPTH_MIN_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthMinRawFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_MIN_RAW,
+                FACET_FLOW_DEPTH_MIN_RAW_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthMaxFilteredFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_MAX_FILTERED,
+                FACET_FLOW_DEPTH_MAX_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthMaxRawFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_MAX_RAW,
+                FACET_FLOW_DEPTH_MAX_RAW_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthCurrentFilteredFacet(final CallContext context, final String hash, final String id,
+            final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_CURRENT_FILTERED,
+                FACET_FLOW_DEPTH_CURRENT_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthCurrentRawFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_CURRENT_RAW,
+                FACET_FLOW_DEPTH_CURRENT_RAW_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthHistoricalFilteredFacet(final CallContext context, final String hash, final String id,
+            final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_HISTORICAL_FILTERED,
+                FACET_FLOW_DEPTH_HISTORICAL_FILTERED_DESCRIPTION);
+    }
+
+    public static Facet createFlowDepthHistoricalRawFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_FLOW_DEPTH_YAXIS_LABEL, FACET_FLOW_DEPTH_HISTORICAL_RAW,
+                FACET_FLOW_DEPTH_HISTORICAL_RAW_DESCRIPTION);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), GAP_DISTANCE);
+    }
+}
\ 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/common/GaugeDischargeValuesFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,120 @@
+/** 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.common;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.model.DischargeTable;
+import org.dive4elements.river.model.DischargeTableValue;
+import org.dive4elements.river.model.Gauge;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Loading and search/interpolation of a gauge's discharge table (.at)
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class GaugeDischargeValuesFinder {
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(GaugeDischargeValuesFinder.class);
+
+    private final Gauge gauge;
+
+    private Calculation problems;
+
+    private final UnivariateRealFunction wInterpolator;
+
+    private final DoubleRange wRange;
+
+
+    /***** CONSTRUCTORS *****/
+
+    private GaugeDischargeValuesFinder(final Gauge gauge, final Calculation problems, final DischargeTable dischargeTable) {
+        // Load W-Q-values from database
+        this.gauge = gauge;
+        this.problems = problems;
+        final TDoubleArrayList ws = new TDoubleArrayList();
+        final TDoubleArrayList qs = new TDoubleArrayList();
+        for (final DischargeTableValue v : DischargeTable.fetchValuesSortedByW(dischargeTable)) {
+            ws.add(v.getW().doubleValue());
+            qs.add(v.getQ().doubleValue());
+        }
+        // Build interpolator
+        if (ws.size() >= 2) {
+            this.wInterpolator = new LinearInterpolator().interpolate(ws.toNativeArray(), qs.toNativeArray());
+            this.wRange = new DoubleRange(ws.get(0), ws.get(ws.size() - 1));
+        }
+        else {
+            this.wInterpolator = null;
+            this.wRange = null;
+        }
+        if ((this.wInterpolator == null) && (this.problems != null)) {
+            this.problems.addProblem("gauge_discharge_table.missing", gauge.getName());
+            // Report only once
+            this.problems = null;
+        }
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the the main discharge table of a gauge ({gauge}.at)
+     *
+     * @return The discharge table values finder of the gauge, or null
+     */
+    public static GaugeDischargeValuesFinder loadValues(final Gauge gauge, final Calculation problems) {
+        final DischargeTable table = gauge.fetchMasterDischargeTable();
+        if ((table == null) || (table.getDischargeTableValues().size() == 0)) {
+            problems.addProblem("gauge_discharge_table.missing", gauge.getName());
+            return null;
+        }
+        else
+            return new GaugeDischargeValuesFinder(gauge, problems, table);
+    }
+
+    /**
+     * If this provider may return valid data at all.
+     */
+    public boolean isValid() {
+        return (this.wInterpolator != null);
+    }
+
+    /**
+     * Discharge for a W
+     *
+     * @param w
+     *            W in cm above gauge datum
+     * @return Q, or NegInf for w less than all, or PosInf for w greater then all, or NaN in case of exception
+     */
+    public double getDischarge(final double w) {
+        try {
+            if (this.wInterpolator == null)
+                return Double.NaN;
+            else if (w < this.wRange.getMinimumDouble())
+                return Double.NEGATIVE_INFINITY;
+            else if (w > this.wRange.getMaximumDouble())
+                return Double.POSITIVE_INFINITY;
+            else
+                return this.wInterpolator.value(w);
+        }
+        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
+            // ignore exception because this can/will happen regularly
+            return Double.NaN;
+        }
+    }
+}
\ 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/common/GaugeDurationValuesFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,155 @@
+/** 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.common;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Search/interpolation of the duration main values of a gauge
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class GaugeDurationValuesFinder {
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class);
+
+    private final Gauge gauge;
+
+    private Calculation problems;
+
+    private UnivariateRealFunction qInterpolator;
+
+    private DoubleRange qRange;
+
+    private UnivariateRealFunction durInterpolator;
+
+    private DoubleRange durRange;
+
+    private final String approxPrefix = "\u2248";// "ca.";
+
+    /***** CONSTRUCTORS *****/
+
+    private GaugeDurationValuesFinder(final Gauge gauge, final Calculation problems) {
+        // Load the duration main values from the database (each duration has a Q)
+        this.gauge = gauge;
+        this.problems = problems;
+        final TDoubleArrayList qs = new TDoubleArrayList();
+        final TDoubleArrayList durs = new TDoubleArrayList();
+        for (final MainValue v : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.DURATION)) {
+            qs.add(v.getValue().doubleValue());
+            durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
+        }
+        // Build the duration-by-Q interpolator
+        try {
+            this.qInterpolator = new LinearInterpolator().interpolate(qs.toNativeArray(), durs.toNativeArray());
+            this.qRange = new DoubleRange(qs.get(0), qs.get(qs.size() - 1));
+        }
+        catch (final Exception e) {
+            this.qInterpolator = null;
+            this.qRange = null;
+        }
+        // Load the Q values by duration from the database
+        qs.clear();
+        durs.clear();
+        for (final MainValue v : MainValue.getDurationDischargesOfGauge(gauge)) {
+            durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
+            qs.add(v.getValue().doubleValue());
+        }
+        // Build the Q-by-duration interpolator
+        try {
+            this.durInterpolator = new LinearInterpolator().interpolate(durs.toNativeArray(), qs.toNativeArray());
+            this.durRange = new DoubleRange(durs.get(0), durs.get(durs.size() - 1));
+        }
+        catch (final Exception e) {
+            this.durInterpolator = null;
+            this.durRange = null;
+        }
+        // Report problems
+        if (((this.qInterpolator == null) || (this.durInterpolator == null)) && (this.problems != null)) {
+            this.problems.addProblem("gauge_duration.missing", gauge.getName());
+            // Report only once
+            this.problems = null;
+        }
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the the discharge-duration table of a gauge ({gauge}.sta)
+     *
+     * @return The main values finder of a a gauge, or null
+     */
+    public static GaugeDurationValuesFinder loadValues(final Gauge gauge, final Calculation problems) {
+        return new GaugeDurationValuesFinder(gauge, problems);
+    }
+
+    /**
+     * If this provider may return valid data at all.
+     */
+    public boolean isValid() {
+        return (this.qInterpolator != null);
+    }
+
+    /**
+     * Discharge for a duration
+     *
+     * @return Q, or NegInf for duration less than all, or PosInf for duration greater then all, or NaN in case of exception
+     */
+    public double getDischarge(final int duration) {
+        try {
+            if (this.durInterpolator == null)
+                return Double.NaN;
+            else if (duration < this.durRange.getMinimumDouble())
+                return Double.NEGATIVE_INFINITY;
+            else if (duration > this.durRange.getMaximumDouble())
+                return Double.POSITIVE_INFINITY;
+            else
+                return this.durInterpolator.value(duration);
+        }
+        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
+            // ignore exception because this can/will happen regularly
+            return Double.NaN;
+        }
+    }
+
+    /**
+     * Duration for a discharge
+     *
+     * @return duration, or 0 for Q less than all, or 365 for duration greater then all, or -1 in case of exception
+     */
+    public double getDuration(final double q) {
+        try {
+            if (this.qInterpolator == null)
+                return -1;
+            else if (q < this.qRange.getMinimumDouble())
+                return 0;
+            else if (q > this.qRange.getMaximumDouble())
+                return 365;
+            else
+                return this.qInterpolator.value(q);
+        }
+        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
+            // ignore exception because this can/will happen regularly
+            return -1;
+        }
+    }
+}
\ 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/common/GaugeMainValueFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,240 @@
+/** 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.common;
+
+import java.util.Map.Entry;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+
+/**
+ * Loading the main values of a gauge to find relative positions of a value and build a corresponding zone name
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class GaugeMainValueFinder {
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(GaugeMainValueNameFinder.class);
+
+    private final Gauge gauge;
+
+    private Calculation problems;
+
+    private final NavigableMap<Double, MainValue> mainValues;
+
+    private final MainValueTypeKey keyType;
+
+    private final String approxPrefix = "\u2248";
+
+    private Entry<Double, MainValue> foundCeiling;
+
+    private Entry<Double, MainValue> foundFloor;
+
+    private double foundRelativeDistance;
+
+
+    /***** CONSTRUCTORS *****/
+
+    private GaugeMainValueFinder(final MainValueTypeKey keyType, final Gauge gauge, final Calculation problems) {
+        this.gauge = gauge;
+        this.problems = problems;
+        this.keyType = keyType;
+        this.mainValues = new TreeMap<>();
+        for (final MainValue mainValue : MainValue.getValuesOfGaugeAndType(gauge, keyType))
+            this.mainValues.put(Double.valueOf(mainValue.getValue().doubleValue()), mainValue);
+        if (this.mainValues.isEmpty() && (this.problems != null)) {
+            this.problems.addProblem("gauge_main_values.missing", gauge.getName());
+            // Report only once
+            this.problems = null;
+        }
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the the main values table of a type and a gauge (GAUGE.sta)
+     *
+     * @return The main values finder of a type and a gauge, or null
+     */
+    public static GaugeMainValueFinder loadValues(final MainValueTypeKey type, final Gauge gauge, final Calculation problems) {
+        return new GaugeMainValueFinder(type, gauge, problems);
+    }
+
+    /**
+     * If this provider may return valid data at all.
+     */
+    public boolean isValid() {
+        return (this.mainValues != null);
+    }
+
+    /**
+     * Searches the main value zone for a value, and returns a textual description of the zone
+     * (name for an exact match, circa expression for +/- 10% match, less-than/between/greater-than expression otherwise)
+     */
+    public String findZoneName(final double value) {
+        this.findValue(value);
+        if (Double.isNaN(this.foundRelativeDistance))
+            return "";
+
+        // Clearly below or just (max. 10%) below lowest named value
+        if (this.foundFloor == null) {
+            if (Double.isInfinite(this.foundRelativeDistance))
+                return "<" + this.foundCeiling.getValue().getMainValue().getName();
+            else
+                return this.approxPrefix + this.foundCeiling.getValue().getMainValue().getName();
+        }
+
+        // Clearly above or just (max. 10%) above highest named value
+        if (this.foundCeiling == null) {
+            if (Double.isInfinite(this.foundRelativeDistance))
+                return ">" + this.foundFloor.getValue().getMainValue().getName();
+            else
+                return this.approxPrefix + this.foundFloor.getValue().getMainValue().getName();
+        }
+
+        // Exact match
+        if (this.mainValues.containsKey(Double.valueOf(value)))
+            return this.mainValues.get(Double.valueOf(value)).getMainValue().getName();
+
+        // Near (10%) one of the borders of a zone interval, or clearly within a zone
+        if (this.foundRelativeDistance <= 0.001)
+            return this.foundFloor.getValue().getMainValue().getName();
+        else if (this.foundRelativeDistance <= 0.1)
+            return this.approxPrefix + this.foundFloor.getValue().getMainValue().getName();
+        else if (this.foundRelativeDistance >= 0.9)
+            return this.approxPrefix + this.foundCeiling.getValue().getMainValue().getName();
+        else
+            return this.foundFloor.getValue().getMainValue().getName() + "-" + this.foundCeiling.getValue().getMainValue().getName();
+    }
+
+    /**
+     * Searches the main value zone for a value, and returns the zone name for an exact match, the nomatchReturn otherwise
+     */
+    public String findExactZoneName(final double value, final String noMatchReturn) {
+        this.findValue(value);
+        if ((this.foundFloor != null) && (this.foundFloor.getKey() == this.foundCeiling.getKey()))
+            return this.foundFloor.getValue().getMainValue().getName();
+        else
+            return noMatchReturn;
+    }
+
+    /**
+     * Searches the interval of a main value and its relative distance from the lower value
+     */
+    public boolean findValue(final double value) {
+        this.foundFloor = null;
+        this.foundCeiling = null;
+        this.foundRelativeDistance = Double.NaN;
+        if (!this.isValid())
+            return false;
+        if (Double.isNaN(value))
+            return false;
+
+        // Clearly below or just (max. 10%) below lowest named value
+        this.foundFloor = this.mainValues.floorEntry(Double.valueOf(value));
+        if (this.foundFloor == null) {
+            this.foundCeiling = this.mainValues.firstEntry();
+            if (value >= this.mainValues.firstKey().doubleValue() * 0.9) {
+                this.foundRelativeDistance = 0.9;
+                return true;
+            }
+            else {
+                this.foundRelativeDistance = Double.NEGATIVE_INFINITY;
+                return false;
+            }
+        }
+
+        // Clearly above or just (max. 10%) above highest named value
+        this.foundCeiling = this.mainValues.ceilingEntry(Double.valueOf(value));
+        if (this.foundCeiling == null) {
+            if (value <= this.mainValues.lastKey().doubleValue() * 1.1) {
+                this.foundRelativeDistance = 0.1;
+                return true;
+            }
+            else {
+                this.foundRelativeDistance = Double.POSITIVE_INFINITY;
+                return false;
+            }
+        }
+
+        // Exact match or within an interval
+        if (this.foundCeiling.getKey() == this.foundFloor.getKey())
+            this.foundRelativeDistance = 0.0;
+        else
+            this.foundRelativeDistance = (value - this.foundFloor.getKey().doubleValue())
+            / (this.foundCeiling.getKey().doubleValue() - this.foundFloor.getKey().doubleValue());
+        return true;
+    }
+
+    /**
+     * Floor value of the last findValue
+     */
+    public MainValue getFoundFloorValue() {
+        if (this.foundFloor != null)
+            return this.foundFloor.getValue();
+        else
+            return null;
+    }
+
+    /**
+     * Ceiling value of the last findValue
+     */
+    public MainValue getFoundCeilingValue() {
+        if (this.foundCeiling != null)
+            return this.foundCeiling.getValue();
+        else
+            return null;
+    }
+
+    /**
+     * Relative distance of the last findValue
+     */
+    public double getFoundRelativeDistance() {
+        return this.getFoundRelativeDistance();
+    }
+
+    /**
+     * Searches a pair of zone names and return the a value within the interval by a relative distance, or NaN
+     */
+    public double findValue(final String floorZone, final String ceilingZone, final double relativeDistance) {
+        this.foundFloor = null;
+        this.foundCeiling = null;
+        this.foundRelativeDistance = relativeDistance;
+        for (final Entry<Double, MainValue> mainValue : this.mainValues.entrySet()) {
+            if (mainValue.getValue().getMainValue().getName().equalsIgnoreCase(floorZone)) {
+                this.foundFloor = mainValue;
+                break;
+            }
+        }
+        if (this.foundFloor == null)
+            return Double.NaN;
+        if (floorZone.equalsIgnoreCase(ceilingZone))
+            return this.foundFloor.getKey().doubleValue();
+        for (final Entry<Double, MainValue> mainValue : this.mainValues.entrySet()) {
+            if (mainValue.getValue().getMainValue().getName().equalsIgnoreCase(ceilingZone)) {
+                this.foundCeiling = mainValue;
+                break;
+            }
+        }
+        if (this.foundCeiling == null)
+            return Double.NaN;
+        else
+            return (this.foundCeiling.getKey().doubleValue() - this.foundFloor.getKey().doubleValue()) * this.foundRelativeDistance
+                    + this.foundFloor.getKey().doubleValue();
+    }
+}
\ 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/common/InfrastructureHeightProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,60 @@
+/** 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.flood_duration.InfrastructureFacet;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for infrastructure height data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class InfrastructureHeightProcessor extends AbstractSInfoProcessor {
+
+    // private final static Logger log = Logger.getLogger(InfrastructureHeightProcessor.class);
+
+    public static final String FACET_INFRASTRUCTURE_HEIGHT = "sinfo_facet_infrastructure_height";
+
+    private static final String I18N_AXIS_LABEL = "chart.longitudinal.section.yaxis.label";
+
+    private static final String I18N_SERIES_NAME_PATTERN = "infrastructure.height.title";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_INFRASTRUCTURE_HEIGHT);
+    }
+
+    public InfrastructureHeightProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, SInfoResultType.infrastructureHeight, null);
+    }
+
+    public static Facet createFacet(final CallMeta callMeta, final String seriesName) {
+        return new InfrastructureFacet(FACET_INFRASTRUCTURE_HEIGHT, Resources.getMsg(callMeta, I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, seriesName),
+                I18N_AXIS_LABEL);
+    }
+}
\ 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/common/PredefinedChannelDepthProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,60 @@
+/** 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.predefinedchannel.PredefinedChannelFacet;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for river channel depth data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedChannelDepthProcessor extends AbstractSInfoProcessor {
+
+    // private final static Logger log = Logger.getLogger(PredefinedChannelDepthProcessor.class);
+
+    public static final String FACET_PREDEFINED_CHANNEL_DEPTH = "sinfo_facet_predefined_channel_depth";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flow_depth.section.yaxis.label";
+
+    private static final String I18N_SERIES_NAME_PATTERN = "predefinedchannel.depth.title";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_PREDEFINED_CHANNEL_DEPTH);
+    }
+
+    public PredefinedChannelDepthProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    public static Facet createFacet(final CallMeta callMeta, final String seriesName) {
+        return new PredefinedChannelFacet(FACET_PREDEFINED_CHANNEL_DEPTH,
+                Resources.getMsg(callMeta, I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, seriesName), I18N_AXIS_LABEL);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, SInfoResultType.collisionCount, null);
+    }
+}
\ 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/common/PredefinedChannelWidthProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,61 @@
+/** 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.predefinedchannel.PredefinedChannelFacet;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for river channel width data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedChannelWidthProcessor extends AbstractSInfoProcessor {
+
+    // private final static Logger log = Logger.getLogger(PredefinedChannelWidthProcessor.class);
+
+    public static final String FACET_PREDEFINED_CHANNEL_WIDTH = "sinfo_facet_predefined_channel_width";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.channel_width.section.yaxis.label";
+
+    private static final String I18N_SERIES_NAME_PATTERN = "predefinedchannel.width.title";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_PREDEFINED_CHANNEL_WIDTH);
+    }
+
+    public PredefinedChannelWidthProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, SInfoResultType.channelWidth, null);
+    }
+
+    public static Facet createFacet(final CallMeta callMeta, final String seriesName) {
+        return new PredefinedChannelFacet(FACET_PREDEFINED_CHANNEL_WIDTH,
+                Resources.getMsg(callMeta, I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, seriesName), I18N_AXIS_LABEL);
+    }
+
+}
\ 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/common/PredefinedDepthEvolPerYearProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,60 @@
+/** 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.predefineddepthevol.PredefinedDepthEvolFacet;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for depth evolution per year data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedDepthEvolPerYearProcessor extends AbstractSInfoProcessor {
+
+    // private final static Logger log = Logger.getLogger(PredefinedDepthEvolPerYearProcessor.class);
+
+    public static final String FACET_PREDEFINED_DEPTHEVOL_PER_YEAR = "sinfo_facet_predefined_depthevol_per_year";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flow_depth_development_per_year.section.yaxis.label";
+
+    private static final String I18N_SERIES_NAME_PATTERN = "predefineddepthevol.peryear.title";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_PREDEFINED_DEPTHEVOL_PER_YEAR);
+    }
+
+    public PredefinedDepthEvolPerYearProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, SInfoResultType.flowdepthDevelopmentPerYear, null);
+    }
+
+    public static Facet createFacet(final CallMeta callMeta, final String seriesName) {
+        return new PredefinedDepthEvolFacet(FACET_PREDEFINED_DEPTHEVOL_PER_YEAR,
+                Resources.getMsg(callMeta, I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, seriesName), I18N_AXIS_LABEL);
+    }
+}
\ 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/common/PredefinedDepthEvolProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,60 @@
+/** 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.predefineddepthevol.PredefinedDepthEvolFacet;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for depth evolution data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedDepthEvolProcessor extends AbstractSInfoProcessor {
+
+    // private final static Logger log = Logger.getLogger(PredefinedDepthEvolProcessor.class);
+
+    public static final String FACET_PREDEFINED_DEPTHEVOL = "sinfo_facet_predefined_depthevol";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flow_depth_development.section.yaxis.label";
+
+    private static final String I18N_SERIES_NAME_PATTERN = "predefineddepthevol.total.title";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_PREDEFINED_DEPTHEVOL);
+    }
+
+    public PredefinedDepthEvolProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForType(generator, bundle, theme, visible, SInfoResultType.flowdepthDevelopment, null);
+    }
+
+    public static Facet createFacet(final CallMeta callMeta, final String seriesName) {
+        return new PredefinedDepthEvolFacet(FACET_PREDEFINED_DEPTHEVOL,
+                Resources.getMsg(callMeta, I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, seriesName), I18N_AXIS_LABEL);
+    }
+}
\ 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/common/PredefinedFlowDepthProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,74 @@
+/** 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.common;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.exports.StyledSeriesBuilder;
+import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for flow depth data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedFlowDepthProcessor extends AbstractSInfoProcessor {
+
+    public static final String FACET_PREDEFINED_FLOW_DEPTH = "sinfo_facet_predefined_flowdepth";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flow_depth.section.yaxis.label";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_PREDEFINED_FLOW_DEPTH);
+    }
+
+    public PredefinedFlowDepthProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+        // TOO MANY DIFFERENCES TO super.buildSeriesForTkh(generator, bundle, theme, visible);
+        final CallContext context = generator.getContext();
+        final Map<String, String> metaData = bundle.getFacet().getMetaData();
+
+        final Artifact artifact = bundle.getArtifact();
+
+        final StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+        series.putMetaData(metaData, artifact, context);
+
+        final String facetName = bundle.getFacetName();
+        final AbstractCalculationResult data = (AbstractCalculationResult) bundle.getData(context);
+        if (data == null) {
+            // Check has been here before so we keep it for security reasons
+            // this should never happen though.
+            throw new IllegalStateException("Data is null for facet: " + facetName);
+        }
+
+        final double[][] points = data.getStationPoints(SInfoResultType.flowdepth);
+
+        StyledSeriesBuilder.addPoints(series, points, true);
+        generator.addAxisSeries(series, getAxisName(), visible);
+
+        return null;
+    }
+}
\ 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/common/PredefinedTkhProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,47 @@
+/** 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate a data series for tkh data loaded from the database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedTkhProcessor extends AbstractSInfoProcessor {
+
+    public static final String FACET_PREDEFINED_TKH = "sinfo_facet_predefined_tkh";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.tkh.section.yaxis.label";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_PREDEFINED_TKH);
+    }
+
+    public PredefinedTkhProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+        return buildSeriesForTkh(generator, bundle, theme, visible);
+
+    }
+}
\ 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/common/RiverInfoProvider.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,127 @@
+/** 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.common;
+
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+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.states.WaterlevelData;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.utils.GaugeIndex;
+
+/**
+ * @author Gernot Belger
+ *
+ */
+public final class RiverInfoProvider {
+
+    private static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range";
+
+    private final River river;
+    private final GaugeIndex gaugeIndex;
+    private final Gauge refGauge;
+    private final boolean showAllGauges;
+    private final String notinrange;
+
+    public static RiverInfoProvider forRange(final CallContext context, final River river, final DoubleRange calcRange) {
+
+        final List<Gauge> gauges = river.determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble());
+        final GaugeIndex gaugeIndex = new GaugeIndex(gauges);
+
+        final String notinrange = Resources.getMsg(context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE);
+
+        return new RiverInfoProvider(notinrange, river, false, gaugeIndex, null);
+    }
+
+    private RiverInfoProvider(final String notinrange, final River river, final boolean showAllGauges, final GaugeIndex gaugeIndex, final Gauge refGauge) {
+        this.notinrange = notinrange;
+        this.river = river;
+        this.showAllGauges = showAllGauges;
+        this.gaugeIndex = gaugeIndex;
+        this.refGauge = refGauge;
+    }
+
+    public RiverInfoProvider forWaterlevel(final WaterlevelData waterlevel) {
+        final WKms wstKms = waterlevel.getWkms();
+        final Gauge waterlevelRefGauge = findReferenceGauge(wstKms);
+        final boolean waterlevelShowAllGauges = waterlevel.isShowAllGauges();
+
+        return new RiverInfoProvider(this.notinrange, this.river, waterlevelShowAllGauges, this.gaugeIndex, waterlevelRefGauge);
+    }
+
+    /**
+     * Re-determines the reference gauge, in the same way as the WaterlevelArtifact would do it
+     */
+    private Gauge findReferenceGauge(final WKms wkms) {
+
+        final double[] wstFromTo = findWstFromTo(wkms);
+        return this.river.determineRefGauge(wstFromTo, true);
+    }
+
+    private static double[] findWstFromTo(final WKms wkms) {
+
+        final double from = wkms.getKm(0);
+        final double to = wkms.getKm(wkms.size() - 1);
+
+        final boolean waterIncreasing = wkms.guessWaterIncreasing();
+        if (waterIncreasing)
+            return new double[] { to, from };
+
+        return new double[] { from, to };
+    }
+
+    public String getLocation(final double km) {
+        return LocationProvider.getLocation(this.river.getName(), km);
+    }
+
+    public String findGauge(final double km) {
+        // REMARK: access the gauge once only during calculation
+        final Gauge gauge = getGauge(km);
+
+        return gauge == null ? this.notinrange : gauge.getName();
+    }
+
+    public String findGauge(final double km, final boolean allGauges) {
+        // REMARK: access the gauge once only during calculation
+        final Gauge gauge = getGauge(km, allGauges);
+
+        return gauge == null ? this.notinrange : gauge.getName();
+    }
+
+    private Gauge getGauge(final double km) {
+
+        // REMARK: using same logic as in WaterlevelExporter here
+
+        return getGauge(km, this.showAllGauges);
+    }
+
+    public Gauge getGauge(final double km, final boolean allGauges) {
+        if (allGauges)
+            return this.gaugeIndex.findGauge(km);
+
+        if ((this.refGauge != null) && this.refGauge.getRange().contains(km))
+            return this.refGauge;
+
+        return null;
+    }
+
+    public String getReferenceGauge() {
+        return this.refGauge == null ? this.notinrange : this.refGauge.getName();
+    }
+
+    public River getRiver() {
+        return this.river;
+    }
+}
\ 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/common/SInfoI18NStrings.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,91 @@
+/** 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.common;
+
+/**
+ * Some commonly used i18n-strings.
+ *
+ * @author Gernot Belger
+ */
+public interface SInfoI18NStrings {
+    // TODO: MAKE interface package-visible again:-)
+    // TODO: Strings werden nur einmal verwenden; direkte Verwendung auch denkbar. Liste ist nicht vollständig
+    String CSV_META_HEADER_WATERLEVEL_GAUGE = "sinfo.export.flow_depth.csv.meta.header.waterlevel.gauge";
+
+    String CSV_META_HEADER_WATERLEVEL_YEAR = "sinfo.export.flow_depth.csv.meta.header.waterlevel.year";
+
+    String CSV_MEAN_BED_HEIGHT_HEADER = "sinfo.export.flow_depth.csv.header.mean_bed_height";
+
+    String CSV_MEAN_BED_HEIGHT_HEADER_SHORT = "sinfo.export.flow_depth.csv.header.mean_bed_height.short";
+
+    String CSV_WATERLEVEL_HEADER = "sinfo.export.flow_depth.csv.header.waterlevel";
+
+    String CSV_DISCHARGE_HEADER = "sinfo.export.flow_depth.csv.header.discharge";
+
+    String CSV_LABEL_HEADER = "sinfo.export.flow_depth.csv.header.label";
+
+    String CSV_GAUGE_HEADER = "sinfo.export.flow_depth.csv.header.gauge";
+
+    String CSV_LOCATION_HEADER = "sinfo.export.flow_depth.csv.header.location";
+
+    String CSV_SOUNDING_HEADER = "sinfo.export.flow_depth.csv.header.sounding";
+
+    String CSV_FLOWDEPTH_HEADER = "sinfo.export.flow_depth.csv.header.flowdepth";
+
+    String CSV_FLOWDEPTHTKH_HEADER = "sinfo.export.flow_depth.csv.header.flowdepthTkh";
+
+    String CSV_FLOWDEPTH_MIN_HEADER = "sinfo.export.flow_depth_minmax.csv.header.min";
+
+    String CSV_FLOWDEPTH_MAX_HEADER = "sinfo.export.flow_depth_minmax.csv.header.max";
+
+    String CSV_TKH_HEADER = "sinfo.export.tkh.csv.header.tkh";
+
+    String CSV_TKH_HEADER_SHORT = "sinfo.export.flow_depth.csv.header.tkh";
+
+    String CSV_TKHKIND_HEADER = "sinfo.export.tkh.csv.header.tkhkind";
+
+    String CSV_CHANNEL_WIDTH_HEADER = "sinfo.export.csv.header.channel.width";
+
+    String CSV_CHANNEL_DEPTH_HEADER = "sinfo.export.csv.header.channel.depth";
+
+    String CSV_FLOWDEPTH_DEVELOPMENT_HEADER = "sinfo.export.csv.header.flowdepth.development";
+
+    String PDF_FLOWDEPTH_DEVELOPMENT_HEADER = "sinfo.export.pdf.header.flowdepth.development";
+
+    String CSV_FLOWDEPTH_DEVELOPMENT_PER_YEAR_HEADER = "sinfo.export.csv.header.flowdepth.development.per.year";
+
+    String CSV_WATERLEVEL_DIFFERENCE_HEADER = "sinfo.export.csv.header.waterlevel.difference";
+
+    String CSV_MEAN_BED_HEIGHT_DIFFERENCE_HEADER = "sinfo.export.csv.header.mean_bed_height.difference";
+
+    String CSV_FLOWDEPTH_CURRENT_HEADER = "sinfo.export.csv.header.flowdepth.current";
+
+    String CSV_FLOWDEPTH_HISTORICAL_HEADER = "sinfo.export.csv.header.flowdepth.historical";
+
+    String CSV_META_HEADER_WATERLEVEL = "sinfo.export.flow_depth.csv.meta.header.waterlevel";
+
+    String CSV_META_HEADER_WATERLEVEL_NAME = "sinfo.export.flow_depth.csv.meta.header.waterlevel.name";
+
+    String PREFIX_TKH_KIND = "sinfo.export.tkh.soilkind.";
+
+    String CSV_INFRASTRUCTURE_HEIGHT_HEADER = "sinfo.export.flood_duration.csv.header.infrastructure.height";
+
+    String PDF_INFRASTRUCTURE_HEIGHT_HEADER = "sinfo.export.flood_duration.pdf.header.infrastructure.height";
+
+    String CSV_COLLISION_COUNT_HEADER = "sinfo.export.csv.header.collision.count";
+
+    String CSV_COLLISION_GAUGEW_HEADER = "sinfo.export.csv.header.collision.gaugew";
+
+    String CSV_META_HEADER_YEARS = "sinfo.export.csv.meta.header.years";
+
+    String CSV_YEARS_HEADER = "sinfo.export.csv.header.years";
+
+    String CSV_DISCHARGE_ZONE_HEADER = "sinfo.export.csv.header.discharge.zone";
+}
\ 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/common/SInfoResultFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,79 @@
+/* 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.common;
+
+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.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+/**
+ * Facet of one of the S-Info curves.
+ */
+public class SInfoResultFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger log = Logger.getLogger(SInfoResultFacet.class);
+
+    private int resultIndex;
+
+    public SInfoResultFacet() {
+        // required for clone operation deepCopy()
+    }
+
+    public SInfoResultFacet(final int resultIndex, final String name, final String description, final String yAxisLabelKey, final ComputeType type,
+            final String stateId, final String hash) {
+        this(resultIndex, resultIndex, name, description, yAxisLabelKey, type, stateId, hash);
+    }
+
+    public SInfoResultFacet(final int facetIndex, final int resultIndex, final String name, final String description, final String yAxisLabelKey,
+            final ComputeType type, final String stateId, final String hash) {
+        // REMARK: in some cases, we have several data-lines for the same result (which normally determines the facet index) and
+        // facet name. But index and name are used by the client side as unique keys for the chart themes...
+        // So we might have different facet index and result index.
+        super(facetIndex, name, description, type, hash, stateId);
+        this.resultIndex = resultIndex;
+
+        this.metaData.put("X", "sinfo.chart.km.xaxis.label");
+        this.metaData.put("Y", yAxisLabelKey);
+    }
+
+    @Override
+    public final Object getData(final Artifact artifact, final CallContext context) {
+        log.debug("Get data for result at index: " + this.resultIndex);
+
+        final D4EArtifact flys = (D4EArtifact) artifact;
+
+        final CalculationResult res = (CalculationResult) flys.compute(context, this.hash, this.stateId, this.type, false);
+
+        final AbstractCalculationResults<AbstractCalculationResult> data = (AbstractCalculationResults<AbstractCalculationResult>) res.getData();
+
+        return data.getResults().get(this.resultIndex);
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        // FIXME: why not simply use the full constructor instead?
+        final SInfoResultFacet copy = new SInfoResultFacet();
+        // FIXME: why does DataFacet does not override set? Bad access to variables of parent!
+        copy.set(this);
+        copy.type = this.type;
+        copy.hash = this.hash;
+        copy.stateId = this.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/common/SInfoResultType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,717 @@
+/** 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.common;
+
+import java.text.NumberFormat;
+
+import org.apache.commons.lang.StringUtils;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractResultType;
+import org.dive4elements.river.artifacts.common.I18NStrings;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.SoilKind;
+import org.dive4elements.river.model.Attribute.AttributeKey;
+import org.dive4elements.river.utils.Formatter;
+import org.dive4elements.river.utils.RiverUtils;
+
+/**
+ * Result type for data that goes into {@link SInfoResultRow}s.
+ *
+ * @author Gernot Belger
+ */
+public abstract class SInfoResultType extends AbstractResultType {
+
+    private static final long serialVersionUID = 1L;
+
+    private SInfoResultType(final String unit, final String csvHeader) {
+        super(unit, csvHeader, csvHeader);
+    }
+
+    private SInfoResultType(final String unit, final String csvHeader, final String pdfHeader) {
+        super(unit, csvHeader, pdfHeader);
+    }
+
+    public static final SInfoResultType customMultiRowColWaterlevel = new SInfoResultType(null, SInfoI18NStrings.CSV_WATERLEVEL_HEADER,
+            "sinfo.export.flow_depth.pdf.header.waterlevel") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+
+    };
+
+    public static final SInfoResultType floodDischarge = new SInfoResultType(I18NStrings.UNIT_CUBIC_M, "sinfo.export.flood_duration.csv.header.discharge",
+            "sinfo.export.flood_duration.pdf.header.discharge") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getWaterlevelQ(context);
+        }
+    };
+
+    public static final SInfoResultType floodDuration = new SInfoResultType(null, "sinfo.export.flood_duration.csv.header.duration",
+            "sinfo.export.flood_duration.pdf.header.duration") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getIntegerFormatter(context);
+        }
+    };
+
+    public static final SInfoResultType waterlevel = new SInfoResultType(null, SInfoI18NStrings.CSV_WATERLEVEL_HEADER,
+            "sinfo.export.flow_depth.pdf.header.waterlevel") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of
+            // digits.
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final SInfoResultType waterlevel1 = new SInfoResultType(null, "sinfo.flood_duration.header.mainvalue.1.w",
+            "sinfo.flood_duration.header.pdf.mainvalue.1.w") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final SInfoResultType waterlevel2 = new SInfoResultType(null, "sinfo.flood_duration.header.mainvalue.2.w",
+            "sinfo.flood_duration.header.pdf.mainvalue.2.w") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    // public static final SInfoResultType waterlevel3 = new SInfoResultType(null,
+    // "sinfo.flood_duration.header.mainvalue.3.w",
+    // "sinfo.flood_duration.header.pdf.mainvalue.3.w") {
+    // private static final long serialVersionUID = 1L;
+    //
+    // @Override
+    // public String exportValue(final CallContext context, final Object value) {
+    // final double doubleValue = asDouble(value);
+    // return exportDoubleValue(context, doubleValue);
+    // }
+    //
+    // @Override
+    // protected NumberFormat createFormatter(final CallContext context) {
+    // return Formatter.getFlowDepth(context);
+    // }
+    // };
+
+    public static final SInfoResultType waterlevelLabel = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_LABEL_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType infrastructuretype = new SInfoResultType(I18NStrings.UNIT_NONE,
+            "sinfo.export.flood_duration.csv.header.infrastructure_type", "sinfo.export.flood_duration.pdf.header.infrastructure_type") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType discharge = new SInfoResultType(I18NStrings.UNIT_CUBIC_M, SInfoI18NStrings.CSV_DISCHARGE_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            final double roundedDischarge = RiverUtils.roundQ(doubleValue);
+            return exportDoubleValue(context, roundedDischarge);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getWaterlevelQ(context);
+        }
+    };
+
+    public static final SInfoResultType discharge1 = new SInfoResultType(I18NStrings.UNIT_CUBIC_M, "sinfo.flood_duration.header.mainvalue.1.q",
+            "sinfo.flood_duration.header.pdf.mainvalue.1.q") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            final double roundedDischarge = RiverUtils.roundQ(doubleValue);
+            return exportDoubleValue(context, roundedDischarge);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getWaterlevelQ(context);
+        }
+    };
+
+    public static final SInfoResultType discharge2 = new SInfoResultType(I18NStrings.UNIT_CUBIC_M, "sinfo.flood_duration.header.mainvalue.2.q",
+            "sinfo.flood_duration.header.pdf.mainvalue.2.q") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            final double roundedDischarge = RiverUtils.roundQ(doubleValue);
+            return exportDoubleValue(context, roundedDischarge);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getWaterlevelQ(context);
+        }
+    };
+
+    public static final SInfoResultType discharge3 = new SInfoResultType(I18NStrings.UNIT_CUBIC_M, "sinfo.flood_duration.header.mainvalue.3.q",
+            "sinfo.flood_duration.header.pdf.mainvalue.3.q") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            final double roundedDischarge = RiverUtils.roundQ(doubleValue);
+            return exportDoubleValue(context, roundedDischarge);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getWaterlevelQ(context);
+        }
+    };
+
+    public static final SInfoResultType meanBedHeight = new SInfoResultType(null, SInfoI18NStrings.CSV_MEAN_BED_HEIGHT_HEADER,
+            SInfoI18NStrings.CSV_MEAN_BED_HEIGHT_HEADER_SHORT) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getMeanBedHeight(context);
+        }
+    };
+
+    public static final SInfoResultType soundingLabel = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_SOUNDING_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+    public static final SInfoResultType flowdepthDevelopmentPerYear = new SInfoResultType(I18NStrings.UNIT_CM_A,
+            SInfoI18NStrings.CSV_FLOWDEPTH_DEVELOPMENT_PER_YEAR_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepthDevelopmentPerYear(context);
+        }
+    };
+
+    public static final SInfoResultType flowdepthmin = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_FLOWDEPTH_MIN_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final SInfoResultType flowdepthmax = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_FLOWDEPTH_MAX_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final SInfoResultType riverside = new SInfoResultType(I18NStrings.UNIT_NONE, "sinfo.export.flood_duration.csv.header.riverside") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return localizeRiverside(context, (AttributeKey) value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    /**
+     * Returns the localized text of a riverside
+     * FIXME: Find a better place for this common method
+     */
+    public static final String localizeRiverside(final CallContext context, final AttributeKey riverside) {
+        if (riverside == AttributeKey.LEFT)
+            return Resources.getMsg(context.getMeta(), "riverside.left");
+        else if (riverside == AttributeKey.RIGHT)
+            return Resources.getMsg(context.getMeta(), "riverside.right");
+        else
+            return "?";
+    }
+
+    public static final SInfoResultType gaugeLabel = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_GAUGE_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType location = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_LOCATION_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType soilkind = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_TKHKIND_HEADER,
+            "sinfo.export.tkh.pdf.header.tkhkind") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+
+            if (value == null)
+                return StringUtils.EMPTY;
+
+            final SoilKind kind = (SoilKind) value;
+
+            final String key = SInfoI18NStrings.PREFIX_TKH_KIND + kind.name();
+            return Resources.getMsg(context.getMeta(), key, key);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType flowdepth = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_FLOWDEPTH_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final SInfoResultType d50 = new SInfoResultType(null, null) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType velocity = new SInfoResultType(null, null) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType tau = new SInfoResultType(null, null) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType tkh = new SInfoResultType(I18NStrings.UNIT_CM, SInfoI18NStrings.CSV_TKH_HEADER, SInfoI18NStrings.CSV_TKH_HEADER_SHORT) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getTkh(context);
+        }
+    };
+
+    public static final SInfoResultType tkhup = new SInfoResultType(I18NStrings.UNIT_M, null) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType tkhdown = new SInfoResultType(I18NStrings.UNIT_M, null) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType flowdepthtkh = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_FLOWDEPTHTKH_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final SInfoResultType channelWidth = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_CHANNEL_WIDTH_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getChannelWidth(context);
+        }
+    };
+
+    public static final SInfoResultType channelDepth = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_CHANNEL_DEPTH_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getChannelDepth(context);
+        }
+    };
+
+    public static final SInfoResultType flowdepthDevelopment = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_FLOWDEPTH_DEVELOPMENT_HEADER,
+            SInfoI18NStrings.PDF_FLOWDEPTH_DEVELOPMENT_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getTkh(context);
+        }
+    };
+
+    public static final SInfoResultType depthDevelopmentPerYear = new SInfoResultType(I18NStrings.UNIT_CM_A,
+            SInfoI18NStrings.CSV_FLOWDEPTH_DEVELOPMENT_PER_YEAR_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepthDevelopmentPerYear(context);
+        }
+    };
+    public static final SInfoResultType waterlevelDifference = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_WATERLEVEL_DIFFERENCE_HEADER,
+            "sinfo.export.csv.header.waterlevel.difference") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getTkh(context);
+        }
+    };
+    public static final SInfoResultType bedHeightDifference = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_MEAN_BED_HEIGHT_DIFFERENCE_HEADER,
+            "sinfo.export.csv.header.mean_bed_height.difference") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getTkh(context);
+        }
+    };
+    public static final SInfoResultType flowdepthCurrent = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_FLOWDEPTH_CURRENT_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+    public static final SInfoResultType flowdepthHistorical = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_FLOWDEPTH_HISTORICAL_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final SInfoResultType infrastructureHeight = new SInfoResultType(I18NStrings.UNIT_M, SInfoI18NStrings.CSV_INFRASTRUCTURE_HEIGHT_HEADER,
+            SInfoI18NStrings.PDF_INFRASTRUCTURE_HEIGHT_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getInfrastructureHeight(context);
+        }
+    };
+
+    public static final SInfoResultType collisionCount = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_COLLISION_COUNT_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getCollisionCount(context);
+        }
+    };
+
+    public static final SInfoResultType collisionGaugeW = new SInfoResultType(I18NStrings.UNIT_CM, SInfoI18NStrings.CSV_COLLISION_GAUGEW_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            return Formatter.getCollisionGaugeW(context);
+        }
+    };
+
+    public static final SInfoResultType years = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_YEARS_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final SInfoResultType dischargeZone = new SInfoResultType(I18NStrings.UNIT_NONE, SInfoI18NStrings.CSV_DISCHARGE_ZONE_HEADER) {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+}
\ 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/common/TauProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,61 @@
+/* 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class TauProcessor extends AbstractSInfoProcessor {
+
+    public static final String FACET_TKH_TAU_FILTERED = "sinfo_facet_tau";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.tkh_tau.section.yaxis.label";
+
+    private static final String SINFO_CHART_TAU_YAXIS_LABEL = "sinfo.chart.tkh_tau.yaxis.label";
+
+    private static final String I18N_FACET_TKH_TAU_FILTERED_DESCRIPTION = "sinfo.facet.tkh_tau.description";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_TKH_TAU_FILTERED);
+    }
+
+    public TauProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    protected SInfoResultType doGetType(final String facetName) {
+
+        if (FACET_TKH_TAU_FILTERED.contentEquals(facetName))
+            return SInfoResultType.tau;
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    public static Facet createTauFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result, final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_TAU_YAXIS_LABEL, FACET_TKH_TAU_FILTERED,
+                I18N_FACET_TKH_TAU_FILTERED_DESCRIPTION);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+        return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), GAP_DISTANCE);
+    }
+}
\ 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/common/TkhProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,58 @@
+/* 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class TkhProcessor extends AbstractSInfoProcessor {
+
+    private static String FACET_TKH = "sinfo_facet_tkh";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.tkh.section.yaxis.label";
+
+    private static final String I18N_FACET_TKH_DESCRIPTION = "sinfo.facet.tkh.description";
+
+    private static final String SINFO_CHART_TKX_YAXIS_LABEL = "sinfo.chart.tkh.yaxis.label";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_TKH);
+    }
+
+    public TkhProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        return buildSeriesForTkh(generator, bundle, theme, visible);
+
+    }
+
+    public static Facet createTkhFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result, final int index) {
+
+        final String facetTkhDescription = Resources.getMsg(context.getMeta(), I18N_FACET_TKH_DESCRIPTION, I18N_FACET_TKH_DESCRIPTION, result.getLabel());
+        return new SInfoResultFacet(index, TkhProcessor.FACET_TKH, facetTkhDescription, TkhProcessor.SINFO_CHART_TKX_YAXIS_LABEL, ComputeType.ADVANCE, id,
+                hash);
+    }
+}
\ 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/common/VelocityProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.themes.ThemeDocument;
+
+public final class VelocityProcessor extends AbstractSInfoProcessor {
+
+    public static final String FACET_TKH_VELOCITY_FILTERED = "sinfo_facet_velocity";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.tkh_velocity.section.yaxis.label";
+
+    private static final String SINFO_CHART_VELOCITY_YAXIS_LABEL = "sinfo.chart.tkh_velocity.yaxis.label";
+
+    private static final String I18N_FACET_TKH_VELOCITY_FILTERED_DESCRIPTION = "sinfo.facet.tkh_velocity.description";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_TKH_VELOCITY_FILTERED);
+    }
+
+    public VelocityProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    protected SInfoResultType doGetType(final String facetName) {
+
+        if (FACET_TKH_VELOCITY_FILTERED.contentEquals(facetName))
+            return SInfoResultType.velocity;
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    public static Facet createVelocityFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int index) {
+        return AbstractSInfoProcessor.createFacet(context, hash, id, result, index, SINFO_CHART_VELOCITY_YAXIS_LABEL, FACET_TKH_VELOCITY_FILTERED,
+                I18N_FACET_TKH_VELOCITY_FILTERED_DESCRIPTION);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+        // TODO Auto-generated method stub
+        return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), GAP_DISTANCE);
+    }
+}
\ 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/common/WQBaseTableFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,185 @@
+/** 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.common;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+import org.dive4elements.river.artifacts.math.Linear;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.type.StandardBasicTypes;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Loading and search/interpolation of a W/Q base table of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class WQBaseTableFinder {
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(WQTableFinder.class);
+
+    private final River river;
+
+    private Calculation problems;
+
+    private final List<String> columnNames;
+
+    private final NavigableMap<Double, PolynomialSplineFunction> kmWs;
+
+    private final NavigableMap<Double, PolynomialSplineFunction> kmQs;
+
+    private static final String SQLCOLUMNS = "SELECT wc.position AS colindex, wc.name AS qzone"
+            + " FROM wsts w"
+            + "  INNER JOIN wst_columns wc ON w.id=wc.wst_id"
+            + " WHERE w.river_id = :river_id"
+            + "  AND w.kind = 0"
+            + " ORDER BY wc.position ASC";
+
+    private static final String SQLMAIN = "SELECT wcv.position AS station, wc.position AS colindex, wcv.w, wqr.q"
+            + " FROM wsts w"
+            + "  INNER JOIN wst_columns wc ON w.id=wc.wst_id"
+            + "  INNER JOIN wst_column_values wcv ON wc.id=wcv.wst_column_id"
+            + "  INNER JOIN wst_column_q_ranges wcqr ON wc.id=wcqr.wst_column_id"
+            + "  INNER JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id=wqr.id"
+            + "  INNER JOIN ranges r ON wqr.range_id=r.id AND wcv.position BETWEEN r.a AND r.b"
+            + " WHERE w.river_id = :river_id"
+            + "  AND w.kind = 0"
+            + "  AND r.river_id = :river_id"
+            + "  AND wcv.position BETWEEN :kmfrom - 1 AND :kmto + 1" // some tolerance for start and end of list
+            + " ORDER BY wcv.position ASC, "
+            + "  wc.position ASC";
+
+
+    /***** CONSTRUCTORS *****/
+
+    private WQBaseTableFinder(final River river, final Calculation problems, final List<Object[]> colnames, final List<Object[]> rows) {
+        this.river = river;
+        this.problems = problems;
+        this.columnNames = new ArrayList<>();
+        for (final Object[] colname : colnames)
+            this.columnNames.add(colname[1].toString());
+        this.kmWs = new TreeMap<>();
+        this.kmQs = new TreeMap<>();
+        final TDoubleArrayList ws = new TDoubleArrayList();
+        final TDoubleArrayList qs = new TDoubleArrayList();
+        double km = Double.NaN;
+        for (int i = 0; i <= rows.size() - 1; i++) {
+            if (ws.isEmpty() || ((double) rows.get(i)[0] <= km + 0.0001)) {
+                if (ws.isEmpty())
+                    km = (double) rows.get(i)[0];
+                ws.add((double) rows.get(i)[2]);
+                qs.add((double) rows.get(i)[3]);
+            }
+            if ((i == rows.size() - 1) || ((double) rows.get(i)[0] > km + 0.0001)) {
+                try {
+                    this.kmWs.put(km, new LinearInterpolator().interpolate(ws.toNativeArray(), qs.toNativeArray()));
+                    this.kmQs.put(km, new LinearInterpolator().interpolate(qs.toNativeArray(), ws.toNativeArray()));
+                }
+                catch (final Exception e) {
+                    if (this.problems != null) {
+                        this.problems.addProblem(km, "wq_base_data.missing");
+                        // Report only once
+                        this.problems = null;
+                    }
+                }
+                ws.clear();
+                qs.clear();
+                km = (double) rows.get(i)[0];
+                ws.add((double) rows.get(i)[2]);
+                qs.add((double) rows.get(i)[3]);
+            }
+        }
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the the W/Q tables of a km range of a river
+     *
+     * @return The W/Q table finder of the river, or null
+     */
+    public static WQBaseTableFinder loadValues(final River river, final double fromKm, final double toKm, final Calculation problems) {
+        final Session session = SessionHolder.HOLDER.get();
+        final SQLQuery colQuery = session.createSQLQuery(SQLCOLUMNS)
+                .addScalar("colindex", StandardBasicTypes.INTEGER)
+                .addScalar("qzone", StandardBasicTypes.STRING);
+        colQuery.setParameter("river_id", river.getId());
+        final List<Object[]> colnames = colQuery.list();
+        if ((colnames == null) || colnames.isEmpty()) {
+            problems.addProblem("wq_table.missing");
+            return null;
+        }
+        final SQLQuery wqQuery = session.createSQLQuery(SQLMAIN)
+                .addScalar("station", StandardBasicTypes.DOUBLE)
+                .addScalar("colindex", StandardBasicTypes.INTEGER)
+                .addScalar("w", StandardBasicTypes.DOUBLE)
+                .addScalar("q", StandardBasicTypes.DOUBLE);
+        wqQuery.setParameter("river_id", river.getId());
+        wqQuery.setParameter("kmfrom", fromKm);
+        wqQuery.setParameter("kmto", toKm);
+        final List<Object[]> rows = wqQuery.list();
+        if ((rows != null) && !rows.isEmpty())
+            return new WQBaseTableFinder(river, problems, colnames, rows);
+        else {
+            problems.addProblem("wq_table.missing");
+            return null;
+        }
+    }
+
+    /**
+     * If this provider may return valid data at all.
+     */
+    public boolean isValid() {
+        return (this.kmWs != null);
+    }
+
+    /**
+     * Discharge for a W
+     *
+     * @param station
+     *            station to find or interpolate
+     * @param w
+     *            W in m+NN or m+NHN
+     * @return Q, or NegInf for w less than all, or PosInf for w greater then all, or NaN in case of exception
+     */
+    public double getDischarge(final double station, final double w) {
+        if (this.kmWs == null)
+            return Double.NaN;
+        final Entry<Double, PolynomialSplineFunction> lowerEntry = this.kmWs.floorEntry(Double.valueOf(station));
+        final Entry<Double, PolynomialSplineFunction> upperEntry = this.kmWs.ceilingEntry(Double.valueOf(station));
+        if ((lowerEntry == null) || (upperEntry == null))
+            return Double.NaN;
+        try {
+            final double lowerQ = lowerEntry.getValue().value(w);
+            final double upperQ = upperEntry.getValue().value(w);
+            return Linear.linear(station, lowerEntry.getKey().doubleValue(), upperEntry.getKey().doubleValue(), lowerQ, upperQ);
+        }
+        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
+            // ignore exception because this can/will happen regularly
+            return Double.NaN;
+        }
+    }
+}
\ 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/flood_duration/DurationWaterlevel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.flood_duration;
+
+import java.io.Serializable;
+import java.text.NumberFormat;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class DurationWaterlevel implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final double w;
+    private final double q;
+    private final String bezeichnung;
+    private final int floodDurDaysPerYear;
+
+    public DurationWaterlevel(final double w, final int floodDurDaysPerYear, final double q, final String bezeichnung) {
+        this.w = w;
+        this.q = q;
+        this.bezeichnung = bezeichnung;
+        this.floodDurDaysPerYear = floodDurDaysPerYear;
+    }
+
+    public double getWaterlevel() {
+        return this.w;
+    }
+
+    public int getFloodDurDaysPerYear() {
+        return this.floodDurDaysPerYear;
+    }
+
+    public String getFloodDurDaysPerYearFormatted() {
+        return String.valueOf(this.floodDurDaysPerYear);
+    }
+
+    public String getBezeichnung() {
+        return this.bezeichnung;
+    }
+
+    public String getQFormatted(final NumberFormat qFormatter) {
+        return qFormatter.format(this.q);
+    }
+
+    public String getWFormatted(final NumberFormat wFormatter) {
+        return wFormatter.format(this.w);
+    }
+
+    // normally, the label is included in the type, but we need to replace the index ("_1")
+    public static final String getHeaderQ() {
+        return "sinfo.flood_duration.header.q_index";
+    }
+
+    public static final String getHeaderWPdf() {
+        return "sinfo.flood_duration.header.pdf.w_index";
+    }
+
+    public static final String getHeaderBezeichnPdf() {
+        return "sinfo.flood_duration.header.pdf.bezeichnung_index";
+    }
+
+    public static final String getHeaderFloodDurPerYearPdf() {
+        return "sinfo.flood_duration.header.pdf.fd_per_year_index";
+    }
+
+    public static final String getHeaderWCsv() {
+        return "sinfo.flood_duration.header.w_index";
+    }
+
+    public static final String getHeaderBezeichnCsv() {
+        return "sinfo.flood_duration.header.bezeichnung_index";
+    }
+
+    public static final String getHeaderFloodDurPerYearCsv() {
+        return "sinfo.flood_duration.header.fd_per_year_index";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,47 @@
+/* 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.flood_duration;
+
+import org.apache.log4j.Logger;
+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.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey;
+
+/**
+ * Access to the flood duration 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
+ */
+final class FloodDurationAccess extends RangeAccess {
+
+    private static Logger log = Logger.getLogger(FloodDurationAccess.class);
+
+    public FloodDurationAccess(final SINFOArtifact artifact) {
+        super(artifact);
+
+        /* assert calculation mode */
+        final SinfoCalcMode calculationMode = artifact.getCalculationMode();
+        assert (calculationMode == SinfoCalcMode.sinfo_calc_flood_duration);
+    }
+
+    @Override
+    public Double getStep() {
+        return super.getStep();
+    }
+
+    public RiversideChoiceKey getRiverside() {
+        return RiversideChoiceKey.fromKey(super.getString("riverside"));
+    }
+}
\ 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/flood_duration/FloodDurationCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,77 @@
+/** 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.flood_duration;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.model.River;
+
+/**
+ * Calculation of the flood durations of the infrastructures of the km range of a river
+ *
+ * @author Matthias Schäfer
+ */
+final class FloodDurationCalculation {
+
+    private final CallContext context;
+
+    public FloodDurationCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+
+        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
+
+        /* access input data */
+        final FloodDurationAccess access = new FloodDurationAccess(sinfo);
+        final River river = access.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+        final DoubleRange calcRange = access.getRange();
+
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
+        final String label = Resources.getMsg(this.context.getMeta(), access.getRiverside().getKey());
+
+        final Calculation problems = new Calculation();
+
+        // Calculate the selected main values, if any
+        /* misuse winfo-artifact to calculate waterlevels in the same way */
+        final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo);
+        winfo.addStringData("ld_mode", "distance");
+        winfo.addStringData("ld_step", "100");
+
+        final FloodDurationCalculationResults results = new FloodDurationCalculationResults(calcModeLabel, user, riverInfo, calcRange);
+
+        calculateResult(label, calcRange, infoProvider, access.getRiverside(), problems, winfo, results);
+
+        return new CalculationResult(results, problems);
+    }
+
+    /**
+     * Calculates the flood durations of the infrastructures of a km range of a river
+     */
+    private void calculateResult(final String label, final DoubleRange calcRange, final RiverInfoProvider riverInfoProvider,
+            final RiversideChoiceKey riverside, final Calculation problems, final WINFOArtifact winfo, final FloodDurationCalculationResults results) {
+
+        final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, riverInfoProvider);
+        calculator.execute(problems, label, calcRange, riverside, winfo, results);
+    }
+}
\ 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/flood_duration/FloodDurationCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,264 @@
+/* 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.flood_duration;
+
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.AbstractExportContext;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IResultType;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoI18NStrings;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.model.Attribute.AttributeKey;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Contains the result of a {@link FloodDurationCalculation}.
+ *
+ * @author Gernot Belger
+ */
+public final class FloodDurationCalculationResult extends AbstractCalculationExportableResult {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String[] mainvalueLabels;
+
+    // private final WstInfo wstInfo;
+
+    private final int maxWaterlevelPdf = 3;
+
+    public interface ValueGetter {
+        double getValue(DurationWaterlevel waterlevel);
+    }
+
+    private enum ExportMode {
+        pdf, csv
+    }
+
+    public FloodDurationCalculationResult(final String label, final String[] mainvalueLabels, final Collection<ResultRow> rows) {
+        super(label, rows);
+        this.mainvalueLabels = mainvalueLabels;
+    }
+
+    /**
+     * Collection of the result rows containing only the rows describing an infrastructure
+     */
+    @Override
+    public Collection<ResultRow> getRows() {
+        final List<ResultRow> infrasOnlyRows = new ArrayList<>();
+        for (final ResultRow row : this.rows)
+            if (row.getValue(SInfoResultType.infrastructuretype) != null)
+                infrasOnlyRows.add(row);
+        return Collections.unmodifiableCollection(infrasOnlyRows);
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        if (this.mainvalueLabels.length >= 1) {
+            // "##METADATEN WASSERSPIEGELLAGE"
+            exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL);
+            for (int i = 1; i <= getWaterlevelCount(); i++) {
+                // "# Bezeichnung der Wasserspiegellage: "
+                final String label = this.getMainValueLabel(i - 1);
+                exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_NAME, String.format("%d: %s", i, label));
+            }
+            // "# Bezugspegel: "
+            for (final ResultRow row : this.rows) {
+                exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_GAUGE, row.getValue(SInfoResultType.gaugeLabel));
+                break;
+            }
+        }
+        exportContextCSV.writeBlankLine();
+    }
+
+    @Override
+    protected String getJasperFile() {
+        if (this.getWaterlevelCount() <= 1)
+            return "/jasper/templates/sinfo.floodduration.jrxml";
+        else
+            return "/jasper/templates/sinfo.floodduration2.jrxml";
+    }
+
+    protected String[] formatRow(final AbstractExportContext exportContextCSV, final ResultRow row, final ExportMode mode) {
+
+        final Collection<String> lines = new ArrayList<>(10);
+
+        lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.station));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.riverside));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.floodDuration));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.floodDischarge));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.infrastructureHeight));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.infrastructuretype));
+
+        final List<DurationWaterlevel> waterlevelList = (List<DurationWaterlevel>) row.getValue(SInfoResultType.customMultiRowColWaterlevel);
+        if (waterlevelList != null) {
+            final NumberFormat wFormatter = exportContextCSV.getFlowDepthFormatter();
+            final NumberFormat qFormatter = exportContextCSV.getQFormatter();
+
+            for (int i = 0; i < waterlevelList.size(); i++) {
+
+                if (i == this.maxWaterlevelPdf && mode == ExportMode.pdf)
+                    break;
+
+                final DurationWaterlevel item = waterlevelList.get(i);
+                lines.add(item.getWFormatted(wFormatter));
+                lines.add(item.getFloodDurDaysPerYearFormatted());
+                lines.add(item.getQFormatted(qFormatter));
+                lines.add(item.getBezeichnung());
+            }
+        }
+
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.gaugeLabel));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.location));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final Collection<String> header = new ArrayList<>(20);
+
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.riverside));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.floodDuration));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.floodDischarge, SInfoResultType.floodDischarge.getUnit()));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.infrastructureHeight, SInfoResultType.infrastructureHeight.getUnit()));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.infrastructuretype));
+
+        // add dynamic headers
+        final int waterlevelCount = // results.
+                getWaterlevelCount();
+        for (int i = 0; i < waterlevelCount; i++) {
+            final String appendIndex = "_" + Integer.toString(i + 1);
+            header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderWCsv(), appendIndex, "results.getRiver().getWstUnit()"));
+            header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderFloodDurPerYearCsv(), appendIndex));
+            header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderQ(), appendIndex));
+            header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderBezeichnCsv(), appendIndex));
+        }
+
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.gaugeLabel));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.location));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return this.formatRow(exportContextCSV, row, ExportMode.csv);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) {
+
+        return this.formatRow(exportContextPDF, row, ExportMode.pdf);
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
+
+        /* column headings */
+        exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContextPDF.addJRMetadata(source, "riverside_header", SInfoResultType.riverside);
+        exportContextPDF.addJRMetadata(source, "inundationduration_header", SInfoResultType.floodDuration);
+        exportContextPDF.addJRMetadata(source, "inundationduration_q_header", SInfoResultType.floodDischarge);
+        exportContextPDF.addJRMetadata(source, "infrastructure_height_header", SInfoResultType.infrastructureHeight);
+        exportContextPDF.addJRMetadata(source, "infrastructure_type_header", SInfoResultType.infrastructuretype);
+
+        for (int i = 1; i <= this.getWaterlevelCount(); i++) {
+
+            final String appendIndex = "_" + Integer.toString(i);
+            exportContextPDF.addJRMetadata(source, getPdfHeader("w", i), exportContextPDF.msg(DurationWaterlevel.getHeaderWPdf(), appendIndex));
+            exportContextPDF.addJRMetadata(source, getPdfHeader("duration", i),
+                    exportContextPDF.msg(DurationWaterlevel.getHeaderFloodDurPerYearPdf(), appendIndex));
+            exportContextPDF.addJRMetadata(source, getPdfHeader("q", i), exportContextPDF.msg(DurationWaterlevel.getHeaderQ(), appendIndex));
+            exportContextPDF.addJRMetadata(source, getPdfHeader("bezeichnung", i),
+                    exportContextPDF.msg(DurationWaterlevel.getHeaderBezeichnPdf(), appendIndex));
+        }
+
+        exportContextPDF.addJRMetadata(source, "gauge_header", SInfoResultType.gaugeLabel);
+        exportContextPDF.addJRMetadata(source, "location_header", SInfoResultType.location);
+    }
+
+    private final String getPdfHeader(final String rootStr, final int index) {
+        final String hd = "_header";
+        final StringBuilder builder = new StringBuilder();
+        return builder.append(rootStr).append("_").append(index).append(hd).toString();
+    }
+
+    public final int getWaterlevelCount() {
+        return (this.mainvalueLabels != null) ? this.mainvalueLabels.length : 0;
+    }
+
+    public String getMainValueLabel(final int j) {
+        if (this.mainvalueLabels != null && j < this.mainvalueLabels.length)
+            return this.mainvalueLabels[j];
+        return "";
+    }
+
+    /**
+     * Gets the longitudinal section of a result value type for one river side
+     */
+    public final double[][] getInfrastructurePoints(final IResultType type, final AttributeKey riverside) {
+
+        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
+        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
+
+        for (final ResultRow row : this.rows) {
+
+            final double station = row.getDoubleValue(GeneralResultType.station);
+            final double value = row.getDoubleValue(type);
+            if (row.getValue(SInfoResultType.riverside) == riverside) {
+                xPoints.add(station);
+                yPoints.add(value);
+            }
+        }
+
+        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
+    }
+
+    /**
+     * Gets a longitudinal section of W, Q, or flood duration of one of the waterlevels
+     */
+    public final double[][] getMainValueDurationPoints(final DiagramGenerator generator, final ValueGetter valuegetter, final int dataIndex) {
+
+        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
+        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
+
+        for (final ResultRow row : this.rows) {
+
+            final double station = row.getDoubleValue(GeneralResultType.station);
+
+            final List<DurationWaterlevel> waterlevels = (List<DurationWaterlevel>) row.getValue(SInfoResultType.customMultiRowColWaterlevel);
+            final DurationWaterlevel waterlevel = waterlevels.get(dataIndex);
+
+            final Double value = valuegetter.getValue(waterlevel);
+
+            xPoints.add(station);
+            yPoints.add(value);
+        }
+
+        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/flood_duration/FloodDurationCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,37 @@
+/** 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.flood_duration;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Gernot Belger
+ */
+final class FloodDurationCalculationResults extends AbstractCalculationResults<FloodDurationCalculationResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    public FloodDurationCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) {
+        super(calcModeLabel, user, river, calcRange);
+    }
+
+    private CalculationResult durationCurve;
+
+    public CalculationResult getDurationCurve() {
+        return this.durationCurve;
+    }
+
+    public void setDurationCurve(final CalculationResult durationCurve) {
+        this.durationCurve = durationCurve;
+    }
+}
\ 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/flood_duration/FloodDurationCalculator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,286 @@
+/** 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.flood_duration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.Calculation.Problem;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.WQDay;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.sinfo.common.GaugeDurationValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.common.WQBaseTableFinder;
+import org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey;
+import org.dive4elements.river.exports.WaterlevelDescriptionBuilder;
+import org.dive4elements.river.model.Attribute.AttributeKey;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.sinfo.InfrastructureValue;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Calculation of the result rows of the flood duration of the infrastructures in a river km range
+ * and selected main value durations
+ *
+ * @author Matthias Schäfer
+ */
+final class FloodDurationCalculator {
+
+    private final Collection<ResultRow> rows = new ArrayList<>();
+
+    private final RiverInfoProvider riverInfoProvider;
+
+    private final CallContext context;
+
+    public FloodDurationCalculator(final CallContext context, final RiverInfoProvider riverInfoProvider) {
+        this.context = context;
+        this.riverInfoProvider = riverInfoProvider;
+    }
+
+    /**
+     * Calculate the infrastructures flood duration result rows
+     */
+    public void execute(final Calculation problems, final String label, final DoubleRange calcRange,
+            final RiversideChoiceKey riverside, final WINFOArtifact winfo, final FloodDurationCalculationResults results) {
+
+        // Find all gauges of the calc range, and create the duration finders
+        final Map<Gauge, GaugeDurationValuesFinder> durFinders = new HashMap<>();
+        Gauge firstGauge = null;
+        for (final Gauge gauge : this.riverInfoProvider.getRiver().determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble())) {
+            durFinders.put(gauge, GaugeDurationValuesFinder.loadValues(gauge, problems));
+            if (firstGauge == null)
+                firstGauge = gauge;
+        }
+
+        // Find all infrastructures within the calc range
+        final AttributeKey bankKey = riverside.getAttributeKey();
+        final List<InfrastructureValue> infras = InfrastructureValue.getValues(this.riverInfoProvider.getRiver(), calcRange.getMinimumDouble(),
+                calcRange.getMaximumDouble(), bankKey);
+
+        // Merge all stations (range/step, borders of gauge ranges, infrastructures)
+        final Map<Double, InfrastructureValue> allStations = new HashMap<>();
+        final Map<Double, InfrastructureValue> secondBank = new HashMap<>(); // any second infrastructure in case of both-banks-option
+        addRangeStations(allStations, winfo);
+        addGaugeLimits(allStations, durFinders.keySet(), calcRange.getMinimumDouble(), calcRange.getMaximumDouble());
+        addInfrastructures(allStations, secondBank, infras);
+        final double[] stationsSorted = sortStations(allStations.keySet());
+
+        // Calculate W and Q for all stations and the selected discharge states
+        // TODO Laut Herrn Reiß: Q und D jeweils konstant für jedes Pegel-Intervall, Q-Änderungen (Zuflüsse etc.) aus .wst
+        // ignorieren
+        final WQKms[] wqkmsArray = calculateWaterlevels(winfo, stationsSorted, problems);
+
+        // Determine discharge state labels of the main values
+        final WaterlevelDescriptionBuilder wdescBuilder = new WaterlevelDescriptionBuilder(winfo, this.context);
+        final String[] mainValueLabels = findMainValueLabels(wqkmsArray, winfo.getQs(), wdescBuilder, problems);
+
+        // Create a finder for Q in the {river}.wst km-w-q table
+        final WQBaseTableFinder wqFinder = WQBaseTableFinder.loadValues(this.riverInfoProvider.getRiver(), calcRange.getMinimumDouble(),
+                calcRange.getMaximumDouble(), problems);
+
+        final WaterlevelDescriptionBuilder descBuilder = new WaterlevelDescriptionBuilder(winfo, this.context);
+
+        // Calculate the durations and create the result rows
+        for (int i = 0; i <= stationsSorted.length - 1; i++) {
+            final Gauge gauge = this.riverInfoProvider.getGauge(stationsSorted[i], true);
+            final ResultRow row = createRow(descBuilder, stationsSorted[i], gauge, firstGauge, wqkmsArray, durFinders.get(gauge), i);
+            if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null))
+                calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wqFinder, durFinders);
+            this.rows.add(row);
+            if (secondBank.containsKey(stationsSorted[i])) {
+                final ResultRow row2 = ResultRow.create(row);
+                calculateInfrastructure(row2, gauge, secondBank.get(stationsSorted[i]), wqFinder, durFinders);
+                this.rows.add(row2);
+            }
+        }
+        results.addResult(new FloodDurationCalculationResult(label, mainValueLabels, this.rows), problems);
+        calcWQDays(problems, stationsSorted[0], AttributeKey.LEFT, winfo, results);
+    }
+
+    public void calcWQDays(final Calculation problems, final double station, final AttributeKey riverside, final WINFOArtifact winfo,
+            final FloodDurationCalculationResults results) {
+
+        winfo.addStringData("ld_locations", Double.toString(station));
+        final CalculationResult res = winfo.getDurationCurveData();
+        final WQDay underflow = (WQDay) res.getData();
+        // Transform underflow days into overflow days and re-sort
+        final int[] days = new int[underflow.getWs().length];
+        final double[] ws = new double[days.length];
+        final double[] qs = new double[days.length];
+        for (int i = 0, j = days.length - 1; i <= days.length - 1; i++, j--) {
+            days[j] = 365 - underflow.getDay(i);
+            ws[j] = underflow.getW(i);
+            qs[j] = underflow.getQ(i);
+        }
+        res.setData(new WQDay(days, ws, qs));
+        // TODO Infrastrukturhoehe
+        // TODO WSPL/Hauptwerte
+        results.setDurationCurve(res);
+    }
+
+    /**
+     * Adds to a stations map all stations corresponding to the active range and step
+     */
+    private void addRangeStations(final Map<Double, InfrastructureValue> allStations, final WINFOArtifact winfo) {
+        for (final double station : new ComputationRangeAccess(winfo).getKms())
+            allStations.put(Double.valueOf(station), null);
+    }
+
+    /**
+     * Adds to a stations map all range limits of the gauges within the calc range
+     */
+    private void addGaugeLimits(final Map<Double, InfrastructureValue> allStations, final Set<Gauge> gauges, final double fromKm, final double toKm) {
+        for (final Gauge gauge : gauges) {
+            final Double kmA = Double.valueOf(gauge.getRange().getA().doubleValue());
+            final Double kmB = Double.valueOf(gauge.getRange().getB().doubleValue());
+            if (kmA > fromKm - 0.0001)
+                allStations.put(kmA, null);
+            if (kmB < toKm + 0.0001)
+                allStations.put(kmB, null);
+        }
+    }
+
+    /**
+     * Adds to a stations map all (first) infrastructures of a station, and the second, if any, to another map
+     */
+    private void addInfrastructures(final Map<Double, InfrastructureValue> allStations, final Map<Double, InfrastructureValue> secondBank,
+            final List<InfrastructureValue> infrastructures) {
+        for (final InfrastructureValue infrastructure : infrastructures) {
+            final Double station = infrastructure.getStation();
+            if (!allStations.containsKey(station) || !(allStations.get(station) instanceof InfrastructureValue))
+                allStations.put(station, infrastructure);
+            else
+                secondBank.put(station, infrastructure);
+        }
+    }
+
+    /**
+     * Returns a double array with a sorted stations set
+     */
+    private double[] sortStations(final Set<Double> stations) {
+        final TDoubleArrayList sorted = new TDoubleArrayList();
+        for (final Double station : stations)
+            sorted.add(station.doubleValue());
+        sorted.sort();
+        return sorted.toNativeArray();
+    }
+
+    /**
+     * Calculates an array of w-q-longitudinal sections for all artifact W/Q options
+     */
+    private WQKms[] calculateWaterlevels(final WINFOArtifact winfo, final double[] stations, final Calculation problems) {
+        // REMARK aus TkhCalculation - move to WinfoArtifactWrapper?
+        // TODO das ist ziemlich langsam - durch den WQBaseTableFinder ersetzen? (vorher W-Optionen in Q umrechnen)
+        // (So funktioniert computeWaterlevelData wohl:
+        // Es sucht die Spalte(n) zum Bezugspegel-Q in der W-Q-Tabelle ({river}.wst in Wst etc.),
+        // interpoliert die horizontale Tabellenposition (Q) und dann die vertikale Tabellenposition der station;
+        // das ergibt das W einer station für einen Abflusszustand;
+        // bei Vorgabe eines Pegel-W wird vorher anhand der W-Q-Tabelle des Pegels ({gauge}.at in DischargeTable) das Q
+        // interpoliert;
+        // bei Vorgabe eines W auf freier Strecke wird wohl vorher noch die .wst-Interpolation eingesetzt, um das Q zu bekommen.
+
+        final CalculationResult waterlevelData = winfo.computeWaterlevelData(stations);
+
+        /* copy all problems */
+        final Calculation winfoProblems = waterlevelData.getReport();
+        final List<Problem> problems2 = winfoProblems.getProblems();
+        if (problems2 != null) {
+            for (final Problem problem : problems2) {
+                problems.addProblem(problem);
+            }
+        }
+        return (WQKms[]) waterlevelData.getData();
+    }
+
+    /**
+     * Determines the waterlevel/discharge state labels for the selected Q or W values
+     */
+    private String[] findMainValueLabels(final WQKms[] wqkmsArray, final double[] qs, final WaterlevelDescriptionBuilder descBuilder,
+            final Calculation problems) {
+
+        final String[] mainValueLabels = new String[wqkmsArray.length];
+        for (int i = 0; i <= wqkmsArray.length - 1; i++)
+            mainValueLabels[i] = descBuilder.getDesc(wqkmsArray[i]);
+        return mainValueLabels;
+    }
+
+    /**
+     * Create a result row for a station and its gauge, and add w-q-values as selected
+     *
+     * @param descBuilder
+     */
+    private ResultRow createRow(final WaterlevelDescriptionBuilder descBuilder, final Double station, final Gauge gauge, final Gauge firstGauge,
+            final WQKms[] wqkmsArray, final GaugeDurationValuesFinder durationFinder, final int kmIndex) {
+
+        final ResultRow row = ResultRow.create();
+        row.putValue(GeneralResultType.station, station);
+        row.putValue(SInfoResultType.infrastructuretype, null); // is replaced later for an infrastructure
+        row.putValue(SInfoResultType.floodDuration, Double.NaN); // is replaced later for an infrastructure
+
+        final String gaugeLabel = this.riverInfoProvider.findGauge(station, (gauge == firstGauge));
+        row.putValue(SInfoResultType.gaugeLabel, gaugeLabel);
+
+        final String location = this.riverInfoProvider.getLocation(station);
+        row.putValue(SInfoResultType.location, location);
+
+        final List<DurationWaterlevel> waterlevels = new ArrayList<>(wqkmsArray.length);
+
+        for (final WQKms wqKm : wqkmsArray) {
+            assert (wqKm.getKm(kmIndex) == station.doubleValue());
+
+            final int overflowDays = (int) Math.round(underflowDaysToOverflowDays(durationFinder.getDuration(wqKm.getQ(kmIndex))));
+
+            final String waterlevelLabel = descBuilder.getDesc(wqKm);
+
+            final DurationWaterlevel dw = new DurationWaterlevel(wqKm.getW(kmIndex), overflowDays, wqKm.getQ(kmIndex), waterlevelLabel);
+            waterlevels.add(dw);
+        }
+        row.putValue(SInfoResultType.customMultiRowColWaterlevel, waterlevels);
+
+        return row;
+    }
+
+    /**
+     * Calculate the result row fields for one infrastructure
+     */
+    private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue infrastructure, final WQBaseTableFinder wqFinder,
+            final Map<Gauge, GaugeDurationValuesFinder> durFinders) {
+
+        final double q = wqFinder.getDischarge(infrastructure.getStation(), infrastructure.getHeight());
+        final double qOut = Double.isInfinite(q) ? Double.NaN : q;
+        final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(q));
+        row.putValue(SInfoResultType.riverside, infrastructure.getAttributeKey());
+        row.putValue(SInfoResultType.floodDuration, dur);
+        row.putValue(SInfoResultType.floodDischarge, qOut);
+        row.putValue(SInfoResultType.infrastructureHeight, infrastructure.getHeight());
+        row.putValue(SInfoResultType.infrastructuretype, infrastructure.getInfrastructure().getType().getName());
+    }
+
+    /**
+     * Translates underflow duration into overflow duration
+     */
+    private double underflowDaysToOverflowDays(final double underflowDays) {
+        return 365 - underflowDays;
+    }
+}
\ 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/flood_duration/FloodDurationCurveFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,120 @@
+/* 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.flood_duration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.DefaultFacet;
+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.WQDay;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+
+/**
+ * Data of a duration curve.
+ */
+public class FloodDurationCurveFacet extends DefaultFacet {
+
+    private static Logger log = Logger.getLogger(FloodDurationCurveFacet.class);
+
+    /** Blackboard data provider key for durationcurve (wqday) data. */
+    public static String BB_DURATIONCURVE = "durationcurve";
+
+    /** Blackboard data provider key for km of durationcurve. */
+    public static String BB_DURATIONCURVE_KM = "durationcurve.km";
+
+    public FloodDurationCurveFacet() {
+    }
+
+    public FloodDurationCurveFacet(final String name, final String description) {
+        super(0, name, description);
+    }
+
+
+    /**
+     * Expose state computation from SINFOArtifact.
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        log.debug("Get data for flood duration curve data");
+
+        final D4EArtifact flys = (D4EArtifact) artifact;
+
+        final CalculationResult res = (CalculationResult) flys.compute(context, ComputeType.ADVANCE, false);
+
+        final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
+
+        return data.getDurationCurve();
+        // return getTestData();
+    }
+
+    private WQDay getTestData() {
+        final int[] days = new int[366];
+        final double[] ws = new double[366];
+        final double[] qs = new double[366];
+        for (int i = 0; i <= 365; i++) {
+            days[i] = i;
+            final double x = (i - 182.5) / 182.5;
+            ws[i] = 102.0 - (Math.pow(x, 5) + x);
+            qs[i] = 1600.0 - 800 * (Math.pow(x, 9) + x);
+        }
+        return new WQDay(days, ws, qs);
+    }
+
+
+    @Override
+    public List getStaticDataProviderKeys(final Artifact art) {
+        final List list = new ArrayList();
+        list.add(BB_DURATIONCURVE);
+        list.add(BB_DURATIONCURVE_KM);
+        return list;
+    }
+
+
+    /**
+     * Can provide whatever getData returns and additionally the location.
+     * @param key      will respond on BB_DURATIONCURVE +KM
+     * @param param    ignored
+     * @param context  ignored
+     * @return whatever getData delivers or location.
+     */
+    @Override
+    public Object provideBlackboardData(final Artifact artifact,
+            final Object key,
+            final Object param,
+            final CallContext context
+            ) {
+        if (key.equals(BB_DURATIONCURVE)) {
+            return getData(artifact, context);
+        }
+        else if (key.equals(BB_DURATIONCURVE_KM)) {
+            return ((D4EArtifact)artifact).getDataAsString("ld_locations");
+        }
+        else {
+            return null;
+        }
+    }
+
+
+    /** Create a deep copy. */
+    @Override
+    public Facet deepCopy() {
+        final FloodDurationCurveFacet copy = new FloodDurationCurveFacet();
+        copy.set(this);
+        return copy;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,258 @@
+/* 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.flood_duration;
+
+import java.awt.Font;
+import java.awt.geom.Point2D;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.model.WQDay;
+import org.dive4elements.river.exports.IdentifiableNumberAxis;
+import org.dive4elements.river.exports.XYChartGenerator;
+import org.dive4elements.river.jfree.Bounds;
+import org.dive4elements.river.jfree.RiverAnnotation;
+import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.themes.ThemeDocument;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.data.Range;
+import org.jfree.data.xy.XYSeries;
+
+
+/**
+ * An OutGenerator that generates duration curves.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class FloodDurationCurveGenerator
+extends      XYChartGenerator
+implements   FacetTypes
+{
+    public static enum YAXIS {
+        W(0),
+        Q(1);
+        public int idx;
+        private YAXIS(final int c) {
+            this.idx = c;
+        }
+    }
+
+    /** Local log. */
+    private static Logger log =
+            Logger.getLogger(FloodDurationCurveGenerator.class);
+
+    public static final String I18N_CHART_TITLE = "sinfo.chart.flood_duration.curve.section.title";
+
+    public static final String I18N_CHART_SUBTITLE = "chart.duration.curve.subtitle";
+
+    public static final String I18N_XAXIS_LABEL = "sinfo.chart.flood_duration.curve.xaxis.label";
+
+    public static final String I18N_YAXIS_LABEL_W = "chart.duration.curve.yaxis.label.w";
+
+    public static final String I18N_YAXIS_LABEL_Q = "chart.duration.curve.yaxis.label.q";
+
+    public static final String I18N_CHART_TITLE_DEFAULT = "Dauerlinie";
+
+    public static final String I18N_XAXIS_LABEL_DEFAULT = "Ãœberflutungsdauer [d/a]";
+
+
+    public FloodDurationCurveGenerator() {
+        super();
+    }
+
+
+    /**
+     * Create Axis for given index.
+     * @return axis with according internationalized label.
+     */
+    @Override
+    protected NumberAxis createYAxis(final int index) {
+        final Font labelFont = new Font("Tahoma", Font.BOLD, 14);
+        final String label   = getYAxisLabel(index);
+
+        final NumberAxis axis = createNumberAxis(index, label);
+        if (index == YAXIS.W.idx) {
+            axis.setAutoRangeIncludesZero(false);
+        }
+        axis.setLabelFont(labelFont);
+        return axis;
+    }
+
+
+    @Override
+    protected String getDefaultChartTitle(final CallContext context) {
+        return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
+    }
+
+
+    @Override
+    protected String getDefaultChartSubtitle(final CallContext context) {
+
+        final double[] dist  = getRange();
+        return msg(I18N_CHART_SUBTITLE, "", getRiverName(), dist[0]);
+    }
+
+
+    @Override
+    protected String getDefaultXAxisLabel(final CallContext context) {
+        return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
+    }
+
+
+    @Override
+    protected String getDefaultYAxisLabel(final int index) {
+
+        String label = "default";
+        if (index == YAXIS.W.idx) {
+            label = msg(I18N_YAXIS_LABEL_W, I18N_YAXIS_LABEL_W, getRiverUnit());
+        }
+        else if (index == YAXIS.Q.idx) {
+            label = msg(I18N_YAXIS_LABEL_Q);
+        }
+        return label;
+    }
+
+
+    @Override
+    protected boolean zoomX(final XYPlot plot, final ValueAxis axis, final Bounds bounds, final Range x) {
+
+        final boolean zoomin = super.zoom(plot, axis, bounds, x);
+        if (!zoomin)
+            axis.setLowerBound(0d);
+        // axis.setUpperBound(364);
+        return zoomin;
+    }
+
+
+    /**
+     * This method overrides the method in the parent class to set the lower
+     * bounds of the Q axis to 0. This axis should never display negative
+     * values on its own.
+     */
+    @Override
+    protected boolean zoomY(final XYPlot plot, final ValueAxis axis, final Bounds bounds, final Range x) {
+
+        final boolean zoomin = super.zoom(plot, axis, bounds, x);
+        if (!zoomin && axis instanceof IdentifiableNumberAxis) {
+            final String id = ((IdentifiableNumberAxis) axis).getId();
+            if (YAXIS.Q.toString().equals(id))
+                axis.setLowerBound(0d);
+        }
+        return zoomin;
+    }
+
+
+    @Override
+    public void doOut(final ArtifactAndFacet artifactFacet, final ThemeDocument attr, final boolean visible) {
+
+        final String name = artifactFacet.getFacetName();
+
+        log.debug("FloodDurationCurveGenerator.doOut: " + name);
+
+        if (name == null || name.length() == 0) {
+            log.error("No facet given. Cannot create dataset.");
+            return;
+        }
+
+        final CallContext context = getContext();
+
+        if (name.equals(DURATION_W)) {
+            doWOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible);
+        }
+        else if (name.equals(DURATION_Q)) {
+            doQOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible);
+        }
+        else if (name.equals(MAINVALUES_Q) || name.equals(MAINVALUES_W)) {
+            doAnnotations((RiverAnnotation) artifactFacet.getData(context), artifactFacet, attr, visible);
+        }
+        else if (name.equals(RELATIVE_POINT)) {
+            doPointOut((Point2D) artifactFacet.getData(context), artifactFacet, attr, visible);
+        }
+        else if (FacetTypes.IS.MANUALPOINTS(name)) {
+            doPoints(artifactFacet.getData(context), artifactFacet, attr, visible, YAXIS.W.idx);
+        }
+        else {
+            log.warn("Unknown facet name: " + name);
+            return;
+        }
+    }
+
+    /**
+     * Creates the series for a duration curve's W facet.
+     *
+     * @param wqdays The WQDay store that contains the Ws.
+     * @param theme
+     */
+    protected void doWOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) {
+
+        // log.debug("DurationCurveGenerator.doWOut");
+        final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
+        final int size = wqdays.size();
+        for (int i = 0; i < size; i++) {
+            final int  day = wqdays.getDay(i);
+            final double w = wqdays.getW(i);
+            series.add(day, w);
+        }
+        addAxisSeries(series, YAXIS.W.idx, visible);
+    }
+
+    protected void doPointOut(final Point2D point, final ArtifactAndFacet aandf, final ThemeDocument theme, final boolean visible) {
+
+        // log.debug("DurationCurveGenerator.doPointOut");
+        final XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme);
+        series.add(point.getX(), point.getY());
+        addAxisSeries(series, YAXIS.W.idx, visible);
+    }
+
+
+    /**
+     * Creates the series for a duration curve's Q facet.
+     *
+     * @param wqdays The WQDay store that contains the Qs.
+     * @param theme
+     */
+    protected void doQOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) {
+
+        // log.debug("DurationCurveGenerator.doQOut");
+        final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
+        final int size = wqdays.size();
+        for (int i = 0; i < size; i++) {
+            final int  day = wqdays.getDay(i);
+            final double q = wqdays.getQ(i);
+            series.add(day, q);
+        }
+        addAxisSeries(series, YAXIS.Q.idx, visible);
+    }
+
+
+    @Override
+    protected YAxisWalker getYAxisWalker() {
+        return new YAxisWalker() {
+            @Override
+            public int length() {
+                return YAXIS.values().length;
+            }
+
+            @Override
+            public String getId(final int idx) {
+                final YAXIS[] yaxes = YAXIS.values();
+                return yaxes[idx].toString();
+            }
+        };
+    }
+
+    // MainValue-Annotations should be visualized by
+    // a line that goes to the curve itself.
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveInfoGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,26 @@
+/* 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.flood_duration;
+
+import org.dive4elements.river.exports.ChartInfoGenerator;
+
+/**
+ * A ChartInfoGenerator that generates meta information for specific duration
+ * curves.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class FloodDurationCurveInfoGenerator
+extends      ChartInfoGenerator
+{
+    public FloodDurationCurveInfoGenerator() {
+        super(new FloodDurationCurveGenerator());
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,74 @@
+/** 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.flood_duration;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.exports.DurationCurveGenerator;
+import org.dive4elements.river.exports.XYChartGenerator;
+import org.dive4elements.river.exports.process.DefaultProcessor;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate the facet and data series of a flood duration curve
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class FloodDurationCurveProcessor extends DefaultProcessor {
+
+    private static final String FACET_FLOOD_DURATION_W = "duration_curve.w";
+
+    private static final String FACET_FLOOD_DURATION_Q = "duration_curve.q";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_FLOOD_DURATION_W);
+        HANDLED_FACET_TYPES.add(FACET_FLOOD_DURATION_Q);
+    }
+
+    public static Facet createFloodDurationWCurveFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int facetIndex, final int resultIndex, final String description) {
+
+        return new FloodDurationCurveFacet(FACET_FLOOD_DURATION_W, description);
+    }
+
+    public static Facet createFloodDurationQCurveFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int facetIndex, final int resultIndex, final String description) {
+
+        return new FloodDurationCurveFacet(FACET_FLOOD_DURATION_Q, description);
+    }
+
+    /**
+     * Processes data to generate a chart.
+     */
+    @Override
+    public void doOut(final XYChartGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible, final int index) {
+
+    }
+
+    @Override
+    public final String getAxisLabel(final DiagramGenerator generator) {
+        return generator.msg(DurationCurveGenerator.I18N_YAXIS_LABEL_W);
+    }
+
+    @Override
+    public final boolean canHandle(final String facettype) {
+        return HANDLED_FACET_TYPES.contains(facettype);
+    }
+}
\ 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/flood_duration/FloodDurationExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,49 @@
+/* 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.flood_duration;
+
+import org.dive4elements.river.artifacts.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.JasperDesigner;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+
+/**
+ * Generates different output formats (csv, pdf) of data that resulted from a flood duration 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 FloodDurationExporter extends AbstractCommonExporter<FloodDurationCalculationResult, FloodDurationCalculationResults> {
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final FloodDurationCalculationResults results) {
+        exportContext.writeCSVGlobalMetadataDefaults();
+    }
+
+    @Override
+    protected void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+    }
+
+    @Override
+    protected void configureDesign(final FloodDurationCalculationResult result, final JasperDesigner design) {
+        if (result instanceof FloodDurationCalculationResult) {
+            final int wlCount = result.getWaterlevelCount();
+            if (wlCount == 0 || wlCount == 2) {
+                design.removeColumn("wOpt");
+                design.removeColumn("qOpt");
+                design.removeColumn("bezOpt");
+                design.removeColumn("durOpt");
+            }
+        }
+    }
+}
\ 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/flood_duration/FloodDurationFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,53 @@
+/** 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.flood_duration;
+
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultFacet;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+final class FloodDurationFacet extends SInfoResultFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    protected int waterlevelIndex = -1; // for custom result
+
+    private FloodDurationFacet() {
+        // required for clone operation deepCopy()
+    }
+
+    public FloodDurationFacet(final int facetIndex, final int resultIndex, final int waterlevelIndex, final String name, final String description,
+            final ComputeType type, final String yAxisLabelKey, final String hash, final String stateId) {
+        super(facetIndex, resultIndex, name, description, yAxisLabelKey, type, stateId, hash);
+
+        this.waterlevelIndex = waterlevelIndex;
+    }
+
+    public int getWaterlevelIndex() {
+        return this.waterlevelIndex;
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        // FIXME: why not simply use the full constructor instead?
+        final FloodDurationFacet copy = new FloodDurationFacet();
+        // FIXME: why does DataFacet does not override set? Bad access to variables of parent!
+        copy.set(this);
+        copy.type = this.type;
+        copy.hash = this.hash;
+        copy.stateId = this.stateId;
+        copy.waterlevelIndex = this.waterlevelIndex;
+        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/flood_duration/FloodDurationProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,131 @@
+/** 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.flood_duration;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.common.AbstractSInfoProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultFacet;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationCalculationResult.ValueGetter;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.model.Attribute.AttributeKey;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate the facet and data series of infrastructure flood durations
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class FloodDurationProcessor extends AbstractSInfoProcessor {
+
+    private static final String FACET_FLOOD_DURATION_LEFT = "sinfo_facet_flood_duration.left";
+
+    private static final String FACET_FLOOD_DURATION_RIGHT = "sinfo_facet_flood_duration.right";
+
+    private static final String FACET_FLOOD_DURATION_DESCRIPTION = "sinfo_facet_flood_duration.description";
+
+    private static final String FACET_MAIN_VALUE_DURATION = "mainvalue.duration";
+
+    private static final String FACET_MAIN_VALUE_DURATION_DESCRIPTION = "mainvalue.duration.description";
+
+    private static final String I18N_AXIS_LABEL = "sinfo.chart.flood_duration.section.yaxis.label";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_FLOOD_DURATION_LEFT);
+        HANDLED_FACET_TYPES.add(FACET_FLOOD_DURATION_RIGHT);
+        HANDLED_FACET_TYPES.add(FACET_MAIN_VALUE_DURATION);
+    }
+
+    public FloodDurationProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    public static Facet createFloodDurationFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int facetIndex, final int resultIndex) {
+
+        if (facetIndex == 0) {
+            final String description = Resources.getMsg(context.getMeta(), FACET_FLOOD_DURATION_DESCRIPTION, FACET_FLOOD_DURATION_DESCRIPTION,
+                    SInfoResultType.localizeRiverside(context, AttributeKey.LEFT));
+            return new SInfoResultFacet(facetIndex, resultIndex, FACET_FLOOD_DURATION_LEFT, description, I18N_AXIS_LABEL, ComputeType.ADVANCE, id, hash);
+        }
+        else {
+            final String description = Resources.getMsg(context.getMeta(), FACET_FLOOD_DURATION_DESCRIPTION, FACET_FLOOD_DURATION_DESCRIPTION,
+                    SInfoResultType.localizeRiverside(context, AttributeKey.RIGHT));
+            return new SInfoResultFacet(facetIndex, resultIndex, FACET_FLOOD_DURATION_RIGHT, description, I18N_AXIS_LABEL, ComputeType.ADVANCE, id, hash);
+        }
+    }
+
+    public static Facet createMainValueDurationFacet(final CallContext context, final String hash, final String id, final FloodDurationCalculationResult result,
+            final int facetIndex, final int resultIndex, final int dataIndex) {
+
+        final String description = Resources.getMsg(context.getMeta(), FACET_MAIN_VALUE_DURATION_DESCRIPTION, FACET_MAIN_VALUE_DURATION_DESCRIPTION,
+                result.getMainValueLabel(dataIndex));
+
+        return new FloodDurationFacet(facetIndex, resultIndex, dataIndex, FACET_MAIN_VALUE_DURATION, description, ComputeType.ADVANCE, I18N_AXIS_LABEL, hash,
+                id);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        final String facetName = bundle.getFacetName();
+
+        if (FACET_FLOOD_DURATION_LEFT.contentEquals(facetName)) {
+            return buildInfrastructureSeries(generator, bundle, theme, visible, AttributeKey.LEFT);
+        }
+
+        if (FACET_FLOOD_DURATION_RIGHT.contentEquals(facetName))
+            return buildInfrastructureSeries(generator, bundle, theme, visible, AttributeKey.RIGHT);
+
+        if (FACET_MAIN_VALUE_DURATION.contentEquals(facetName)) {
+
+            final AbstractCalculationResult data = getResult(generator, bundle);
+
+            final FloodDurationFacet facet = (FloodDurationFacet) bundle.getFacet();
+            final int index = facet.getWaterlevelIndex();
+
+            if (data instanceof FloodDurationCalculationResult) {
+                final FloodDurationCalculationResult.ValueGetter valuegetter = new ValueGetter() {
+                    @Override
+                    public double getValue(final DurationWaterlevel waterlevel) {
+                        return waterlevel.getFloodDurDaysPerYear();
+                    }
+                };
+                final double[][] points = ((FloodDurationCalculationResult) data).getMainValueDurationPoints(generator, valuegetter, index);
+                return buildStepLineSeriesForType(points, generator, bundle, theme, visible);
+            }
+        }
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    private String buildInfrastructureSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible,
+            final AttributeKey riverside) {
+
+        final FloodDurationCalculationResult data = (FloodDurationCalculationResult) getResult(generator, bundle);
+
+        final double[][] points = data.getInfrastructurePoints(SInfoResultType.floodDuration, riverside);
+
+        return buildSeriesForType(points, generator, bundle, theme, visible, null);
+    }
+}
\ 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/flood_duration/FloodDurationState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,132 @@
+/* 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.flood_duration;
+
+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.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey;
+import org.dive4elements.river.artifacts.states.DefaultState;
+
+/**
+ * Last state of the S-Info flood duration workflow that calculates and outputs the result
+ */
+public class FloodDurationState extends DefaultState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FloodDurationState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 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) {
+        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 = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+
+        final FloodDurationCalculationResults results = (FloodDurationCalculationResults) res.getData();
+        final List<FloodDurationCalculationResult> resultList = results.getResults();
+        int resultIndex = 0;
+        int themeCount = 0;
+        for (final FloodDurationCalculationResult result : resultList) {
+
+            final FloodDurationAccess access = new FloodDurationAccess(sinfo);
+            if ((access.getRiverside() == RiversideChoiceKey.LEFT) || (access.getRiverside() == RiversideChoiceKey.BOTH))
+                facets.add(FloodDurationProcessor.createFloodDurationFacet(context, hash, this.id, result, 0, resultIndex));
+            if ((access.getRiverside() == RiversideChoiceKey.RIGHT) || (access.getRiverside() == RiversideChoiceKey.BOTH))
+                facets.add(FloodDurationProcessor.createFloodDurationFacet(context, hash, this.id, result, 1, resultIndex));
+
+            final int waterlevelCount = result.getWaterlevelCount();
+
+            if ((access.getRiverside() == RiversideChoiceKey.LEFT) || (access.getRiverside() == RiversideChoiceKey.BOTH))
+                facets.add(FloodHeightProcessor.createFloodHeightFacet(context, hash, this.id, result, 0, resultIndex));
+            if ((access.getRiverside() == RiversideChoiceKey.RIGHT) || (access.getRiverside() == RiversideChoiceKey.BOTH))
+                facets.add(FloodHeightProcessor.createFloodHeightFacet(context, hash, this.id, result, 1, resultIndex));
+
+            for (int j = 0; j < waterlevelCount; j++) {
+
+                // final String waterlevelLabel = result.getMainValueLabel(j);
+                // FIXME: use label as label for theme
+
+                // final int facetIndex, final int resultIndex, final int dataIndex
+                facets.add(FloodDurationProcessor.createMainValueDurationFacet(context, hash, this.id, result, themeCount, resultIndex, j));
+                facets.add(FloodHeightProcessor.createMainValueHeightFacet(context, hash, this.id, result, themeCount, resultIndex, j));
+
+                themeCount++;
+            }
+
+            final String nameW = Resources.getMsg(context.getMeta(), "sinfo.chart.flood_duration.curve.w");
+            final String nameQ = Resources.getMsg(context.getMeta(), "sinfo.chart.flood_duration.curve.q");
+            facets.add(FloodDurationCurveProcessor.createFloodDurationWCurveFacet(context, hash, this.id, result, 0, resultIndex, nameW));
+            facets.add(FloodDurationCurveProcessor.createFloodDurationQCurveFacet(context, hash, this.id, result, 1, resultIndex, nameQ));
+
+            facets.add(new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id));
+            facets.add(new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id));
+
+            resultIndex++;
+        }
+
+        final Calculation report = res.getReport();
+        if (report.hasProblems())
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final SINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new FloodDurationCalculation(context).calculate(sinfo);
+    }
+}
\ 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/flood_duration/FloodHeightProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,130 @@
+/** 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.flood_duration;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.common.AbstractSInfoProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultFacet;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationCalculationResult.ValueGetter;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.exports.LongitudinalSectionGenerator;
+import org.dive4elements.river.model.Attribute.AttributeKey;
+import org.dive4elements.river.themes.ThemeDocument;
+
+/**
+ * Processor to generate the facet and data series of infrastructure flood heights
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class FloodHeightProcessor extends AbstractSInfoProcessor {
+
+    private static final String FACET_FLOOD_HEIGHT_LEFT = "sinfo_facet_flood_height.left";
+
+    private static final String FACET_FLOOD_HEIGHT_RIGHT = "sinfo_facet_flood_height.right";
+
+    private static final String FACET_FLOOD_HEIGHT_DESCRIPTION = "sinfo_facet_flood_height.description";
+
+    private static final String FACET_MAIN_VALUE_HEIGHT = "mainvalue.w";
+
+    private static final String FACET_MAIN_VALUE_HEIGHT_DESCRIPTION = "mainvalue.w.description";
+
+    private static final String I18N_AXIS_LABEL = LongitudinalSectionGenerator.I18N_YAXIS_LABEL;
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_FLOOD_HEIGHT_LEFT);
+        HANDLED_FACET_TYPES.add(FACET_FLOOD_HEIGHT_RIGHT);
+        HANDLED_FACET_TYPES.add(FACET_MAIN_VALUE_HEIGHT);
+    }
+
+    public FloodHeightProcessor() {
+        super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES);
+    }
+
+    public static Facet createFloodHeightFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int facetIndex, final int resultIndex) {
+
+        if (facetIndex == 0) {
+            final String description = Resources.getMsg(context.getMeta(), FACET_FLOOD_HEIGHT_DESCRIPTION, FACET_FLOOD_HEIGHT_DESCRIPTION,
+                    SInfoResultType.localizeRiverside(context, AttributeKey.LEFT));
+            return new SInfoResultFacet(facetIndex, resultIndex, FACET_FLOOD_HEIGHT_LEFT, description, I18N_AXIS_LABEL, ComputeType.ADVANCE, id, hash);
+        }
+        else {
+            final String description = Resources.getMsg(context.getMeta(), FACET_FLOOD_HEIGHT_DESCRIPTION, FACET_FLOOD_HEIGHT_DESCRIPTION,
+                    SInfoResultType.localizeRiverside(context, AttributeKey.RIGHT));
+            return new SInfoResultFacet(facetIndex, resultIndex, FACET_FLOOD_HEIGHT_RIGHT, description, I18N_AXIS_LABEL, ComputeType.ADVANCE, id, hash);
+        }
+    }
+
+    public static Facet createMainValueHeightFacet(final CallContext context, final String hash, final String id, final FloodDurationCalculationResult result,
+            final int facetIndex, final int resultIndex, final int dataIndex) {
+        final String description = Resources.getMsg(context.getMeta(), FACET_MAIN_VALUE_HEIGHT_DESCRIPTION, FACET_MAIN_VALUE_HEIGHT_DESCRIPTION,
+                result.getMainValueLabel(dataIndex));
+
+        return new FloodDurationFacet(facetIndex, resultIndex, dataIndex, FACET_MAIN_VALUE_HEIGHT, description, ComputeType.ADVANCE, I18N_AXIS_LABEL, hash, id);
+    }
+
+    @Override
+    protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        final String facetName = bundle.getFacetName();
+
+        if (FACET_FLOOD_HEIGHT_LEFT.contentEquals(facetName)) {
+            return buildInfrastructureSeries(generator, bundle, theme, visible, AttributeKey.LEFT);
+        }
+
+        if (FACET_FLOOD_HEIGHT_RIGHT.contentEquals(facetName))
+            return buildInfrastructureSeries(generator, bundle, theme, visible, AttributeKey.RIGHT);
+
+        if (FACET_MAIN_VALUE_HEIGHT.contentEquals(facetName)) {
+
+            final AbstractCalculationResult data = getResult(generator, bundle);
+
+            final FloodDurationFacet facet = (FloodDurationFacet) bundle.getFacet();
+            final int index = facet.getWaterlevelIndex();
+
+            if (data instanceof FloodDurationCalculationResult) {
+                final FloodDurationCalculationResult.ValueGetter valuegetter = new ValueGetter() {
+                    @Override
+                    public double getValue(final DurationWaterlevel waterlevel) {
+                        return waterlevel.getWaterlevel();
+                    }
+                };
+                final double[][] points = ((FloodDurationCalculationResult) data).getMainValueDurationPoints(generator, valuegetter, index);
+                return buildSeriesForType(points, generator, bundle, theme, visible, null);
+            }
+        }
+
+        final String error = String.format("Unknown facet name: %s", facetName);
+        throw new UnsupportedOperationException(error);
+    }
+
+    private String buildInfrastructureSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible,
+            final AttributeKey riverside) {
+
+        final FloodDurationCalculationResult data = (FloodDurationCalculationResult) getResult(generator, bundle);
+
+        final double[][] points = data.getInfrastructurePoints(SInfoResultType.infrastructureHeight, riverside);
+
+        return buildSeriesForType(points, generator, bundle, theme, visible, null);
+    }
+}
\ 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/flood_duration/InfrastructureAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,52 @@
+/** 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.flood_duration;
+
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+
+/**
+ * Access to the database loaded infrastructure artifact data
+ *
+ * @author Matthias Schäfer
+ */
+final class InfrastructureAccess extends RangeAccess {
+
+    /***** FIELDS *****/
+
+    private Integer id;
+
+    private String name;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public InfrastructureAccess(final D4EArtifact artifact) {
+        super(artifact);
+    }
+
+
+    /***** METHODS *****/
+
+    public Integer getId() {
+        if (this.id == null) {
+            this.id = getInteger("infrastructure_id");
+        }
+        return this.id;
+    }
+
+    public String getName() {
+        if (this.name == null) {
+            this.name = getString("name");
+        }
+        return this.name;
+    }
+}
\ 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/flood_duration/InfrastructureArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,126 @@
+/** 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.flood_duration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.DefaultOutput;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactFactory;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.AbstractStaticStateArtifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.InfrastructureHeightProcessor;
+import org.dive4elements.river.artifacts.states.StaticState;
+import org.w3c.dom.Document;
+
+/**
+ * Display of a infrastructure height data series loaded from database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class InfrastructureArtifact extends AbstractStaticStateArtifact implements FacetTypes {
+
+    /** The log for this class. */
+    private static Logger log = Logger.getLogger(InfrastructureArtifact.class);
+
+    /** Artifact name. */
+    private static final String NAME = "infrastructure";
+
+    static {
+        // TODO: Move to configuration.
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
+    }
+
+    public static final String STATIC_STATE_NAME = "state.infrastructure.static";
+
+    /**
+     * Trivial Constructor.
+     */
+    public InfrastructureArtifact() {
+        log.debug("new InfrastructureArtifact");
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * Gets called from factory, to set things up.
+     */
+    @Override
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
+
+        log.debug("InfrastructureArtifact.setup");
+
+        if (log.isDebugEnabled()) {
+            log.debug(XMLUtils.toString(data));
+        }
+
+        final String code = getDatacageIDValue(data);
+        final String seriesName = (code.split("-").length >= 3) ? code.split("-", 3)[2] : "name?";
+
+        createFacets(callMeta, code, seriesName);
+
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
+
+    private void createFacets(final CallMeta callMeta, final String code, final String seriesName) {
+        if (code == null)
+            return;
+        final String[] parts = code.split("-");
+        if (parts.length < 2) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
+        }
+        addStringData("infrastructure_id", parts[1]);
+        final ArrayList<Facet> facets = new ArrayList<>(2);
+        facets.add(InfrastructureHeightProcessor.createFacet(callMeta, seriesName));
+        addFacets(STATIC_STATE_NAME, facets);
+    }
+
+    @Override
+    protected void initStaticState() {
+
+        log.debug("initStaticState " + getName() + " " + identifier());
+
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
+
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        output.addFacets(facets);
+        state.addOutput(output);
+
+        setStaticState(state);
+    }
+
+    @Override
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
+        // do not clone facets, etc. from master artifact
+
+        log.debug("initialize");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
+
+        log.debug("ld_from " + getDataAsString("ld_from"));
+        log.debug("ld_to " + getDataAsString("ld_to"));
+    }
+}
\ 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/flood_duration/InfrastructureFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,81 @@
+/** 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.flood_duration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.DefaultCalculationResult;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.model.sinfo.Infrastructure;
+import org.dive4elements.river.model.sinfo.InfrastructureValue;
+
+/**
+ * Facet for a infrastructure value series loaded from the database
+ *
+ * @author Matthias Schäfer
+ */
+public class InfrastructureFacet extends BlackboardDataFacet implements FacetTypes {
+
+    private static final long serialVersionUID = 1;
+
+    public InfrastructureFacet(final String name, final String description, final String yAxisLabel) {
+        super(0, name, description);
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", yAxisLabel);
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return
+     *         the data as InfrastructureQueryCalculationResult
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final InfrastructureAccess access = new InfrastructureAccess((D4EArtifact) artifact);
+        final Infrastructure series = Infrastructure.getSeries(access.getId());
+        final List<InfrastructureValue> values = InfrastructureValue.getValues(series, access.getFrom(true), access.getTo(true));
+        final Collection<ResultRow> rows = new ArrayList<>();
+        for (final InfrastructureValue value : values) {
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, value.getStation()) //
+                    .putValue(SInfoResultType.infrastructureHeight, value.getHeight()));
+        }
+        return new DefaultCalculationResult(series.getFilename(), rows);
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public InfrastructureFacet deepCopy() {
+        final InfrastructureFacet copy = new InfrastructureFacet(this.name, this.description, this.metaData.get("Y"));
+        copy.set(this);
+        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/flood_duration/RiversideRadioChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,64 @@
+/* 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.flood_duration;
+
+import java.util.LinkedHashMap;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.states.RadioSelect;
+import org.dive4elements.river.model.Attribute.AttributeKey;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class RiversideRadioChoice extends RadioSelect {
+
+    private static final long serialVersionUID = 1L;
+
+    public enum RiversideChoiceKey {
+        NONE("", AttributeKey.NONE), //
+        LEFT("state.sinfo.riverside.left", AttributeKey.LEFT), //
+        RIGHT("state.sinfo.riverside.right", AttributeKey.RIGHT), //
+        BOTH("state.sinfo.riverside.both", AttributeKey.UNKNOWN);
+
+        private final String key;
+        private final AttributeKey attributeKey;
+
+        RiversideChoiceKey(final String key, final AttributeKey attributeKey) {
+            this.key = key;
+            this.attributeKey = attributeKey;
+        }
+
+        public static RiversideChoiceKey fromKey(final String key) {
+            for (final RiversideChoiceKey v : values()) {
+                if (key.equalsIgnoreCase(v.key))
+                    return v;
+            }
+            return NONE;
+        }
+
+        public String getKey() {
+            return this.key;
+        }
+
+        public AttributeKey getAttributeKey() {
+            return this.attributeKey;
+        }
+    }
+
+    @Override
+    protected LinkedHashMap<String, String> makeEntries(final CallMeta meta, final Artifact artifact) {
+        final LinkedHashMap<String, String> entries = new LinkedHashMap<>();
+        entries.put(RiversideChoiceKey.LEFT.getKey(), null);
+        entries.put(RiversideChoiceKey.RIGHT.getKey(), null);
+        entries.put(RiversideChoiceKey.BOTH.getKey(), null);
+        return entries;
+    }
+}
\ 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/flood_duration/WqinputChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,23 @@
+/* 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.flood_duration;
+
+import org.dive4elements.river.artifacts.states.BooleanChoiceState;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class WqinputChoice extends BooleanChoiceState {
+
+    private static final long serialVersionUID = 1L;
+
+    public WqinputChoice() {
+        super("state.sinfo.wqinput.option", "wspl.active", "wspl.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/flood_duration/WsplChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,23 @@
+/* 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.flood_duration;
+
+import org.dive4elements.river.artifacts.states.BooleanChoiceState;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class WsplChoice extends BooleanChoiceState {
+
+    private static final long serialVersionUID = 1L;
+
+    public WsplChoice() {
+        super("state.sinfo.wspl.option", "state.sinfo.wspl.active", "state.sinfo.wspl.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/flowdepth/FlowDepthAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,57 @@
+/* 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.Collections;
+
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.SinfoCalcMode;
+
+/**
+ * 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
+ */
+final class FlowDepthAccess extends RangeAccess {
+
+    private static final String FIELD_DIFFIDS = "diffids"; //$NON-NLS-1$
+
+    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 = this.artifact.getDataAsBoolean(FIELD_USE_TKH);
+        return useTkh == null ? false : useTkh;
+    }
+
+    public Collection<WstSoundingIdPair> getDifferencePairs() {
+
+        final String diffids = getString(FIELD_DIFFIDS);
+        if (diffids == null) {
+            // Should never happen as this is handled by the ui
+            return Collections.emptyList();
+        }
+
+        return WstSoundingIdPair.parsePairs(diffids);
+    }
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,121 @@
+/* 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 org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+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.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.states.WaterlevelData;
+import org.dive4elements.river.artifacts.states.WaterlevelFetcher;
+import org.dive4elements.river.model.River;
+
+class FlowDepthCalculation {
+
+    // private static Logger log = Logger.getLogger(FloodDurationCalculation.class);
+
+    private final CallContext context;
+
+    public FlowDepthCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+
+        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
+
+        /* access input data */
+        final FlowDepthAccess access = new FlowDepthAccess(sinfo);
+        final River river = access.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+
+        final Collection<WstSoundingIdPair> diffPairs = access.getDifferencePairs();
+
+        final DoubleRange calcRange = access.getRange();
+
+        final boolean useTkh = access.isUseTransportBodies();
+
+        /* calculate results for each diff pair */
+        final Calculation problems = new Calculation();
+
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
+
+        final FlowDepthCalculationResults results = new FlowDepthCalculationResults(calcModeLabel, user, riverInfo, calcRange, useTkh);
+
+        for (final WstSoundingIdPair diffPair : diffPairs) {
+            final FlowDepthCalculationResult result = calculateResult(calcRange, diffPair, problems, infoProvider, useTkh);
+            results.addResult(result, problems);
+        }
+
+        return new CalculationResult(results, problems);
+    }
+
+    /**
+     * Calculates one W-MSH differences pair.
+     *
+     * @param infoProvider
+     */
+    private FlowDepthCalculationResult calculateResult(final DoubleRange calcRange, final WstSoundingIdPair diffPair, final Calculation problems,
+            final RiverInfoProvider infoProvider, final boolean useTkh) {
+
+        /* access real input data from database */
+        final String soundingId = diffPair.getSoundingId();
+        final String wstId = diffPair.getWstId();
+
+        final BedHeightsFinder bedHeight = BedHeightsFinder.forId(this.context, soundingId, calcRange, problems);
+        if (bedHeight == null)
+            return null;
+
+        /* REMARK: fetch ALL wst kms, because we want to determine the original reference gauge */
+        final WaterlevelData waterlevel = new WaterlevelFetcher().findWaterlevel(this.context, wstId, calcRange, problems);
+        if (waterlevel == null)
+            return null;
+
+        final WKms wstKms = waterlevel.getWkms();
+
+        final String wspLabel = wstKms.getName();
+
+        final String soundingLabel = bedHeight.getInfo().getDescription();
+        final String label = String.format("%s - %s", wspLabel, soundingLabel);
+
+        FlowDepthUtils.checkYearDifference(label, waterlevel.getYear(), bedHeight.getInfo().getYear(), problems);
+
+        /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */
+        final RiverInfoProvider riverInfoProvider = infoProvider.forWaterlevel(waterlevel);
+
+        final int wspYear = waterlevel.getYear();
+        final WstInfo wstInfo = new WstInfo(wspLabel, wspYear, riverInfoProvider.getReferenceGauge());
+
+        final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(problems, wstKms);
+        final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wstKms);
+
+        final River river = riverInfoProvider.getRiver();
+        final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(useTkh, problems, label, river, calcRange, waterlevelProvider, dischargeProvider,
+                bedHeight);
+
+        final FlowDepthCalculator calculator = new FlowDepthCalculator(riverInfoProvider, wspLabel, bedHeight, tkhCalculator);
+        return calculator.execute(label, wstInfo, calcRange);
+    }
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,153 @@
+/* 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 org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.AbstractTkhCalculationResult;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+
+/**
+ * Contains the results of a {@link FloodDurationCalculation}.
+ *
+ * @author Gernot Belger
+ */
+
+final class FlowDepthCalculationResult extends AbstractTkhCalculationResult {
+
+    private static final long serialVersionUID = 1L;
+
+    private enum ExportMode { // TODO; nicht ständig kopieren
+        pdf, csv
+    }
+
+    private static final String JASPER_FILE = "/jasper/templates/sinfo.flowdepth.jrxml"; // TODO use jrxml-path all over the project
+
+    private final BedHeightInfo sounding;
+
+    public FlowDepthCalculationResult(final String label, final WstInfo wst, final BedHeightInfo sounding, final boolean hasTkh,
+            final Collection<ResultRow> rows) {
+        super(label, wst, hasTkh, rows);
+
+        this.sounding = sounding;
+
+    }
+
+    public BedHeightInfo getSounding() {
+        return this.sounding;
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+        // getLog().info("FlowDepthExporter.writeCSVHeader");
+
+        final Collection<String> header = new ArrayList<>(11);
+
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.flowdepth));
+
+        if (this.hasTkh()) {
+            header.add(exportContextCSV.msgUnitCSV(SInfoResultType.flowdepthtkh));
+            header.add(exportContextCSV.msgUnitCSV(SInfoResultType.tkh));
+        }
+
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.waterlevel, river.getWstUnit()));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.discharge));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.waterlevelLabel));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.gaugeLabel));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.meanBedHeight));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.soundingLabel));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.location));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+
+        exportContextCSV.writeCSVSoundingMetadata(this.sounding);
+
+        exportContextCSV.writeBlankLine();// .writeNext(new String[] { "" }); // break line
+
+        exportContextCSV.writeCSVWaterlevelMetadata(super.getWst()); // TODO move to super
+
+        exportContextCSV.writeBlankLine();// .writeNext(new String[] { "" }); // break line
+
+    }
+
+    @Override
+    protected String getJasperFile() {
+        return JASPER_FILE;
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+        return formatRow(ExportMode.csv, exportContextCSV, row);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) {
+
+        return formatRow(ExportMode.pdf, exportContextPDF, row);
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
+
+        /* column headings */
+        exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContextPDF.addJRMetadata(source, "flowdepth_header", SInfoResultType.flowdepth);
+        exportContextPDF.addJRMetadata(source, "flowdepth_tkh_header", SInfoResultType.flowdepthtkh);
+        exportContextPDF.addJRMetadata(source, "tkh_header", SInfoResultType.tkh);
+        exportContextPDF.addJRMetadata(source, "waterlevel_header", SInfoResultType.waterlevel);
+        exportContextPDF.addJRMetadata(source, "discharge_header", SInfoResultType.discharge);
+        exportContextPDF.addJRMetadata(source, "waterlevel_name_header", SInfoResultType.waterlevelLabel);
+        exportContextPDF.addJRMetadata(source, "gauge_header", SInfoResultType.gaugeLabel);
+        exportContextPDF.addJRMetadata(source, "bedheight_header", SInfoResultType.meanBedHeight);
+        exportContextPDF.addJRMetadata(source, "sounding_name_header", SInfoResultType.soundingLabel);
+        exportContextPDF.addJRMetadata(source, "location_header", SInfoResultType.location);
+    }
+
+    private String[] formatRow(final ExportMode mode, final IExportContext exportContext, final ResultRow row) {
+
+        final Collection<String> lines = new ArrayList<>(11);
+
+        lines.add(exportContext.formatRowValue(row, GeneralResultType.station));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.flowdepth));
+        final FlowDepthCalculationResults results = exportContext.getResults();
+
+        if (mode == ExportMode.pdf || results.isUseTkh()) {
+            lines.add(exportContext.formatRowValue(row, SInfoResultType.flowdepthtkh));
+            lines.add(exportContext.formatRowValue(row, SInfoResultType.tkh));
+        }
+
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.waterlevel));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.discharge));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.waterlevelLabel));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.gaugeLabel));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.meanBedHeight));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.soundingLabel));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.location));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,37 @@
+/** 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.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Gernot Belger
+ */
+
+final class FlowDepthCalculationResults extends AbstractCalculationResults<FlowDepthCalculationResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final boolean useTkh;
+
+    public FlowDepthCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange,
+            final boolean useTkh) {
+        super(calcModeLabel, user, river, calcRange);
+
+        this.useTkh = useTkh;
+    }
+
+    public boolean isUseTkh() {
+        return this.useTkh;
+    }
+
+}
\ 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/FlowDepthCalculator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,84 @@
+/** 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 org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+
+/**
+ * @author Gernot Belger
+ */
+final class FlowDepthCalculator {
+
+    private final Collection<ResultRow> rows = new ArrayList<>();
+
+    private final BedHeightsFinder bedHeight;
+
+    private final TkhCalculator tkhCalculator;
+
+    private final RiverInfoProvider riverInfoProvider;
+
+    private final String bedHeightLabel;
+
+    private final String wstLabel;
+
+    public FlowDepthCalculator(final RiverInfoProvider riverInfoProvider, final String wstLabel, final BedHeightsFinder bedHeight,
+            final TkhCalculator tkhCalculator) {
+
+        this.riverInfoProvider = riverInfoProvider;
+        this.wstLabel = wstLabel;
+
+        this.bedHeight = bedHeight;
+        this.tkhCalculator = tkhCalculator;
+
+        this.bedHeightLabel = bedHeight.getInfo().getDescription();
+    }
+
+    public FlowDepthCalculationResult execute(final String label, final WstInfo wstInfo, final DoubleRange calcRange) {
+
+        final Collection<Double> stations = this.bedHeight.getStations();
+        for (final Double station : stations) {
+            if (calcRange.containsDouble(station))
+                calculateResultRow(station);
+        }
+
+        final boolean hasTkh = this.tkhCalculator.hasTkh();
+
+        return new FlowDepthCalculationResult(label, wstInfo, this.bedHeight.getInfo(), hasTkh, this.rows);
+    }
+
+    private void calculateResultRow(final double station) {
+
+        final ResultRow row = ResultRow.create();
+
+        row.putValue(SInfoResultType.waterlevelLabel, this.wstLabel);
+        row.putValue(SInfoResultType.soundingLabel, this.bedHeightLabel);
+
+        // REMARK: access the gauge once only during calculation
+        final String gaugeLabel = this.riverInfoProvider.findGauge(station);
+        row.putValue(SInfoResultType.gaugeLabel, gaugeLabel);
+
+        // REMARK: access the location once only during calculation
+        final String location = this.riverInfoProvider.getLocation(station);
+        row.putValue(SInfoResultType.location, location);
+
+        if (this.tkhCalculator.calculateTkh(station, row))
+            this.rows.add(row);
+    }
+}
\ 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/FlowDepthChartExtender.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,74 @@
+/** 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.awt.BasicStroke;
+import java.awt.Stroke;
+
+import org.dive4elements.river.exports.ChartExtender;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.plot.XYPlot;
+
+/**
+ * @author Gernot Belger
+ */
+public class FlowDepthChartExtender implements ChartExtender {
+
+    private static final String TKH_AXIS = "tkhAxis";
+
+    private static final String FLOWDEPTH_AXIS = "flowdepthAxis";
+
+    @Override
+    public void beforeAutoZoom(final DiagramGenerator generator) {
+        final ValueAxis tkhAxis = generator.getAxis(TKH_AXIS);
+        if (tkhAxis != null) {
+            /* If tkh is not the only dataset, we push it to the bottom */
+            final int numYAxes = generator.getNumYAxes();
+            if (numYAxes > 1)
+                tkhAxis.setUpperMargin(4.0);
+        }
+    }
+
+    /**
+     * Synchronizes the location of '0' on the flow-depth-axis with the tkh-axis, by extending the lower bound of the
+     * flow-depth-axis.
+     */
+    @Override
+    public void afterAutoZoom(final DiagramGenerator generator) {
+        final ValueAxis axis1 = generator.getAxis(FLOWDEPTH_AXIS);
+        final ValueAxis axis2 = generator.getAxis(TKH_AXIS);
+        if (axis1 == null || axis2 == null)
+            return;
+
+        final double axis2lb = axis2.getLowerBound();
+        final double axis1ub = axis1.getUpperBound();
+        final double axis2ub = axis2.getUpperBound();
+
+        final double ratio = axis2lb / (axis2ub - axis2lb);
+        final double axis1lbNew = axis1ub / (1 / ratio + 1);
+
+        axis1.setLowerBound(axis1lbNew);
+    }
+
+    @Override
+    public void afterGenerateChart(final DiagramGenerator generator, final XYPlot plot) {
+        final ValueAxis tkhAxis = generator.getAxis(TKH_AXIS);
+        if (tkhAxis != null) {
+            /* show baseline if tkhAxis is present */
+
+            // TODO: it would probably better to configure this via the ChartSettings, but currently no chart settings are loaded,
+            // so it is unclear if that feature still works.
+            final Stroke baselineStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
+            plot.setRangeZeroBaselineStroke(baselineStroke);
+            plot.setRangeZeroBaselineVisible(true);
+        }
+    }
+}
\ 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/FlowDepthExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,45 @@
+/* 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.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.JasperDesigner;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+
+/**
+ * Generates different output formats (csv, pdf) of data that resulted from a flow depths min/max 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 AbstractCommonExporter<FlowDepthCalculationResult, FlowDepthCalculationResults> {
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final FlowDepthCalculationResults results) {
+        exportContext.writeCSVGlobalMetadataDefaults();
+    }
+
+    @Override
+    protected void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+    }
+
+    @Override
+    protected final void configureDesign(final FlowDepthCalculationResult result, final JasperDesigner design) {
+
+        if (result instanceof FlowDepthCalculationResult)
+            if (!result.hasTkh()) {
+                design.removeColumn("tkh");
+                design.removeColumn("flowdepthtkh");
+            }
+    }
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -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.sinfo.common.DatacagePairSelectState;
+
+/**
+ * @author Gernot Belger
+ *
+ */
+// REMARK: very ugly; but probably we will break the serialization of WaterlevelPairSelectState if we introduce an
+// abstraction
+public final class FlowDepthPairSelectState extends DatacagePairSelectState {
+
+    private static final long serialVersionUID = 1L;
+
+    public FlowDepthPairSelectState() {
+        super("sinfo_flowdepth_twin_panel", "diffids");
+    }
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,120 @@
+/* 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.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.TkhProcessor;
+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 long serialVersionUID = 1L;
+
+    /**
+     * 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) {
+        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 = doCompute(sinfo, context, old);
+
+        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);
+
+            /* filtered (zoom dependent mean) flow depth */
+            facets.add(FlowDepthProcessor.createFlowDepthFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthRawFacet(context, hash, this.id, result, index));
+
+            if (results.isUseTkh()) {
+                /* filtered (zoom dependent mean) flow depth including tkh */
+                facets.add(FlowDepthProcessor.createFlowDepthTkhFilteredFacet(context, hash, this.id, result, index));
+                facets.add(FlowDepthProcessor.createFlowDepthTkhRawFacet(context, hash, this.id, result, index));
+
+                facets.add(TkhProcessor.createTkhFacet(context, hash, this.id, result, index));
+            }
+        }
+
+        if (!resultList.isEmpty()) {
+            final Facet csv = new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id);
+            final Facet pdf = new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id);
+
+            facets.add(csv);
+            facets.add(pdf);
+        }
+
+        final Calculation report = res.getReport();
+
+        if (report.hasProblems()) {
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+        }
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final SINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new FlowDepthCalculation(context).calculate(sinfo);
+    }
+}
\ 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/FlowDepthUtils.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,58 @@
+/** 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.model.Calculation;
+
+/**
+ * @author Gernot Belger
+ */
+public final class FlowDepthUtils {
+
+    private FlowDepthUtils() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Checks the year difference between waterlevels and sounding, and issues a warning if too big.
+     *
+     * Zeitraum Zeitliche Differenz [a]
+     * X ≥ 1998 ± 3
+     * 1958 ≤ X < 1998 ± 6
+     * 1918 ≤ X < 1958 ± 12
+     * X < 1918 ± 25
+     */
+    public static void checkYearDifference(final String label, final int wstYear, final int soundingYear, final Calculation problems) {
+
+        if (wstYear < 0)
+            return;
+
+        final int maxDifference = getMaxDifferenceYears(soundingYear);
+
+        final int difference = Math.abs(soundingYear - wstYear);
+        if (difference > maxDifference)
+            problems.addProblem("sinfo_calc_flow_depth.warning.year_difference", label, Integer.toString(wstYear), Integer.toString(soundingYear));
+    }
+
+    public static int getMaxDifferenceYears(final int year) {
+
+        if (year < 1918)
+            return 25;
+
+        if (1918 <= year && year < 1958)
+            return 12;
+
+        if (1958 <= year && year < 1998)
+            return 6;
+
+        /* >= 1998 */
+        return 3;
+    }
+}
\ 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/FlowVelocityKmModelValues.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,207 @@
+/* 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.apache.commons.math.analysis.interpolation.LinearInterpolator;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+
+import gnu.trove.TDoubleArrayList;
+import gnu.trove.TIntArrayList;
+
+/**
+ * Sorted arrays of a station's q, v, and tau model values, running in parallel
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class FlowVelocityKmModelValues {
+
+    /***** FIELDS *****/
+
+    /**
+     * Km
+     */
+    private final double km;
+
+    /**
+     * The station's discharge model values, sorted in ascending order
+     */
+    private final TDoubleArrayList qs;
+
+    /**
+     * Same q values count used to calculate mean
+     */
+    private final TIntArrayList counts;
+
+    /**
+     * The station's main section velocity for the q values
+     */
+    private final TDoubleArrayList vmains;
+
+    /**
+     * The station's shear stress (tau) values for the q values
+     */
+    private final TDoubleArrayList taus;
+
+    /**
+     * Discharge found by the last findQ
+     */
+    private double findQ;
+
+    /**
+     * Velocity found by the last {@link findQ}
+     */
+    private double vmainFound;
+
+    /**
+     * Shear stress found by the last {@link findQ}
+     */
+    private double tauFound;
+
+    /**
+     * Whether qFound has been interpolated
+     */
+    private boolean isInterpolated;
+
+    /**
+     * Real linear interpolator for q and v values
+     */
+    private PolynomialSplineFunction vInterpolator;
+
+    /**
+     * Real linear interpolator for q and tau values
+     */
+    private PolynomialSplineFunction tauInterpolator;
+
+    /***** CONSTRUCTORS *****/
+
+    /**
+     * Constructor with km parameter
+     */
+    public FlowVelocityKmModelValues(final double km) {
+        this.km = km;
+        this.qs = new TDoubleArrayList();
+        this.counts = new TIntArrayList();
+        this.vmains = new TDoubleArrayList();
+        this.taus = new TDoubleArrayList();
+        this.vInterpolator = null;
+        this.tauInterpolator = null;
+    }
+
+    /**
+     * Copy constructor with new km
+     */
+    public FlowVelocityKmModelValues(final double km, final FlowVelocityKmModelValues src) {
+        this(km);
+        src.copyTo(this.qs, this.counts, this.vmains, this.taus);
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Number of the q-v-tau tuples
+     */
+    public int size() {
+        return this.qs.size();
+    }
+
+    /**
+     * Km
+     */
+    public double getKm() {
+        return this.km;
+    }
+
+    /**
+     * Adds all q-v-tau to another set of arrays
+     */
+    void copyTo(final TDoubleArrayList dstqs, final TIntArrayList dstcounts, final TDoubleArrayList dstvmains, final TDoubleArrayList dsttaus) {
+        for (int i = 0; i <= this.qs.size(); i++) {
+            dstqs.add(this.qs.getQuick(i));
+            dstcounts.add(this.counts.getQuick(i));
+            dstvmains.add(this.vmains.getQuick(i));
+            dsttaus.add(this.taus.getQuick(i));
+        }
+    }
+
+    /**
+     * Discharge found by the last {@link findQ}
+     *
+     * @return
+     */
+    public double getFindQ() {
+        return this.findQ;
+    }
+
+    /**
+     * Velocity found by the last {@link findQ}
+     */
+    public double getVmainFound() {
+        return this.vmainFound;
+    }
+
+    /**
+     * Shear stress found by the last {@link findQ}
+     */
+    public double getTauFound() {
+        return this.tauFound;
+    }
+
+    /**
+     * Whether qFound has been interpolated
+     */
+    public boolean getIsInterpolated() {
+        return this.isInterpolated;
+    }
+
+    /**
+     * Adds a q-v-tau value triple, averaging the last values if q duplicates.
+     */
+    public void addValues(final double q, final double vmain, final double tau) {
+        final int j = this.qs.size() - 1;
+        if ((j >= 0) && (q < this.qs.getQuick(j) + 0.001)) {
+            this.qs.setQuick(j, (this.qs.getQuick(j) * this.counts.getQuick(j) + q) / (this.counts.getQuick(j) + 1));
+            this.vmains.setQuick(j, (this.vmains.getQuick(j) * this.counts.getQuick(j) + vmain) / (this.counts.getQuick(j) + 1));
+            this.taus.setQuick(j, (this.taus.getQuick(j) * this.counts.getQuick(j) + tau) / (this.counts.getQuick(j) + 1));
+            this.counts.setQuick(j, this.counts.getQuick(j) + 1);
+        }
+        else {
+            this.qs.add(q);
+            this.counts.add(1);
+            this.vmains.add(vmain);
+            this.taus.add(tau);
+        }
+    }
+
+    /**
+     * Searches a discharge value and returns it or the interpolated value
+     *
+     * @return Found or interpolated discharge, or NaN otherwise
+     */
+    public double findQ(final double q) {
+        if (this.vInterpolator == null) {
+            this.vInterpolator = new LinearInterpolator().interpolate(this.qs.toNativeArray(), this.vmains.toNativeArray());
+            this.tauInterpolator = new LinearInterpolator().interpolate(this.qs.toNativeArray(), this.taus.toNativeArray());
+        }
+
+        this.findQ = q;
+
+        try {
+            this.vmainFound = this.vInterpolator.value(q);
+            this.tauFound = this.tauInterpolator.value(q);
+            return q;
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+            return Double.NaN;
+        }
+    }
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,23 @@
+/* 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 {
+
+    private static final long serialVersionUID = 1L;
+
+    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/flowdepth/WstSoundingIdPair.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,56 @@
+/** 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.backend.utils.StringUtil;
+
+/**
+ * @author Gernot Belger
+ */
+public final class WstSoundingIdPair {
+
+    private final String wstId;
+
+    private final String soundingId;
+
+    public WstSoundingIdPair(final String wstId, final String soundingId) {
+        this.wstId = wstId;
+        this.soundingId = soundingId;
+    }
+
+    public String getWstId() {
+        return this.wstId;
+    }
+
+    public String getSoundingId() {
+        return this.soundingId;
+    }
+
+    public static List<WstSoundingIdPair> parsePairs(final String diffids) {
+
+        // FIXME: this way of parsing the datacage-ids is repeated all over flys!
+        final String datas[] = diffids.split("#");
+
+        final List<WstSoundingIdPair> diffPairs = new ArrayList<>(datas.length);
+
+        for (int i = 0; i < datas.length; i += 2) {
+            final String soundingId = StringUtil.unbracket(datas[i]);
+            final String wstId = StringUtil.unbracket(datas[i + 1]);
+
+            diffPairs.add(new WstSoundingIdPair(wstId, soundingId));
+        }
+
+        return Collections.unmodifiableList(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/flowdepthdev/FlowDepthDevelopmentAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,60 @@
+/* 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.flowdepthdev;
+
+import java.util.List;
+
+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.artifacts.sinfo.flowdepth.WstSoundingIdPair;
+
+/**
+ * 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
+ */
+final class FlowDepthDevelopmentAccess extends RangeAccess {
+
+    static final String FIELD_DIFFID_CURRENT = "diffid_current";
+    static final String FIELD_DIFFID_HIST = "diffid_historical";
+
+    public FlowDepthDevelopmentAccess(final SINFOArtifact artifact) {
+        super(artifact);
+
+        /* assert calculation mode */
+        final SinfoCalcMode calculationMode = artifact.getCalculationMode();
+        assert (calculationMode == SinfoCalcMode.sinfo_calc_flow_depth_minmax);
+    }
+
+    public WstSoundingIdPair getCurrentPair() {
+        return getPair(FIELD_DIFFID_CURRENT);
+    }
+
+    public WstSoundingIdPair getHistoricalPair() {
+        return getPair(FIELD_DIFFID_HIST);
+    }
+
+    private WstSoundingIdPair getPair(final String field) {
+        final String diffids = getString(field);
+
+        /* fetch the raw configured pairs */
+        final List<WstSoundingIdPair> diffPairs = WstSoundingIdPair.parsePairs(diffids);
+
+        if (diffPairs.size() != 1)
+            return null;
+
+        return diffPairs.get(0);
+    }
+}
\ 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/flowdepthdev/FlowDepthDevelopmentCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,227 @@
+/** 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.flowdepthdev;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+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.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthUtils;
+import org.dive4elements.river.artifacts.sinfo.flowdepth.WstSoundingIdPair;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.states.WaterlevelData;
+import org.dive4elements.river.artifacts.states.WaterlevelFetcher;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Gernot Belger
+ */
+final class FlowDepthDevelopmentCalculation {
+
+    private final CallContext context;
+
+    public FlowDepthDevelopmentCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+
+        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
+
+        /* access input data */
+        final FlowDepthDevelopmentAccess access = new FlowDepthDevelopmentAccess(sinfo);
+        final River river = access.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+
+        final WstSoundingIdPair currentPair = access.getCurrentPair();
+        final WstSoundingIdPair histPair = access.getHistoricalPair();
+
+        final DoubleRange calcRange = access.getRange();
+
+        /* calculate results for each diff pair */
+        final Calculation problems = new Calculation();
+
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
+
+        final FlowDepthDevelopmentCalculationResults results = new FlowDepthDevelopmentCalculationResults(calcModeLabel, user, riverInfo, calcRange);
+
+        final FlowDepthDevelopmentCalculationResult result = calculateResult(calcRange, currentPair, histPair, problems, infoProvider);
+        results.addResult(result, problems);
+
+        return new CalculationResult(results, problems);
+    }
+
+    private FlowDepthDevelopmentCalculationResult calculateResult(final DoubleRange calcRange, final WstSoundingIdPair currentPair,
+            final WstSoundingIdPair histPair, final Calculation problems, final RiverInfoProvider infoProvider) {
+
+        /* access real input data from database */
+        final WaterlevelData currentWaterlevel = loadWaterlevel(currentPair, calcRange, problems);
+        if (currentWaterlevel == null)
+            return null;
+
+        final WaterlevelData historicalWaterlevel = loadWaterlevel(histPair, calcRange, problems);
+        if (historicalWaterlevel == null)
+            return null;
+
+        final BedHeightsFinder currentSounding = loadBedHeight(currentPair, calcRange, problems);
+        if (currentSounding == null)
+            return null;
+
+        final BedHeightsFinder historicalSounding = loadBedHeight(histPair, calcRange, problems);
+        if (historicalSounding == null)
+            return null;
+
+        final BedHeightInfo currentSoundingInfo = currentSounding.getInfo();
+        final BedHeightInfo historicalSoundingInfo = historicalSounding.getInfo();
+
+        final int currentWstYear = currentWaterlevel.getYear();
+        final int historicalWstYear = historicalWaterlevel.getYear();
+        final int currentSoundingYear = currentSoundingInfo.getYear();
+        final int historicalSoundingYear = historicalSoundingInfo.getYear();
+
+        if (currentWstYear < 0) {
+            problems.addProblem("flowdepthdevelopmentcalculation.missingCurrentYear", currentWaterlevel.getName());
+            return null;
+        }
+
+        if (historicalWstYear < 0) {
+            problems.addProblem("flowdepthdevelopmentcalculation.missingHistoricalYear", historicalWaterlevel.getName());
+            return null;
+        }
+
+        FlowDepthUtils.checkYearDifference(Resources.getMsg(this.context.getMeta(), "flowdepthdevelopmentcalculation.yearDifferenceCurrent"), currentWstYear,
+                currentSoundingYear, problems);
+        FlowDepthUtils.checkYearDifference(Resources.getMsg(this.context.getMeta(), "flowdepthdevelopmentcalculation.yearDifferenceHistorical"),
+                historicalWstYear,
+                historicalSoundingYear, problems);
+
+        /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */
+        final RiverInfoProvider currentRiverInfoProvider = infoProvider.forWaterlevel(currentWaterlevel);
+        final RiverInfoProvider histRiverInfoProvider = infoProvider.forWaterlevel(historicalWaterlevel);
+
+        final WstInfo currentWstInfo = new WstInfo(currentWaterlevel.getName(), currentWstYear, currentRiverInfoProvider.getReferenceGauge());
+        final WstInfo historicalWstInfo = new WstInfo(historicalWaterlevel.getName(), historicalWstYear, histRiverInfoProvider.getReferenceGauge());
+
+        final WKms currentWkms = currentWaterlevel.getWkms();
+        final WaterlevelValuesFinder currentWstProvider = WaterlevelValuesFinder.fromKms(problems, currentWkms);
+
+        final WKms historicalWkms = historicalWaterlevel.getWkms();
+        final WaterlevelValuesFinder historicalWstProvider = WaterlevelValuesFinder.fromKms(problems, historicalWkms);
+
+        final int currentMeanYear = (currentWstYear + currentSoundingYear) / 2;
+        final int historcialMeanYear = (historicalWstYear + historicalSoundingYear) / 2;
+
+        final double diffYear = currentMeanYear - historcialMeanYear;
+
+        /* real calculation loop */
+        final Collection< ResultRow> rows = new ArrayList<>();
+
+        final Collection<Double> stations = determineCalculationSteps(currentSounding, historicalSounding);
+        for (final double station : stations) {
+            if (calcRange.containsDouble(station)) {
+
+                final double currentWst = currentWstProvider.getWaterlevel(station);
+                final double currentBedHeight = currentSounding.getMeanBedHeight(station);
+
+                final double historicalWst = historicalWstProvider.getWaterlevel(station);
+                final double historicalBedHeight = historicalSounding.getMeanBedHeight(station);
+
+                /* ignore invalid lines */
+                if (Double.isNaN(currentWst) || Double.isNaN(currentBedHeight) || Double.isNaN(historicalWst) || Double.isNaN(historicalBedHeight))
+                    continue;
+
+                final double diffWst = (currentWst - historicalWst) * 100;
+                final double diffBedHeight = (currentBedHeight - historicalBedHeight) * 100;
+
+                final double flowDepthDevelopment = diffWst - diffBedHeight;
+
+                final double flowDepthDevelopmentPerYear = flowDepthDevelopment / diffYear;
+
+                final double currentFlowDepth = currentWst - currentBedHeight;
+                final double historicalFlowDepth = historicalWst - historicalBedHeight;
+
+                // REMARK: access the location once only during calculation
+                final String location = currentRiverInfoProvider.getLocation(station);
+
+                final ResultRow row =  ResultRow.create().//
+                        putValue(GeneralResultType.station, station). //
+                        putValue(SInfoResultType.flowdepthDevelopment, flowDepthDevelopment). //
+                        putValue(SInfoResultType.flowdepthDevelopmentPerYear, flowDepthDevelopmentPerYear). //
+                        putValue(SInfoResultType.waterlevelDifference, diffWst). //
+                        putValue(SInfoResultType.bedHeightDifference, diffBedHeight). //
+                        putValue(SInfoResultType.flowdepthCurrent, currentFlowDepth). //
+                        putValue(SInfoResultType.flowdepthHistorical, historicalFlowDepth). //
+                        putValue(SInfoResultType.location, location);
+                rows.add(row);
+            }
+        }
+
+        final String label = buildLabel(currentWaterlevel, currentSoundingInfo, historicalWaterlevel, historicalSoundingInfo);
+
+        return new FlowDepthDevelopmentCalculationResult(label, currentWstInfo, historicalWstInfo, currentSoundingInfo, historicalSoundingInfo,
+                rows);
+    }
+
+    /**
+     * Calculation steps are simply the union of all stations of all involved bed-height datasets
+     */
+    private Collection<Double> determineCalculationSteps(final BedHeightsFinder currentSounding, final BedHeightsFinder historicalSounding) {
+
+        final Collection<Double> allStations = new TreeSet<>();
+
+        allStations.addAll(currentSounding.getStations());
+        allStations.addAll(historicalSounding.getStations());
+
+        return allStations;
+    }
+
+    private String buildLabel(final WaterlevelData currentWaterlevel, final BedHeightInfo currentSounding, final WaterlevelData historicalWaterlevel,
+            final BedHeightInfo historicalSounding) {
+
+        return new StringBuilder(). //
+                append(currentWaterlevel.getName()). //
+                append('/'). //
+                append(historicalWaterlevel.getName()). //
+                append(" - "). //
+                append(currentSounding.getDescription()). //
+                append('/'). //
+                append(historicalSounding.getDescription()). //
+                toString();
+    }
+
+    /* REMARK: fetch ALL wst kms, because we need to determine the original reference gauge */
+    private WaterlevelData loadWaterlevel(final WstSoundingIdPair pair, final DoubleRange calcRange, final Calculation problems) {
+        final String wstId = pair.getWstId();
+        return new WaterlevelFetcher().findWaterlevel(this.context, wstId, calcRange, problems);
+    }
+
+    private BedHeightsFinder loadBedHeight(final WstSoundingIdPair pair, final DoubleRange calcRange, final Calculation problems) {
+        final String soundingId = pair.getSoundingId();
+        return BedHeightsFinder.forId(this.context, soundingId, calcRange, problems);
+    }
+}
\ 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/flowdepthdev/FlowDepthDevelopmentCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,200 @@
+/* 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.flowdepthdev;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+
+/**
+ * Contains the results of a {@link FloodDurationCalculation}.
+ *
+ * @author Gernot Belger
+ */
+final class FlowDepthDevelopmentCalculationResult extends AbstractCalculationExportableResult {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String CSV_META_HEADER_SOUNDING_CURRENT = "sinfo.export.csv.meta.header.sounding.current";
+
+    private static final String CSV_META_HEADER_SOUNDING_HISTORICAL = "sinfo.export.csv.meta.header.sounding.historical";
+
+    private static final String CSV_META_HEADER_WATERLEVEL_CURRENT = "sinfo.export.csv.meta.header.waterlevel.current";
+
+    private static final String CSV_META_HEADER_WATERLEVEL_HISTORICAL = "sinfo.export.csv.meta.header.waterlevel.historical";
+
+    private static final String JASPER_FILE = "/jasper/templates/sinfo.flowdepthdevelopment.jrxml";
+
+    private final BedHeightInfo currentSounding;
+
+    private final BedHeightInfo historicalSounding;
+
+    private final WstInfo historicalWst;
+
+    private final WstInfo currentWst;
+
+    public FlowDepthDevelopmentCalculationResult(final String label, final WstInfo currentWst, final WstInfo historicalWst, final BedHeightInfo currentSounding,
+            final BedHeightInfo historicalSounding, final Collection<ResultRow> rows) {
+        super(label, rows);
+
+        this.currentWst = currentWst;
+        this.historicalWst = historicalWst;
+
+        this.currentSounding = currentSounding;
+        this.historicalSounding = historicalSounding;
+    }
+
+    public WstInfo getCurrentWst() {
+        return this.currentWst;
+    }
+
+    public WstInfo getHistoricalWst() {
+        return this.historicalWst;
+    }
+
+    public BedHeightInfo getCurrentSounding() {
+        return this.currentSounding;
+    }
+
+    public BedHeightInfo getHistoricalSounding() {
+        return this.historicalSounding;
+    }
+
+    public String getWaterlevelDifferenceLabel() {
+        return new StringBuilder(). //
+                append(this.currentWst.getLabel()). //
+                append(" - "). //
+                append(this.historicalWst.getLabel()). //
+                toString();
+    }
+
+    public String getBedHeightDifferenceLabel() {
+        return new StringBuilder(). //
+                append(this.currentSounding.getDescription()). //
+                append(" - "). //
+                append(this.historicalSounding.getDescription()). //
+                toString();
+    }
+
+    public String getFlowDepthCurrentLabel() {
+        return new StringBuilder(). //
+                append(this.currentWst.getLabel()). //
+                append(" - "). //
+                append(this.currentSounding.getDescription()). //
+                toString();
+    }
+
+    public String getFlowDepthHistoricalLabel() {
+        return new StringBuilder(). //
+                append(this.historicalWst.getLabel()). //
+                append(" - "). //
+                append(this.historicalSounding.getDescription()). //
+                toString();
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+
+        exportContextCSV.writeCSVSoundingMetadata(getCurrentSounding(), CSV_META_HEADER_SOUNDING_CURRENT);
+        exportContextCSV.writeBlankLine();
+        exportContextCSV.writeCSVWaterlevelMetadata(getCurrentWst(), CSV_META_HEADER_WATERLEVEL_CURRENT);
+        exportContextCSV.writeBlankLine();
+        exportContextCSV.writeCSVSoundingMetadata(getHistoricalSounding(), CSV_META_HEADER_SOUNDING_HISTORICAL);
+        exportContextCSV.writeBlankLine();
+        exportContextCSV.writeCSVWaterlevelMetadata(getHistoricalWst(), CSV_META_HEADER_WATERLEVEL_HISTORICAL);
+        exportContextCSV.writeBlankLine();
+
+    }
+
+    @Override
+    protected String getJasperFile() {
+        return JASPER_FILE;
+    }
+
+    protected String[] formatRow(final IExportContext exportContext, final ResultRow row) {
+
+        final Collection<String> lines = new ArrayList<>(10);
+
+        lines.add(exportContext.formatRowValue(row, GeneralResultType.station));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.flowdepthDevelopment));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.flowdepthDevelopmentPerYear));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.waterlevelDifference));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.bedHeightDifference));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.flowdepthCurrent));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.flowdepthHistorical));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.location));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final Collection<String> header = new ArrayList<>(11);
+
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.flowdepthDevelopment, SInfoResultType.flowdepthDevelopment.getUnit()));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.flowdepthDevelopmentPerYear, SInfoResultType.flowdepthDevelopmentPerYear.getUnit()));
+        header.add(exportContextCSV.msgUnitLabel(SInfoResultType.waterlevelDifference, getWaterlevelDifferenceLabel()));
+        header.add(exportContextCSV.msgUnitLabel(SInfoResultType.bedHeightDifference, getBedHeightDifferenceLabel()));
+        header.add(exportContextCSV.msgUnitLabel(SInfoResultType.flowdepthCurrent, getFlowDepthCurrentLabel()));
+        header.add(exportContextCSV.msgUnitLabel(SInfoResultType.flowdepthHistorical, getFlowDepthHistoricalLabel()));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.location));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return this.formatRow(exportContextCSV, row);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) {
+
+        return this.formatRow(exportContextPDF, row);
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
+        /* column headings */
+        exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContextPDF.addJRMetadata(source, "flowdepthdevelopment_header", SInfoResultType.flowdepthDevelopment);
+        exportContextPDF.addJRMetadata(source, "flowdepthdevelopmentperyear_header", SInfoResultType.flowdepthDevelopmentPerYear);
+
+        exportContextPDF.addJRMetadata(source, "waterleveldifference_header", SInfoResultType.waterlevelDifference);
+        exportContextPDF.addJRMetadata(source, "waterleveldifference_header2", getWaterlevelDifferenceLabel());
+
+        exportContextPDF.addJRMetadata(source, "bedheightdifference_header", SInfoResultType.bedHeightDifference);
+        exportContextPDF.addJRMetadata(source, "bedheightdifference_header2", getBedHeightDifferenceLabel());
+
+        exportContextPDF.addJRMetadata(source, "flowdepthcurrent_header", SInfoResultType.flowdepthCurrent);
+        exportContextPDF.addJRMetadata(source, "flowdepthcurrent_header2", getFlowDepthCurrentLabel());
+
+        exportContextPDF.addJRMetadata(source, "flowdepthhistorical_header", SInfoResultType.flowdepthHistorical);
+        exportContextPDF.addJRMetadata(source, "flowdepthhistorical_header2", getFlowDepthHistoricalLabel());
+
+        exportContextPDF.addJRMetadata(source, "location_header", SInfoResultType.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/flowdepthdev/FlowDepthDevelopmentCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.artifacts.sinfo.flowdepthdev;
+
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Gernot Belger
+ */
+final class FlowDepthDevelopmentCalculationResults extends AbstractCalculationResults<FlowDepthDevelopmentCalculationResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    public FlowDepthDevelopmentCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) {
+        super(calcModeLabel, user, river, calcRange);
+    }
+
+    /**
+     * We know that this type of results only has one result member, so we can directly access it.
+     */
+    public FlowDepthDevelopmentCalculationResult getResult() {
+        final List<FlowDepthDevelopmentCalculationResult> results = getResults();
+        if (results.size() < 1)
+            return null;
+
+        return results.get(0);
+    }
+}
\ 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/flowdepthdev/FlowDepthDevelopmentExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,46 @@
+/* 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.flowdepthdev;
+
+import org.dive4elements.river.artifacts.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.JasperDesigner;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+
+/**
+ * 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 FlowDepthDevelopmentExporter extends AbstractCommonExporter<FlowDepthDevelopmentCalculationResult, FlowDepthDevelopmentCalculationResults> {
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final FlowDepthDevelopmentCalculationResults results) {
+        exportContext.writeCSVGlobalMetadataDefaults();
+
+    }
+
+    @Override
+    protected void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+        source.addMetaData("flowdepthdevelopment_header_label", SInfoResultType.flowdepthDevelopment.getCsvHeader(this.context.getMeta()));// (this.context.getMeta()));
+
+    }
+
+    @Override
+    protected void configureDesign(final FlowDepthDevelopmentCalculationResult result, final JasperDesigner design) {
+        if (result instanceof FlowDepthDevelopmentCalculationResult) { // redundant, but type might change
+            design.getSource().addMetaData("flowdepthdevelopment", result.getLabel()); // globalMeta? wrong place. only one result expected, so it works
+        }
+    }
+}
\ 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/flowdepthdev/FlowDepthDevelopmentState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,117 @@
+/** 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.flowdepthdev;
+
+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.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthDevelopmentPerYearProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthDevelopmentProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthProcessor;
+import org.dive4elements.river.artifacts.states.DefaultState;
+
+/**
+ * @author Gernot Belger
+ */
+public class FlowDepthDevelopmentState extends DefaultState {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 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 = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+
+        final FlowDepthDevelopmentCalculationResults results = (FlowDepthDevelopmentCalculationResults) res.getData();
+        final FlowDepthDevelopmentCalculationResult result = results.getResult();
+        if (result != null) {
+            // final FlowDepthDevelopmentCalculationResult result = (FlowDepthDevelopmentCalculationResult) resultList.get(0);
+            /* add themes for chart, for each result */
+            final int index = 0;
+
+            // /* filtered (zoom dependent mean) flow depth development */
+            facets.add(FlowDepthDevelopmentProcessor.createFlowDepthDevelopmentFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthDevelopmentProcessor.createFlowDepthDevelopmentRawFacet(context, hash, this.id, result, index));
+
+            facets.add(FlowDepthDevelopmentPerYearProcessor.createFlowDepthDevelopmentFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthDevelopmentPerYearProcessor.createFlowDepthDevelopmentRawFacet(context, hash, this.id, result, index));
+
+            facets.add(FlowDepthDevelopmentProcessor.createWaterlevelDifferenceFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthDevelopmentProcessor.createBedHeightDifferenceFacet(context, hash, this.id, result, index));
+
+            facets.add(FlowDepthProcessor.createFlowDepthCurrentFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthCurrentRawFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthHistoricalFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthHistoricalRawFacet(context, hash, this.id, result, index));
+
+            facets.add(new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id));
+            facets.add(new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id));
+        }
+
+        final Calculation report = res.getReport();
+        if (report.hasProblems())
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final SINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new FlowDepthDevelopmentCalculation(context).calculate(sinfo);
+    }
+}
\ 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/flowdepthdev/WaterlevelSoundingCurrentPairSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.flowdepthdev;
+
+import org.dive4elements.river.artifacts.sinfo.common.DatacagePairSelectState;
+
+/**
+ * @author Gernot Belger
+ *
+ */
+// REMARK: very ugly; but probably we will break the serialization of WaterlevelPairSelectState if we introduce an
+// abstraction
+public final class WaterlevelSoundingCurrentPairSelectState extends DatacagePairSelectState {
+
+    private static final long serialVersionUID = 1L;
+
+    public WaterlevelSoundingCurrentPairSelectState() {
+        super("sinfo_flowdepth_twin_panel", FlowDepthDevelopmentAccess.FIELD_DIFFID_CURRENT);
+    }
+}
\ 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/flowdepthdev/WaterlevelSoundingHistoricalPairSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,26 @@
+/** 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.flowdepthdev;
+
+import org.dive4elements.river.artifacts.sinfo.common.DatacagePairSelectState;
+
+/**
+ * @author Gernot Belger
+ */
+// REAMRK: very ugly; but probably we will break the serialization of WaterlevelPairSelectState if we introduce an
+// abstraction
+public final class WaterlevelSoundingHistoricalPairSelectState extends DatacagePairSelectState {
+
+    private static final long serialVersionUID = 1L;
+
+    public WaterlevelSoundingHistoricalPairSelectState() {
+        super("sinfo_flowdepth_twin_panel", FlowDepthDevelopmentAccess.FIELD_DIFFID_HIST);
+    }
+}
\ 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/flowdepthminmax/FlowDepthMinMaxAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,44 @@
+/* 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.flowdepthminmax;
+
+import java.util.Collection;
+
+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.artifacts.sinfo.flowdepth.WstSoundingIdPair;
+
+/**
+ * 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
+ */
+final class FlowDepthMinMaxAccess extends RangeAccess {
+
+    private static final String FIELD_DIFFIDS = "diffids";
+
+    public FlowDepthMinMaxAccess(final SINFOArtifact artifact) {
+        super(artifact);
+
+        /* assert calculation mode */
+        final SinfoCalcMode calculationMode = artifact.getCalculationMode();
+        assert (calculationMode == SinfoCalcMode.sinfo_calc_flow_depth_minmax);
+    }
+
+    public Collection<WstSoundingIdPair> getMinMaxPairs() {
+        final String diffids = getString(FIELD_DIFFIDS);
+        return WstSoundingIdPair.parsePairs(diffids);
+    }
+}
\ 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/flowdepthminmax/FlowDepthMinMaxCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,175 @@
+/** 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.flowdepthminmax;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+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.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthUtils;
+import org.dive4elements.river.artifacts.sinfo.flowdepth.WstSoundingIdPair;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.states.WaterlevelData;
+import org.dive4elements.river.artifacts.states.WaterlevelFetcher;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Gernot Belger
+ */
+final class FlowDepthMinMaxCalculation {
+
+    private final CallContext context;
+
+    public FlowDepthMinMaxCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+
+        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
+
+        /* access input data */
+        final FlowDepthMinMaxAccess access = new FlowDepthMinMaxAccess(sinfo);
+        final River river = access.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+
+        final Collection<WstSoundingIdPair> minMaxPairs = access.getMinMaxPairs();
+
+        final DoubleRange calcRange = access.getRange();
+
+        /* calculate results for each diff pair */
+        final Calculation problems = new Calculation();
+
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
+
+        final FlowDepthMinMaxCalculationResults results = new FlowDepthMinMaxCalculationResults(calcModeLabel, user, riverInfo, calcRange);
+
+        for (final WstSoundingIdPair minMaxPair : minMaxPairs) {
+            final FlowDepthMinMaxCalculationResult result = calculateResult(calcRange, minMaxPair, problems, infoProvider);
+            results.addResult(result, problems);
+        }
+
+        return new CalculationResult(results, problems);
+    }
+
+    /**
+     * Calculates one W-MSH differences pair.
+     *
+     * @param infoProvider
+     */
+    private FlowDepthMinMaxCalculationResult calculateResult(final DoubleRange calcRange, final WstSoundingIdPair minMaxPair, final Calculation problems,
+            final RiverInfoProvider infoProvider) {
+
+        /* access real input data from database */
+        final String wstId = minMaxPair.getWstId();
+
+        final String soundingId = minMaxPair.getSoundingId();
+
+        final BedHeightsFinder bedHeight = BedHeightsFinder.forId(this.context, soundingId, calcRange, problems);
+        if (bedHeight == null)
+            return null;
+
+        /* REMARK: fetch ALL wst kms, because we want to determine the original reference gauge */
+        final WaterlevelData waterlevel = new WaterlevelFetcher().findWaterlevel(this.context, wstId, calcRange, problems);
+        if (waterlevel == null)
+            return null;
+
+        final String label = createLabel(waterlevel, bedHeight);
+
+        final WKms wstKms = waterlevel.getWkms();
+
+        final BedHeightInfo bedHeightInfo = bedHeight.getInfo();
+
+        final int soundingYear = bedHeightInfo.getYear();
+        FlowDepthUtils.checkYearDifference(label, waterlevel.getYear(), soundingYear, problems);
+
+        /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */
+        final RiverInfoProvider riverInfoProvider = infoProvider.forWaterlevel(waterlevel);
+
+        final int wspYear = waterlevel.getYear();
+        final WstInfo wstInfo = new WstInfo(waterlevel.getName(), wspYear, riverInfoProvider.getReferenceGauge());
+
+        final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(problems, wstKms);
+        final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wstKms);
+
+        final String waterlevelLabel = waterlevel.getName();
+        final String soundingLabel = bedHeightInfo.getDescription();
+
+        /* real calculation loop */
+        final Collection< ResultRow> rows = new ArrayList<>();
+
+        final Collection<Double> stations = bedHeight.getStations();
+        for (final double station : stations) {
+            if (calcRange.containsDouble(station)) {
+
+                final double wst = waterlevelProvider.getWaterlevel(station);
+                final double discharge = dischargeProvider.getDischarge(station);
+
+                final double minBedHeightValue = bedHeight.getMinBedHeight(station);
+                final double maxBedHeightValue = bedHeight.getMaxBedHeight(station);
+                final double meanBedHeight = bedHeight.getMeanBedHeight(station);
+
+                final double minFlowDepth = wst - maxBedHeightValue;
+                final double maxFlowDepth = wst - minBedHeightValue;
+
+                // REMARK: access the location once only during calculation
+                final String location = riverInfoProvider.getLocation(station);
+
+                // REMARK: access the gauge once only during calculation
+                final String gaugeLabel = riverInfoProvider.findGauge(station);
+
+                /* ignore invalid lines */
+                if (Double.isNaN(wst) || Double.isNaN(minBedHeightValue) || Double.isNaN(maxBedHeightValue))
+                    continue;
+
+                final  ResultRow row =  ResultRow.create().//
+                        putValue(GeneralResultType.station, station). //
+                        putValue(SInfoResultType.flowdepthmin, minFlowDepth). //
+                        putValue(SInfoResultType.flowdepthmax, maxFlowDepth). //
+                        putValue(SInfoResultType.waterlevel, wst). //
+                        putValue(SInfoResultType.discharge, discharge). //
+                        putValue(SInfoResultType.waterlevelLabel, waterlevelLabel). //
+                        putValue(SInfoResultType.gaugeLabel, gaugeLabel). //
+                        putValue(SInfoResultType.meanBedHeight, meanBedHeight). //
+                        putValue(SInfoResultType.soundingLabel, soundingLabel). //
+                        putValue(SInfoResultType.location, location);
+                rows.add(row);
+            }
+        }
+
+        return new FlowDepthMinMaxCalculationResult(label, wstInfo, bedHeightInfo, rows);
+    }
+
+    private String createLabel(final WaterlevelData waterlevel, final BedHeightsFinder bedHeight) {
+
+        return new StringBuilder(waterlevel.getName()). //
+                append(" - "). //
+                append(bedHeight.getInfo().getDescription()). //
+                toString();
+    }
+}
\ 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/flowdepthminmax/FlowDepthMinMaxCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,139 @@
+/* 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.flowdepthminmax;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+
+/**
+ * Contains the results of a {@link FloodDurationCalculation}.
+ *
+ * @author Gernot Belger
+ */
+final class FlowDepthMinMaxCalculationResult extends AbstractCalculationExportableResult {
+
+    private static final long serialVersionUID = 1L;
+    private static final String JASPER_FILE = "/jasper/templates/sinfo.flowdepthminmax.jrxml";
+
+    private final BedHeightInfo sounding;
+    private final WstInfo wst;
+
+    public FlowDepthMinMaxCalculationResult(final String label, final WstInfo wst, final BedHeightInfo sounding, final Collection<ResultRow> rows) {
+        super(label, rows);
+        this.wst = wst;
+        this.sounding = sounding;
+    }
+
+    public BedHeightInfo getSounding() {
+        return this.sounding;
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final Collection<String> header = new ArrayList<>(11);
+
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.flowdepthmin));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.flowdepthmax));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.waterlevel, river.getWstUnit()));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.discharge));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.waterlevelLabel));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.gaugeLabel));
+        header.add(exportContextCSV.msgUnitCSV(SInfoResultType.meanBedHeight, river.getWstUnit()));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.soundingLabel));
+        header.add(exportContextCSV.formatCsvHeader(SInfoResultType.location));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+
+        exportContextCSV.writeCSVSoundingMetadata(this.sounding);
+        exportContextCSV.writeBlankLine();
+
+        exportContextCSV.writeCSVWaterlevelMetadata(this.wst);
+        exportContextCSV.writeBlankLine();
+
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return formatRow(exportContextCSV, row);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) {
+
+        return formatRow(exportContextPDF, row);
+    }
+
+    @Override
+    protected String getJasperFile() {
+        return this.JASPER_FILE;
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
+
+        /* column headings */
+        exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContextPDF.addJRMetadata(source, "flowdepthmin_header", SInfoResultType.flowdepthmin);
+        exportContextPDF.addJRMetadata(source, "flowdepthmax_header", SInfoResultType.flowdepthmax);
+        exportContextPDF.addJRMetadata(source, "waterlevel_header", SInfoResultType.waterlevel);
+        exportContextPDF.addJRMetadata(source, "discharge_header", SInfoResultType.discharge);
+        exportContextPDF.addJRMetadata(source, "waterlevel_name_header", SInfoResultType.waterlevelLabel);
+        exportContextPDF.addJRMetadata(source, "gauge_header", SInfoResultType.gaugeLabel);
+        exportContextPDF.addJRMetadata(source, "bedheight_header", SInfoResultType.meanBedHeight);
+        exportContextPDF.addJRMetadata(source, "sounding_name_header", SInfoResultType.soundingLabel);
+        exportContextPDF.addJRMetadata(source, "location_header", SInfoResultType.location);
+
+    }
+
+    protected String[] formatRow(final IExportContext exportContextCSV, final ResultRow row) {
+
+        final Collection<String> lines = new ArrayList<>(10);
+
+        lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.station));
+
+        // REMARK: null check as pdf will call this with null and in that case we show all columns (to avoid multiple jasper
+        // FIXME: does not work like this: we may have several pairs of min/max; so we need to look at all of them?
+        // templates)
+        // if (result == null || result.getMinSounding() != null)
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.flowdepthmin));
+        // if (result == null || result.getMaxSounding() != null)
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.flowdepthmax));
+
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.waterlevel));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.discharge));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.waterlevelLabel));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.gaugeLabel));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.meanBedHeight));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.soundingLabel));
+        lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.location));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+}
\ 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/flowdepthminmax/FlowDepthMinMaxCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,26 @@
+/** 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.flowdepthminmax;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Gernot Belger
+ */
+final class FlowDepthMinMaxCalculationResults extends AbstractCalculationResults<FlowDepthMinMaxCalculationResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    public FlowDepthMinMaxCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) {
+        super(calcModeLabel, user, river, calcRange);
+    }
+}
\ 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/flowdepthminmax/FlowDepthMinMaxExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,35 @@
+/* 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.flowdepthminmax;
+
+import org.dive4elements.river.artifacts.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+
+/**
+ * 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 FlowDepthMinMaxExporter extends AbstractCommonExporter<FlowDepthMinMaxCalculationResult, FlowDepthMinMaxCalculationResults> {
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final FlowDepthMinMaxCalculationResults results) {
+        exportContext.writeCSVGlobalMetadataDefaults();
+
+    }
+
+    @Override
+    protected void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+    }
+}
\ 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/flowdepthminmax/FlowDepthMinMaxPairSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.flowdepthminmax;
+
+import org.dive4elements.river.artifacts.sinfo.common.DatacagePairSelectState;
+
+/**
+ * @author Gernot Belger
+ *
+ */
+// FIXME: very ugly; but probably we will break the serialization of WaterlevelPairSelectState if we introduce an
+// abstraction
+public final class FlowDepthMinMaxPairSelectState extends DatacagePairSelectState {
+
+    private static final long serialVersionUID = 1L;
+
+    public FlowDepthMinMaxPairSelectState() {
+        super("sinfo_flowdepthminmax_twin_panel", "diffids");
+    }
+}
\ 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/flowdepthminmax/FlowDepthMinMaxState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,109 @@
+/* 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.flowdepthminmax;
+
+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.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthProcessor;
+import org.dive4elements.river.artifacts.states.DefaultState;
+
+/** State in which a waterlevel has been calculated. */
+public class FlowDepthMinMaxState extends DefaultState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FlowDepthState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 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 = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+
+        final FlowDepthMinMaxCalculationResults results = (FlowDepthMinMaxCalculationResults) res.getData();
+
+        /* add themes for chart, for each result */
+        final List<FlowDepthMinMaxCalculationResult> resultList = results.getResults();
+        for (int index = 0; index < resultList.size(); index++) {
+
+            final FlowDepthMinMaxCalculationResult result = resultList.get(index);
+
+            /* filtered (zoom dependent mean) flow depth */
+            facets.add(FlowDepthProcessor.createFlowDepthMinFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthMinRawFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthMaxFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthMaxRawFacet(context, hash, this.id, result, index));
+        }
+
+        if (!resultList.isEmpty()) {
+            facets.add(new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id));
+            facets.add(new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id));
+        }
+
+        final Calculation report = res.getReport();
+        if (report.hasProblems())
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final SINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new FlowDepthMinMaxCalculation(context).calculate(sinfo);
+    }
+}
\ 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/predefinedchannel/PredefinedChannelAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,50 @@
+/** 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.predefinedchannel;
+
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+
+/**
+ * Access to the database loaded channel artifact data
+ *
+ * @author Matthias Schäfer
+ */
+final class PredefinedChannelAccess extends RangeAccess {
+
+    /***** FIELDS *****/
+
+    private Integer id;
+
+    private String name;
+
+    /***** CONSTRUCTORS *****/
+
+    public PredefinedChannelAccess(final D4EArtifact artifact) {
+        super(artifact);
+    }
+
+    /***** METHODS *****/
+
+    public Integer getId() {
+        if (this.id == null) {
+            this.id = getInteger("channel_id");
+        }
+        return this.id;
+    }
+
+    public String getName() {
+        if (this.name == null) {
+            this.name = getString("name");
+        }
+        return this.name;
+    }
+}
\ 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/predefinedchannel/PredefinedChannelArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,128 @@
+/** 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.predefinedchannel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.DefaultOutput;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactFactory;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.AbstractStaticStateArtifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.PredefinedChannelDepthProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.PredefinedChannelWidthProcessor;
+import org.dive4elements.river.artifacts.states.StaticState;
+import org.w3c.dom.Document;
+
+/**
+ * Display of a river channel data series loaded from database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedChannelArtifact extends AbstractStaticStateArtifact implements FacetTypes {
+
+    /** The log for this class. */
+    private static Logger log = Logger.getLogger(PredefinedChannelArtifact.class);
+
+    /** Artifact name. */
+    private static final String NAME = "channel";
+
+    static {
+        // TODO: Move to configuration.
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
+    }
+
+    public static final String STATIC_STATE_NAME = "state.predefined_channel.static";
+
+    /**
+     * Trivial Constructor.
+     */
+    public PredefinedChannelArtifact() {
+        log.debug("new PredefinedChannelArtifact");
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * Gets called from factory, to set things up.
+     */
+    @Override
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
+
+        log.debug("PredefinedChannelArtifact.setup");
+
+        if (log.isDebugEnabled()) {
+            log.debug(XMLUtils.toString(data));
+        }
+
+        final String code = getDatacageIDValue(data);
+        final String seriesName = (code.split("-").length >= 3) ? code.split("-", 3)[2] : "name?";
+
+        createFacets(callMeta, code, seriesName);
+
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
+
+    private void createFacets(final CallMeta callMeta, final String code, final String seriesName) {
+        if (code == null)
+            return;
+        final String[] parts = code.split("-");
+        if (parts.length < 2) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
+        }
+        addStringData("channel_id", parts[1]);
+        final ArrayList<Facet> facets = new ArrayList<>(2);
+        facets.add(PredefinedChannelDepthProcessor.createFacet(callMeta, seriesName));
+        facets.add(PredefinedChannelWidthProcessor.createFacet(callMeta, seriesName));
+        addFacets(STATIC_STATE_NAME, facets);
+    }
+
+    @Override
+    protected void initStaticState() {
+
+        log.debug("initStaticState " + getName() + " " + identifier());
+
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
+
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        output.addFacets(facets);
+        state.addOutput(output);
+
+        setStaticState(state);
+    }
+
+    @Override
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
+        // do not clone facets, etc. from master artifact
+
+        log.debug("initialize");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
+
+        log.debug("ld_from " + getDataAsString("ld_from"));
+        log.debug("ld_to " + getDataAsString("ld_to"));
+    }
+}
\ 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/predefinedchannel/PredefinedChannelFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,82 @@
+/** 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.predefinedchannel;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.DefaultCalculationResult;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.model.sinfo.Channel;
+import org.dive4elements.river.model.sinfo.ChannelValue;
+
+/**
+ * Facet for a river channel value series loaded from the database
+ *
+ * @author Matthias Schäfer
+ */
+public class PredefinedChannelFacet extends BlackboardDataFacet implements FacetTypes {
+
+    private static final long serialVersionUID = 56753318291306671L;
+
+    public PredefinedChannelFacet(final String name, final String description, final String yAxisLabel) {
+        super(0, name, description);
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", yAxisLabel);
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return
+     *         the data as PredefinedChannelQueryCalculationResult
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final PredefinedChannelAccess access = new PredefinedChannelAccess((D4EArtifact) artifact);
+        final Channel series = Channel.getSeries(access.getId());
+        final List<ChannelValue> values = ChannelValue.getValues(series, access.getFrom(true), access.getTo(true));
+        final Collection<ResultRow> rows = new ArrayList<>();
+        for (final ChannelValue value : values) {
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, value.getStation()) //
+                    .putValue(SInfoResultType.channelWidth, value.getWidth()) //
+                    .putValue(SInfoResultType.channelDepth, value.getDepth()));
+        }
+        return new DefaultCalculationResult(series.getFilename(), rows);
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public PredefinedChannelFacet deepCopy() {
+        final PredefinedChannelFacet copy = new PredefinedChannelFacet(this.name, this.description, this.metaData.get("Y"));
+        copy.set(this);
+        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/predefineddepthevol/PredefinedDepthEvolAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,50 @@
+/** 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.predefineddepthevol;
+
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+
+/**
+ * Access to the database loaded depth evolution artifact data
+ *
+ * @author Matthias Schäfer
+ */
+final class PredefinedDepthEvolAccess extends RangeAccess {
+
+    /***** FIELDS *****/
+
+    private Integer id;
+
+    private String name;
+
+    /***** CONSTRUCTORS *****/
+
+    public PredefinedDepthEvolAccess(final D4EArtifact artifact) {
+        super(artifact);
+    }
+
+    /***** METHODS *****/
+
+    public Integer getId() {
+        if (this.id == null) {
+            this.id = getInteger("depthevol_id");
+        }
+        return this.id;
+    }
+
+    public String getName() {
+        if (this.name == null) {
+            this.name = getString("name");
+        }
+        return this.name;
+    }
+}
\ 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/predefineddepthevol/PredefinedDepthEvolArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,130 @@
+/** 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.predefineddepthevol;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.DefaultOutput;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactFactory;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.AbstractStaticStateArtifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.PredefinedDepthEvolPerYearProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.PredefinedDepthEvolProcessor;
+import org.dive4elements.river.artifacts.states.StaticState;
+import org.w3c.dom.Document;
+
+/**
+ * Display of a depth evolution data series loaded from database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedDepthEvolArtifact extends AbstractStaticStateArtifact implements FacetTypes {
+
+    /** The log for this class. */
+    private static Logger log = Logger.getLogger(PredefinedDepthEvolArtifact.class);
+
+    /** Artifact name. */
+    private static final String NAME = "depth_evol";
+
+    static {
+        // TODO: Move to configuration.
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
+    }
+
+    public static final String STATIC_STATE_NAME = "state.predefined_depthevol.static";
+
+    /**
+     * Trivial Constructor.
+     */
+    public PredefinedDepthEvolArtifact() {
+        log.debug("new PredefinedDepthEvolArtifact");
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * Gets called from factory, to set things up.
+     */
+    @Override
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
+
+        log.debug("PredefinedDepthEvolArtifact.setup");
+
+        if (log.isDebugEnabled()) {
+            log.debug(XMLUtils.toString(data));
+        }
+
+        // FIXME Irgendwie muss es doch möglich sein, an das name-Attribut aus meta-data.xml ranzukommen
+        // (jetzt provisorisch in ids untergebracht)
+        final String code = getDatacageIDValue(data);
+        final String seriesName = (code.split("-").length >= 3) ? code.split("-", 3)[2] : "name?";
+
+        createFacets(callMeta, code, seriesName);
+
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
+
+    private void createFacets(final CallMeta callMeta, final String code, final String seriesName) {
+        if (code == null)
+            return;
+        final String[] parts = code.split("-");
+        if (parts.length < 2) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
+        }
+        addStringData("depthevol_id", parts[1]);
+        final ArrayList<Facet> facets = new ArrayList<>(2);
+        facets.add(PredefinedDepthEvolProcessor.createFacet(callMeta, seriesName));
+        facets.add(PredefinedDepthEvolPerYearProcessor.createFacet(callMeta, seriesName));
+        addFacets(STATIC_STATE_NAME, facets);
+    }
+
+    @Override
+    protected void initStaticState() {
+
+        log.debug("initStaticState " + getName() + " " + identifier());
+
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
+
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        output.addFacets(facets);
+        state.addOutput(output);
+
+        setStaticState(state);
+    }
+
+    @Override
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
+        // do not clone facets, etc. from master artifact
+
+        log.debug("initialize");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
+
+        log.debug("ld_from " + getDataAsString("ld_from"));
+        log.debug("ld_to " + getDataAsString("ld_to"));
+    }
+}
\ 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/predefineddepthevol/PredefinedDepthEvolFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,82 @@
+/** 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.predefineddepthevol;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.DefaultCalculationResult;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.model.sinfo.DepthEvolution;
+import org.dive4elements.river.model.sinfo.DepthEvolutionValue;
+
+/**
+ * Facet for a depth evolution value series loaded from the database
+ *
+ * @author Matthias Schäfer
+ */
+public class PredefinedDepthEvolFacet extends BlackboardDataFacet implements FacetTypes {
+
+    private static final long serialVersionUID = -4298111901634067027L;
+
+    public PredefinedDepthEvolFacet(final String name, final String description, final String yAxisLabel) {
+        super(0, name, description);
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", yAxisLabel);
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return
+     *         the data as PredefinedDepthEvolQueryCalculationResult
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final PredefinedDepthEvolAccess access = new PredefinedDepthEvolAccess((D4EArtifact) artifact);
+        final DepthEvolution series = DepthEvolution.getSeries(access.getId());
+        final List<DepthEvolutionValue> values = DepthEvolutionValue.getValues(series, access.getFrom(true), access.getTo(true));
+        final Collection<ResultRow> rows = new ArrayList<>();
+        for (final DepthEvolutionValue value : values) {
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, value.getStation()) //
+                    .putValue(SInfoResultType.flowdepthDevelopment, value.getTotalChangeCm()) //
+                    .putValue(SInfoResultType.flowdepthDevelopmentPerYear, value.getPerYearChangeCm()));
+        }
+        return new DefaultCalculationResult(series.getFilename(), rows);
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public PredefinedDepthEvolFacet deepCopy() {
+        final PredefinedDepthEvolFacet copy = new PredefinedDepthEvolFacet(this.name, this.description, this.metaData.get("Y"));
+        copy.set(this);
+        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/predefinedflowdepth/PredefinedFlowDepthArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,130 @@
+/** 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.predefinedflowdepth;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.DefaultOutput;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactFactory;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.AbstractStaticStateArtifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.PredefinedFlowDepthProcessor;
+import org.dive4elements.river.artifacts.states.StaticState;
+import org.dive4elements.river.model.sinfo.FlowDepthColumn;
+import org.w3c.dom.Document;
+
+/**
+ * Display of a flow depth data series loaded from database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedFlowDepthArtifact extends AbstractStaticStateArtifact implements FacetTypes {
+
+    /** The log for this class. */
+    private static Logger log = Logger.getLogger(PredefinedFlowDepthArtifact.class);
+
+    /** Artifact name. */
+    private static final String NAME = "flowdepthx";
+
+    static {
+        // TODO: Move to configuration.
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
+    }
+
+    public static final String STATIC_STATE_NAME = "state.predefined_flowdepth.static";
+
+    /**
+     * Trivial Constructor.
+     */
+    public PredefinedFlowDepthArtifact() {
+        log.debug("new PredefinedFLowDepthArtifact");
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * Gets called from factory, to set things up.
+     */
+    @Override
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
+
+        log.debug("PredefinedFlowDepthArtifact.setup");
+
+        if (log.isDebugEnabled()) {
+            log.debug(XMLUtils.toString(data));
+        }
+
+        final String code = getDatacageIDValue(data);
+
+        createFacets(callMeta, code);
+
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
+
+    private void createFacets(final CallMeta callMeta, final String code) {
+        if (code == null)
+            return;
+        final String[] parts = code.split("-");
+        if (parts.length < 3) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
+        }
+        addStringData("flowdepth_col_id", parts[1]);
+        addStringData("flowdepth_id", parts[2]);
+        final FlowDepthColumn col = FlowDepthColumn.getColumnById(Integer.parseInt(parts[1]));
+
+        final ArrayList<Facet> facets = new ArrayList<>(1);
+        facets.add(new PredefinedFlowDepthFacet(PredefinedFlowDepthProcessor.FACET_PREDEFINED_FLOW_DEPTH,
+                col.getName() + " (" + col.getSeries().getFilename() + ")"));
+        addFacets(STATIC_STATE_NAME, facets);
+    }
+
+    @Override
+    protected void initStaticState() {
+
+        log.debug("initStaticState " + getName() + " " + identifier());
+
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
+
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        output.addFacets(facets);
+        state.addOutput(output);
+
+        setStaticState(state);
+    }
+
+    @Override
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
+        // do not clone facets, etc. from master artifact
+
+        log.debug("initialize");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
+
+        log.debug("ld_from " + getDataAsString("ld_from"));
+        log.debug("ld_to " + getDataAsString("ld_to"));
+    }
+}
\ 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/predefinedflowdepth/PredefinedFlowDepthColumnAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,59 @@
+/** 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.predefinedflowdepth;
+
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+
+/**
+ * Access to the database loaded flow depth column artifact data
+ *
+ * @author Matthias Schäfer
+ */
+final class PredefinedFlowDepthColumnAccess extends RangeAccess {
+
+    /***** FIELDS *****/
+
+    private Integer columnId;
+
+    private Integer seriesId;
+
+    private String name;
+
+    /***** CONSTRUCTORS *****/
+
+    public PredefinedFlowDepthColumnAccess(final D4EArtifact artifact) {
+        super(artifact);
+    }
+
+    /***** METHODS *****/
+
+    public Integer getSeriesId() {
+        if (this.seriesId == null) {
+            this.seriesId = getInteger("flowdepth_id");
+        }
+        return this.columnId;
+    }
+
+    public Integer getColumnId() {
+        if (this.columnId == null) {
+            this.columnId = getInteger("flowdepth_col_id");
+        }
+        return this.columnId;
+    }
+
+    public String getName() {
+        if (this.name == null) {
+            this.name = getString("name");
+        }
+        return this.name;
+    }
+}
\ 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/predefinedflowdepth/PredefinedFlowDepthFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,81 @@
+/** 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.predefinedflowdepth;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.DefaultCalculationResult;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.model.sinfo.FlowDepthColumn;
+import org.dive4elements.river.model.sinfo.FlowDepthValue;
+
+/**
+ * Facet for a flow depth value series loaded from the database
+ *
+ * @author Matthias Schäfer
+ */
+public class PredefinedFlowDepthFacet extends BlackboardDataFacet implements FacetTypes {
+
+    private static final long serialVersionUID = -5314814229001970855L;
+
+    public PredefinedFlowDepthFacet(final String name, final String description) {
+        super(0, name, description);
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.flow_depth.section.yaxis.label");
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return
+     *         the data as PredefinedFlowDepthQueryCalculationResult
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final PredefinedFlowDepthColumnAccess access = new PredefinedFlowDepthColumnAccess((D4EArtifact) artifact);
+        final FlowDepthColumn series = FlowDepthColumn.getColumnById(access.getColumnId());
+        final List<FlowDepthValue> values = FlowDepthValue.getValues(series, access.getFrom(true), access.getTo(true));
+        final Collection<ResultRow> rows = new ArrayList<>();
+        for (final FlowDepthValue value : values) {
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, value.getStation()) //
+                    .putValue(SInfoResultType.flowdepth, value.getDepth()));
+        }
+        return new DefaultCalculationResult(series.getName(), rows);
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public PredefinedFlowDepthFacet deepCopy() {
+        final PredefinedFlowDepthFacet copy = new PredefinedFlowDepthFacet(this.name, this.description);
+        copy.set(this);
+        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/predefinedtkh/PredefinedTkhArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,129 @@
+/** 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.predefinedtkh;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.DefaultOutput;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactFactory;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.artifacts.AbstractStaticStateArtifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.PredefinedTkhProcessor;
+import org.dive4elements.river.artifacts.states.StaticState;
+import org.dive4elements.river.model.sinfo.TkhColumn;
+import org.w3c.dom.Document;
+
+/**
+ * Display of a tkh data series loaded from database
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class PredefinedTkhArtifact extends AbstractStaticStateArtifact implements FacetTypes {
+
+    /** The log for this class. */
+    private static Logger log = Logger.getLogger(PredefinedTkhArtifact.class);
+
+    /** Artifact name. */
+    private static final String NAME = "tkhx";
+
+    static {
+        // TODO: Move to configuration.
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
+    }
+
+    public static final String STATIC_STATE_NAME = "state.predefined_tkh.static";
+
+    /**
+     * Trivial Constructor.
+     */
+    public PredefinedTkhArtifact() {
+        log.debug("new PredefinedTkhArtifact");
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * Gets called from factory, to set things up.
+     */
+    @Override
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
+
+        log.debug("PredefinedTkhArtifact.setup");
+
+        if (log.isDebugEnabled()) {
+            log.debug(XMLUtils.toString(data));
+        }
+
+        final String code = getDatacageIDValue(data);
+
+        createFacets(callMeta, code);
+
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
+
+    private void createFacets(final CallMeta callMeta, final String code) {
+        if (code == null)
+            return;
+        final String[] parts = code.split("-");
+        if (parts.length < 3) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
+        }
+        addStringData("tkh_col_id", parts[1]);
+        addStringData("tkh_id", parts[2]);
+        final TkhColumn tkhcol = TkhColumn.getTkhColumnById(Integer.parseInt(parts[1]));
+
+        final ArrayList<Facet> facets = new ArrayList<>(1);
+        facets.add(new PredefinedTkhFacet(PredefinedTkhProcessor.FACET_PREDEFINED_TKH, tkhcol.getName() + " (" + tkhcol.getTkh().getFilename() + ")"));
+        addFacets(STATIC_STATE_NAME, facets);
+    }
+
+    @Override
+    protected void initStaticState() {
+
+        log.debug("initStaticState " + getName() + " " + identifier());
+
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
+
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        output.addFacets(facets);
+        state.addOutput(output);
+
+        setStaticState(state);
+    }
+
+    @Override
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
+        // do not clone facets, etc. from master artifact
+
+        log.debug("initialize");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
+
+        log.debug("ld_from " + getDataAsString("ld_from"));
+        log.debug("ld_to " + getDataAsString("ld_to"));
+    }
+}
\ 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/predefinedtkh/PredefinedTkhColumnAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,59 @@
+/** 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.predefinedtkh;
+
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+
+/**
+ * Access to the database loaded tkh column artifact data
+ *
+ * @author Matthias Schäfer
+ */
+final class PredefinedTkhColumnAccess extends RangeAccess {
+
+    /***** FIELDS *****/
+
+    private Integer columnId;
+
+    private Integer tkhId;
+
+    private String name;
+
+    /***** CONSTRUCTORS *****/
+
+    public PredefinedTkhColumnAccess(final D4EArtifact artifact) {
+        super(artifact);
+    }
+
+    /***** METHODS *****/
+
+    public Integer getTkhId() {
+        if (this.tkhId == null) {
+            this.tkhId = getInteger("tkh_id");
+        }
+        return this.columnId;
+    }
+
+    public Integer getColumnId() {
+        if (this.columnId == null) {
+            this.columnId = getInteger("tkh_col_id");
+        }
+        return this.columnId;
+    }
+
+    public String getName() {
+        if (this.name == null) {
+            this.name = getString("name");
+        }
+        return this.name;
+    }
+}
\ 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/predefinedtkh/PredefinedTkhFacet.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,97 @@
+/** 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.predefinedtkh;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.DefaultCalculationResult;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.SoilKind;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.SoilKindKmValueFinder;
+import org.dive4elements.river.model.sinfo.TkhColumn;
+import org.dive4elements.river.model.sinfo.TkhValue;
+
+/**
+ * Facet for a tkh value series loaded from the database
+ *
+ * @author Matthias Schäfer
+ */
+public class PredefinedTkhFacet extends BlackboardDataFacet implements FacetTypes {
+
+    private static final long serialVersionUID = 5508868967789155306L;
+
+    public PredefinedTkhFacet(final String name, final String description) {
+        super(0, name, description);
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.tkh.section.yaxis.label");
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return
+     *         the data as PredefinedTkhQueryCalculationResult
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final PredefinedTkhColumnAccess access = new PredefinedTkhColumnAccess((D4EArtifact) artifact);
+        final TkhColumn series = TkhColumn.getTkhColumnById(access.getColumnId());
+        final List<TkhValue> tkhValues = TkhValue.getTkhValues(series, access.getFrom(true), access.getTo(true));
+        final Calculation problems = new Calculation();
+        final SoilKindKmValueFinder soilKindFinder = SoilKindKmValueFinder.loadValues(problems, access.getRiver(), access.getRange());
+
+        final Collection<ResultRow> rows = new ArrayList<>();
+        SoilKind bedMobility = SoilKind.mobil;
+        for (final TkhValue tkhValue : tkhValues) {
+            final ResultRow row = ResultRow.create();
+            row.putValue(GeneralResultType.station, tkhValue.getStation());
+            if (soilKindFinder != null) {
+                bedMobility = soilKindFinder.findSoilKind(tkhValue.getStation().doubleValue());
+                row.putValue(SInfoResultType.soilkind, bedMobility);
+            } else
+                row.putValue(SInfoResultType.soilkind, null);
+            row.putValue(SInfoResultType.tkh, tkhValue.getTkhCm());
+            row.putValue(SInfoResultType.tkhup, tkhValue.getTkhUpCm(bedMobility == SoilKind.mobil));
+            row.putValue(SInfoResultType.tkhdown, tkhValue.getTkhDownCm(bedMobility == SoilKind.mobil));
+            rows.add(row);
+        }
+        return new DefaultCalculationResult(series.getName(), rows);// new PredefinedTkhQueryCalculationResult(series.getName(), rows);
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public PredefinedTkhFacet deepCopy() {
+        final PredefinedTkhFacet copy = new PredefinedTkhFacet(this.name, this.description);
+        copy.set(this);
+        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/tkhcalculation/BedQualityD50KmValueFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,181 @@
+/* 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.tkhcalculation;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.commons.math.ArgumentOutsideDomainException;
+import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+import org.apache.log4j.Logger;
+import org.dive4elements.river.artifacts.math.Utils;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.backend.SedDBSessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.type.StandardBasicTypes;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Searchable sorted km array with parallel bed measurements value array and linear interpolation for km and d50 between
+ * the array elements.<br />
+ * <br />
+ * See comment of SQL command on how the values are filtered and aggregated.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class BedQualityD50KmValueFinder {
+
+    /***** FIELDS *****/
+
+    /**
+     * Private log to use here.
+     */
+    private static Logger log = Logger.getLogger(BedQualityD50KmValueFinder.class);
+
+    /**
+     * Query selecting all sub layer bed measurements with their d50 for a km range and a time period<br />
+     * <br />
+     * A km may have bed measurements for multiple dates, multiple distances from the river bank, and multiple depth layers.
+     * The query filters by km range, time period and layer (sub layer: below bed to max. 50 cm depth).<br />
+     *
+     * If PostgreSQL would support a median aggregate function like Oracle does, the aggregation could be placed into this
+     * query.
+     */
+    private static final String SQL_BED_D50_SUBLAYER_MEASUREMENT = //
+            "SELECT s.km, t.datum, p.tiefevon, p.tiefebis, a.d50"
+            + " FROM sohltest t INNER JOIN station s ON t.stationid = s.stationid"
+            + "    INNER JOIN gewaesser g ON s.gewaesserid = g.gewaesserid"
+            + "    INNER JOIN sohlprobe p ON t.sohltestid = p.sohltestid"
+            + "    INNER JOIN siebanalyse a ON p.sohlprobeid = a.sohlprobeid"
+            + " WHERE (g.name = :name) AND (s.km BETWEEN :fromkm - 0.0001 AND :tokm + 0.0001)"
+            + "    AND (p.tiefevon > 0.0) AND (p.tiefebis <= 0.5)"
+            + "    AND (t.datum BETWEEN :fromdate AND :todate)"
+            + " ORDER BY s.km ASC, a.d50 ASC";
+
+    private Calculation problems;
+
+    /**
+     * Real linear interpolator for kms and d50 values (m)
+     */
+    private final PolynomialSplineFunction interpolator;
+
+    /***** CONSTRUCTORS *****/
+
+    private BedQualityD50KmValueFinder(final Calculation problems, final double[] kms, final double[] values) {
+        this.problems = problems;
+
+        this.interpolator = new LinearInterpolator().interpolate(kms, values);
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Sohlbeschaffenheit (D50 Korndurchmesser aus Seddb)
+     * Abhängig von Peiljahr
+     *
+     * @param problems
+     */
+    public static BedQualityD50KmValueFinder loadBedMeasurements(final Calculation problems, final River river, final DoubleRange kmRange,
+            final int soundingYear, final int validYears) {
+
+        /* construct valid measurement time range */
+        final Calendar cal = Calendar.getInstance();
+        cal.clear();
+
+        cal.set(soundingYear - validYears, 0, 1);
+        final Date startTime = cal.getTime();
+
+        cal.set(soundingYear + validYears, 11, 31);
+        final Date endTime = cal.getTime();
+
+        final String seddbRiver = river.nameForSeddb();
+        log.debug(String.format("loadValues '%s' km %.3f - %.3f %tF - %tF", seddbRiver, kmRange.getMinimumDouble(), kmRange.getMaximumDouble(), startTime,
+                endTime));
+        final Session session = SedDBSessionHolder.HOLDER.get();
+        final SQLQuery sqlQuery = session.createSQLQuery(SQL_BED_D50_SUBLAYER_MEASUREMENT).addScalar("km", StandardBasicTypes.DOUBLE)
+                .addScalar("datum", StandardBasicTypes.DATE).addScalar("tiefevon", StandardBasicTypes.DOUBLE).addScalar("tiefebis", StandardBasicTypes.DOUBLE)
+                .addScalar("d50", StandardBasicTypes.DOUBLE);
+        sqlQuery.setString("name", seddbRiver);
+        sqlQuery.setDouble("fromkm", kmRange.getMinimumDouble());
+        sqlQuery.setDouble("tokm", kmRange.getMaximumDouble());
+        sqlQuery.setDate("fromdate", startTime);
+        sqlQuery.setDate("todate", endTime);
+
+        final List<Object[]> rows = sqlQuery.list();
+        final TDoubleArrayList kms = new TDoubleArrayList();
+        final TDoubleArrayList values = new TDoubleArrayList();
+        final TDoubleArrayList kmd50s = new TDoubleArrayList();
+
+        // Median aggregate d50 values for each km
+        if (rows != null) {
+            for (int i = 0; i <= rows.size() - 1; i++) {
+                log.trace("loadValues rows(" + i + ") " + rows.get(i)[0] + " " + rows.get(i)[1] + " " + rows.get(i)[2] + " " + rows.get(i)[3] + " "
+                        + rows.get(i)[4]);
+                kmd50s.add((double) rows.get(i)[4]);
+                if (((i == rows.size() - 1) || !Utils.epsilonEquals((double) rows.get(i)[0], (double) rows.get(i + 1)[0], 0.0001))) {
+                    final int k = kmd50s.size() / 2;
+                    values.add(((k + k < kmd50s.size()) ? kmd50s.get(k) : (kmd50s.get(k - 1) + kmd50s.get(k)) / 2) / 1000);
+                    kms.add((double) rows.get(i)[0]);
+                    log.debug(String.format("loadValues km %.3f d50(mm) %.1f count %d", kms.get(kms.size() - 1), values.get(values.size() - 1) * 1000,
+                            kmd50s.size()));
+                    kmd50s.clear();
+                }
+            }
+        }
+        if (kms.size() >= 1)
+            log.debug(String.format("loadValues: %d kms found from %.3f to %.3f", kms.size(), kms.get(0), kms.get(kms.size() - 1)));
+        else
+            log.debug("loadValues: no kms found");
+
+        if (kms.size() < 2 || values.size() < 2) {
+            problems.addProblem("bedqualityd50kmvaluefinder.empty", soundingYear);
+            return null;
+        }
+
+        try {
+            return new BedQualityD50KmValueFinder(problems, kms.toNativeArray(), values.toNativeArray());
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+            problems.addProblem("bedqualityd50kmvaluefinder.error", e.getLocalizedMessage());
+            return null;
+        }
+    }
+
+    /**
+     * Returns the d50 value interpolated according to a km
+     *
+     * @return d50 (m) of the km, or NaN
+     */
+    public double findD50(final double km) {
+        try {
+            return this.interpolator.value(km);
+        }
+        catch (final ArgumentOutsideDomainException e) {
+            // e.printStackTrace();
+
+            if (this.problems != null) {
+                this.problems.addProblem(km, "bedqualityd50kmvaluefinder.missing");
+                // Report only once
+                this.problems = null;
+            }
+
+            return Double.NaN;
+        }
+    }
+}
\ 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/tkhcalculation/DischargeValuesFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,96 @@
+/** 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.tkhcalculation;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.dive4elements.river.artifacts.model.QKms;
+import org.dive4elements.river.artifacts.model.WKms;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.utils.DoubleUtil;
+
+import gnu.trove.TDoubleDoubleHashMap;
+
+/**
+ * @author Gernot Belger
+ */
+public final class DischargeValuesFinder {
+
+    private final UnivariateRealFunction qInterpolator;
+
+    private final TDoubleDoubleHashMap exactValues;
+
+    private final QKms qKms;
+
+    /**
+     * Create an instance from a {@link WKms} object. If the given {@link WKms} is not a {@link WQKms}, a finder that always
+     * returns {@link Double#NaN} is returned.
+     */
+    public static DischargeValuesFinder fromKms(final WKms wstKms) {
+        if (!(wstKms instanceof QKms)) {
+            return new DischargeValuesFinder(null);
+        }
+
+        final QKms qKms = (QKms) wstKms;
+
+        return new DischargeValuesFinder(qKms);
+    }
+
+    public DischargeValuesFinder(final QKms qKms) {
+        this.qKms = qKms;
+
+        if (qKms == null) {
+            this.qInterpolator = null;
+            this.exactValues = null;
+        } else {
+            this.qInterpolator = DoubleUtil.getLinearInterpolator(qKms.allKms(), qKms.allQs());
+
+            this.exactValues = new TDoubleDoubleHashMap(qKms.size());
+
+            for (int i = 0; i < qKms.size(); i++) {
+                final double station = qKms.getKm(i);
+                final double discharge = qKms.getQ(i);
+                this.exactValues.put(station, discharge);
+            }
+        }
+    }
+
+    /**
+     * If this provider may return valid data at all.
+     */
+    public boolean isValid() {
+        return this.qInterpolator != null;
+    }
+
+    public DoubleRange getRange() {
+        return new DoubleRange(this.qKms.allQs().min(), this.qKms.allQs().max());
+    }
+
+    public double getDischarge(final double station) {
+
+        try {
+            // IMPORTANT: we first try to retrieve the exact value if it is present, to avoid rounding changes due to interpolation.
+            // This is important because in the WaterlevelExporter code, these values are double-compared (with '==' ...) in order
+            // to find the corresponding main-value.
+            if (this.exactValues != null && this.exactValues.contains(station))
+                return this.exactValues.get(station);
+
+            if (this.qInterpolator == null)
+                return Double.NaN;
+
+            return this.qInterpolator.value(station);
+        }
+        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
+            // ignore exception because this can/will happen regularly
+            return Double.NaN;
+        }
+    }
+}
\ 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/tkhcalculation/FlowVelocityModelKmValueFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,373 @@
+/* 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.tkhcalculation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.log4j.Logger;
+import org.dive4elements.river.artifacts.math.Linear;
+import org.dive4elements.river.artifacts.math.Utils;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowVelocityKmModelValues;
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.type.StandardBasicTypes;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Searchable sorted km array with parallel FlowVelocityKmModelValues array and linear interpolation for km and the
+ * model values between the array elements.<br />
+ * {@link loadValues} loads all the model values for a given km range of a river.<br />
+ * {@link findKmQValues} then searches a km in the values table or the nearest including km interval, resp.
+ * The v and tau values for a given discharge are either found directly or also interpolated linearly.<br />
+ *
+ * (Created based on a copy of FlowVelocityMeasurementFactory.)
+ *
+ * @author Matthias Schäfer
+ */
+final class FlowVelocityModelKmValueFinder {
+
+    /***** FIELDS *****/
+
+    /**
+     * Private log to use here.
+     */
+    private static Logger log = Logger.getLogger(FlowVelocityModelKmValueFinder.class);
+
+    /**
+     * Query for a range of stations of a river with all their q, main-v and tau values.<br />
+     * (Might be several 10000 rows if many stations and large q range)
+     */
+    private static final String SQL_SELECT_ALL = //
+            "SELECT fvmv.station AS station, fvmv.q AS q, fvmv.main_channel AS vmain, fvmv.shear_stress AS tau"
+            + "  FROM (discharge_zone dz INNER JOIN flow_velocity_model fvm ON dz.id = fvm.discharge_zone_id)"
+            + "    INNER JOIN flow_velocity_model_values fvmv ON fvm.id = fvmv.flow_velocity_model_id"
+            + "  WHERE (dz.river_id = :river_id) AND (fvmv.station BETWEEN :kmfrom - 0.0001 AND :kmto + 0.0001)"
+            /* + "  WHERE (dz.river_id = :river_id) AND (fvmv.q BETWEEN :qmin AND :qmax)" */
+            + "  ORDER BY fvmv.station ASC, fvmv.q ASC";
+
+    /**
+     * Query for a river's max km below a limit with all its q, main-v and tau values.
+     */
+    private static final String SQL_SELECT_KMLOWER = //
+            "SELECT fvmv.station AS station, fvmv.q AS q, fvmv.main_channel AS vmain, fvmv.shear_stress AS tau"
+            + "  FROM flow_velocity_model_values fvmv"
+            + "    INNER JOIN (SELECT MAX(fvmvi.station) AS kmmax"
+            + "      FROM discharge_zone dz INNER JOIN flow_velocity_model fvm ON dz.id = fvm.discharge_zone_id"
+            + "        INNER JOIN flow_velocity_model_values fvmvi ON fvm.id = fvmvi.flow_velocity_model_id"
+            + "        WHERE (dz.river_id = :river_id) AND (fvmvi.station < :kmfrom - 0.0001)) finf ON fvmv.station = finf.kmmax"
+            + "  ORDER BY fvmv.q ASC";
+
+    /**
+     * Query for a river's min km above a limit with all its q, main-v and tau values.
+     */
+    private static final String SQL_SELECT_KMUPPER = //
+            "SELECT fvmv.station AS station, fvmv.q AS q, fvmv.main_channel AS vmain, fvmv.shear_stress AS tau"
+            + "  FROM flow_velocity_model_values fvmv"
+            + "    INNER JOIN (SELECT MIN(fvmvi.station) AS kmmin"
+            + "      FROM discharge_zone dz INNER JOIN flow_velocity_model fvm ON dz.id = fvm.discharge_zone_id"
+            + "        INNER JOIN flow_velocity_model_values fvmvi ON fvm.id = fvmvi.flow_velocity_model_id"
+            + "        WHERE (dz.river_id = :river_id) AND (fvmvi.station > :kmto + 0.0001)) fsup ON fvmv.station = fsup.kmmin"
+            + "  ORDER BY fvmv.q ASC";
+
+    // /**
+    // * Query to select all km-q-v-tau of a river that are the q maxima below a q limit
+    // */
+    // private static final String SQL_SELECT_QLOWER =
+    // "SELECT fvmv.station AS station, fvmv.q AS q, fvmv.main_channel AS vmain, fvmv.shear_stress AS tau"
+    // + " FROM flow_velocity_model_values fvmv"
+    // + " INNER JOIN (SELECT fv2.station, MAX(fv2.q) AS q"
+    // + " FROM (discharge_zone dz INNER JOIN flow_velocity_model fvm ON dz.id = fvm.discharge_zone_id)"
+    // + " INNER JOIN flow_velocity_model_values fv2 ON fvm.id = fv2.flow_velocity_model_id"
+    // + " WHERE (dz.river_id = :river_id) AND (fv2.q < :qlim) GROUP BY fv2.station) qx"
+    // + " ON (fvmv.station=qx.station) AND (fvmv.q=qx.q)"
+    // + " ORDER BY fvmv.station ASC";
+    //
+    // /**
+    // * Query to select all km-q-v-tau of a river that are the q minima above a q limit
+    // */
+    // private static final String SQL_SELECT_QUPPER =
+    // "SELECT fvmv.station AS station, fvmv.q AS q, fvmv.main_channel AS vmain, fvmv.shear_stress AS tau"
+    // + " FROM flow_velocity_model_values fvmv"
+    // + " INNER JOIN (SELECT fv2.station, MIN(fv2.q) AS q"
+    // + " FROM (discharge_zone dz INNER JOIN flow_velocity_model fvm ON dz.id = fvm.discharge_zone_id)"
+    // + " INNER JOIN flow_velocity_model_values fv2 ON fvm.id = fv2.flow_velocity_model_id"
+    // + " WHERE (dz.river_id = :river_id) AND (fv2.q > :qlim) GROUP BY fv2.station) qx"
+    // + " ON (fvmv.station=qx.station) AND (fvmv.q=qx.q)"
+    // + " ORDER BY fvmv.station ASC";
+
+    /**
+     * Kms of the loaded river range
+     */
+    private final TDoubleArrayList kms = new TDoubleArrayList();
+
+    /**
+     * For each km in kms a list of q-v-tau-tupels
+     */
+    private final List<FlowVelocityKmModelValues> values = new ArrayList<>();
+
+    private Calculation problems;
+
+    /**
+     * Searched km of the last findKmValue
+     */
+    private double findKm;
+
+    /**
+     * kms and values index of the interval start found by the last findKmValue
+     */
+    private int leftIndexFound = -1;
+
+    /**
+     * kms and values index of the interval end found by the last findKmValue
+     */
+    private int rightIndexFound = -1;
+
+    /**
+     * Q of the last findKmQValues
+     */
+    private double findQ;
+
+    public FlowVelocityModelKmValueFinder(final Calculation problems) {
+        this.problems = problems;
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Discharge of the last {@link findKmQValue}
+     */
+    public double getFindQ() {
+        return this.findQ;
+    }
+
+    /**
+     * Velocity of the last {@link findKmQValues}
+     */
+    public double getFindVmainFound() {
+        if (this.leftIndexFound < 0)
+            return Double.NaN;
+        else if (this.leftIndexFound == this.rightIndexFound)
+            return getLeftValues().getVmainFound();
+        else
+            return Linear.linear(this.findKm, getLeftValues().getKm(), getRightValues().getKm(), getLeftValues().getVmainFound(),
+                    getRightValues().getVmainFound());
+    }
+
+    /**
+     * Shear stress tau of the last {@link findKmQValues}
+     */
+    public double getFindTauFound() {
+        if (this.leftIndexFound < 0)
+            return Double.NaN;
+
+        if (this.leftIndexFound == this.rightIndexFound)
+            return getLeftValues().getTauFound();
+
+        return Linear.linear(this.findKm, getLeftValues().getKm(), getRightValues().getKm(), getLeftValues().getTauFound(), getRightValues().getTauFound());
+    }
+
+    /**
+     * Whether the discharge has been interpolated in the last {@link findKmQValues}
+     */
+    public boolean getFindIsQInterpolated() {
+        return (getLeftValues() != null) && (getLeftValues().getIsInterpolated() || getRightValues().getIsInterpolated());
+    }
+
+    /**
+     * Static constructor: queries a range of a river's kms with all their q-v-tau values.
+     *
+     * @param problems
+     *
+     * @return Whether the load has been successful the new instance, <code>null</code> otherwise.
+     */
+    public static FlowVelocityModelKmValueFinder loadValues(final Calculation problems, final River river, final DoubleRange kmRange,
+            final DoubleRange qRange) {
+        // DB session
+        log.debug(String.format("loadValues km %.3f - %.3f / q %.1f - %.1f", kmRange.getMinimumDouble(), kmRange.getMaximumDouble(), qRange.getMinimumDouble(),
+                qRange.getMaximumDouble()));
+
+        final FlowVelocityModelKmValueFinder instance = new FlowVelocityModelKmValueFinder(problems);
+
+        final TDoubleArrayList kms = instance.kms;
+        final List<FlowVelocityKmModelValues> values = instance.values;
+
+        final boolean isDemoValuesCorrection = river.getName().equalsIgnoreCase("beispielfluss");
+        final Session session = SessionHolder.HOLDER.get();
+
+        // Select km infimum
+        SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_KMLOWER).addScalar("station", StandardBasicTypes.DOUBLE).addScalar("q", StandardBasicTypes.DOUBLE)
+                .addScalar("vmain", StandardBasicTypes.DOUBLE).addScalar("tau", StandardBasicTypes.DOUBLE);
+        sqlQuery.setParameter("river_id", river.getId());
+        sqlQuery.setParameter("kmfrom", kmRange.getMinimumDouble());
+        instance.addKms(sqlQuery.list(), isDemoValuesCorrection);
+
+        // Select km range
+        sqlQuery = session.createSQLQuery(SQL_SELECT_ALL).addScalar("station", StandardBasicTypes.DOUBLE).addScalar("q", StandardBasicTypes.DOUBLE)
+                .addScalar("vmain", StandardBasicTypes.DOUBLE).addScalar("tau", StandardBasicTypes.DOUBLE);
+        sqlQuery.setParameter("river_id", river.getId());
+        sqlQuery.setParameter("kmfrom", kmRange.getMinimumDouble());
+        sqlQuery.setParameter("kmto", kmRange.getMaximumDouble());
+        // sqlQuery.setParameter("qmin", qRange.getMinimumDouble());
+        // sqlQuery.setParameter("qmax", qRange.getMaximumDouble());
+
+        int kmcount = kms.size();
+        final int rowcount = instance.addKms(sqlQuery.list(), isDemoValuesCorrection);
+        kmcount = kms.size() - kmcount;
+
+        // Select km supremum
+        sqlQuery = session.createSQLQuery(SQL_SELECT_KMUPPER).addScalar("station", StandardBasicTypes.DOUBLE).addScalar("q", StandardBasicTypes.DOUBLE)
+                .addScalar("vmain", StandardBasicTypes.DOUBLE).addScalar("tau", StandardBasicTypes.DOUBLE);
+        sqlQuery.setParameter("river_id", river.getId());
+        sqlQuery.setParameter("kmto", kmRange.getMaximumDouble());
+        final int supcnt = instance.addKms(sqlQuery.list(), isDemoValuesCorrection);
+
+        // Add copy of last km for search of max km value
+        if ((supcnt == 0) && (values.size() >= 1)) {
+            kms.add(kms.getQuick(kms.size()) + 0.0001);
+            values.add(new FlowVelocityKmModelValues(kms.getQuick(kms.size() - 1), values.get(values.size() - 1)));
+        }
+
+        // log.debug
+        if (values.size() - 1 >= 0) {
+            log.debug(String.format("loadValues %d: km %.3f - %d values", 0, values.get(0).getKm(), values.get(0).size()));
+
+            if (values.size() - 1 >= 1) {
+                log.debug(String.format("loadValues %d: km %.3f - %d values", 1, values.get(1).getKm(), values.get(1).size()));
+
+                if (values.size() - 1 >= 2)
+                    log.debug("loadValues ...");
+
+                if (values.size() - 2 >= 3)
+                    log.debug(String.format("loadValues %d: km %.3f - %d values", values.size() - 2, values.get(values.size() - 2).getKm(),
+                            values.get(values.size() - 2).size()));
+
+                if (values.size() - 1 >= 3)
+                    log.debug(String.format("loadValues %d: km %.3f - %d values", values.size() - 1, values.get(values.size() - 1).getKm(),
+                            values.get(values.size() - 1).size()));
+            }
+        }
+
+        log.debug(String.format("loadValues %d kms, %d values loaded", kmcount, rowcount));
+
+        if (kms.size() == 0) {
+            problems.addProblem("flowvelocitymodelkmvaluefinder.empty");
+            return null;
+        }
+
+        return instance;
+    }
+
+    /**
+     * Adds the km-q-v-tau values of a query result row to the last km of the list, or a new one resp.
+     *
+     * @return Number of rows
+     */
+    private int addKms(final List<Object[]> rows, final boolean isDemoValuesCorrection) {
+        log.trace("addKms i km j q v tau");
+        for (final Object[] row : rows) {
+            if ((this.kms.size() == 0) || !Utils.epsilonEquals(this.kms.get(this.kms.size() - 1), (double) row[0], 0.0001)) {
+                this.kms.add((double) row[0]);
+                this.values.add(new FlowVelocityKmModelValues(this.kms.get(this.kms.size() - 1)));
+            }
+            if (isDemoValuesCorrection)
+                // "Verfremdung" der v-Werte etwas korrigieren (Originalwerte wurden mit Zufallswert zwischen 10 und 20 multipliziert)
+                this.values.get(this.values.size() - 1).addValues((double) row[1], ((double) row[2]) / 10, (double) row[3]);
+            else
+                this.values.get(this.values.size() - 1).addValues((double) row[1], (double) row[2], (double) row[3]);
+            final int j = this.values.size() - 1;
+            log.trace(String.format("addKms %d %.3f %d %.0f %.2f %.2f", this.values.size() - 1, this.values.get(j).getKm(),
+                    this.values.get(j).size() - 1, (double) row[1], (double) row[2], (double) row[3]));
+        }
+        return rows.size();
+    }
+
+    /**
+     * Searches a km and finds or interpolates the velocity and shear stress values for a discharge<br />
+     * The values may be got via {@link getVmainFound} etc.
+     *
+     * @return Whether values have been found
+     */
+    public boolean findKmQValues(final double km, final double q) {
+        this.findQ = q;
+
+        final boolean found = doFindKmQValues(km, q);
+
+        if (this.problems != null) {
+
+            this.problems.addProblem(km, "flowvelocitymodelkmvaluefinder.missing");
+
+            // report only once
+            this.problems = null;
+        }
+
+        return found;
+    }
+
+    private boolean doFindKmQValues(final double km, final double q) {
+        if (!searchKm(km))
+            return false;
+
+        if (this.leftIndexFound == this.rightIndexFound) {
+            // Exact km match
+            final double qfound = getLeftValues().findQ(q);
+            log.trace(String.format("findKmQValues km %.3f q %.0f = %.0f (%d, %.3f) - %.0f (%d, %.3f) v = %.3f, tau = %.3f", km, q, qfound, this.leftIndexFound,
+                    km, qfound, this.rightIndexFound, km, this.getFindVmainFound(), this.getFindTauFound()));
+            return !Double.isNaN(qfound);
+        }
+
+        final double[] qfound = { getLeftValues().findQ(q), getRightValues().findQ(q) };
+        log.trace(String.format("findKmQValues km %.3f q %.0f = %.0f (%d, %.3f) - %.0f (%d, %.3f) v = %.3f, tau = %.3f", km, q, qfound[0], this.leftIndexFound,
+                getLeftValues().getKm(), qfound[1], this.rightIndexFound, getRightValues().getKm(), this.getFindVmainFound(), this.getFindTauFound()));
+        return !Double.isNaN(qfound[0]) && !Double.isNaN(qfound[1]);
+    }
+
+    /**
+     * Searches a km
+     *
+     * @return Whether the km was within the supported range
+     */
+    private boolean searchKm(final double km) {
+        this.findKm = km;
+        this.leftIndexFound = -1;
+        this.rightIndexFound = -1;
+
+        int i = this.kms.binarySearch(km);
+        if (i >= 0) {
+            // Exact km match
+            this.leftIndexFound = i;
+            this.rightIndexFound = i;
+            return true;
+        }
+
+        // Out of range or within km interval
+        if (i < 0)
+            i = -i - 1;
+        if ((i <= 0) || (i >= this.kms.size()))
+            return false;
+        this.leftIndexFound = i - 1;
+        this.rightIndexFound = i;
+        return true;
+    }
+
+    private FlowVelocityKmModelValues getLeftValues() {
+        return this.values.get(this.leftIndexFound);
+    }
+
+    private FlowVelocityKmModelValues getRightValues() {
+        return this.values.get(this.rightIndexFound);
+    }
+}
\ 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/tkhcalculation/SoilKind.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,14 @@
+/** 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.tkhcalculation;
+
+public enum SoilKind {
+    mobil, starr
+}
\ 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/tkhcalculation/SoilKindKmValueFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,117 @@
+/* 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.tkhcalculation;
+
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.type.StandardBasicTypes;
+
+/**
+ * @author Matthias Schäfer
+ */
+public final class SoilKindKmValueFinder {
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(SoilKindKmValueFinder.class);
+
+    /**
+     * Query selecting the bed mobility attribute for a range of stations of a river
+     */
+    private static final String SQL_BED_MOBILITY = "SELECT bmv.station, bmv.moving"
+            + " FROM bed_mobility bm INNER JOIN bed_mobility_values bmv ON bm.id = bmv.bed_mobility_id"
+            + " WHERE (bm.river_id=:river_id) AND (bmv.station BETWEEN (:fromkm-0.0001) AND (:tokm+0.0001))" + " ORDER BY bmv.station ASC";
+
+    private final NavigableMap<Double, SoilKind> kmMobility = new TreeMap<>();
+
+    private Calculation problems;
+
+    /***** CONSTRUCTORS *****/
+
+    private SoilKindKmValueFinder(final Calculation problems, final List<Object[]> queryRows) {
+        this.problems = problems;
+
+        for (int i = 0; i <= queryRows.size() - 1; i++) {
+            this.kmMobility.put(Double.valueOf((double) queryRows.get(i)[0]), (((int) queryRows.get(i)[1]) == 1) ? SoilKind.mobil : SoilKind.starr);
+        }
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the range of the river's kms with their soil kind.
+     *
+     * @return Whether the load has been successful
+     */
+    public static SoilKindKmValueFinder loadValues(final Calculation problems, final River river, final DoubleRange kmRange) {
+        final Session session = SessionHolder.HOLDER.get();
+        final SQLQuery sqlQuery = session.createSQLQuery(SQL_BED_MOBILITY).addScalar("station", StandardBasicTypes.DOUBLE).addScalar("moving",
+                StandardBasicTypes.INTEGER);
+        sqlQuery.setInteger("river_id", river.getId().intValue());
+        sqlQuery.setDouble("fromkm", kmRange.getMinimumDouble());
+        sqlQuery.setDouble("tokm", kmRange.getMaximumDouble());
+        final List<Object[]> rows = sqlQuery.list();
+        if (rows.size() >= 1)
+            return new SoilKindKmValueFinder(problems, rows);
+
+        problems.addProblem("soilkindkmvaluefinder.empty");
+        return null;
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Searches a km with its soil kind
+     */
+    public SoilKind findSoilKind(final double km) {
+
+        if (this.kmMobility.containsKey(Double.valueOf(km)))
+            return this.kmMobility.get(Double.valueOf(km));
+
+        final Entry<Double, SoilKind> streamUp = this.kmMobility.floorEntry(Double.valueOf(km));
+        if (streamUp == null) {
+            reportProblem(km);
+            return null;
+        }
+
+        // Return the soil kind of the neighbouring station with the shorter distance to the candidate.
+        final Entry<Double, SoilKind> streamDown = this.kmMobility.ceilingEntry(Double.valueOf(km));
+        if (streamDown == null)
+            return streamUp.getValue();
+
+        final double streamUpValue = streamUp.getKey().doubleValue();
+        final double streamDownValue = streamDown.getKey().doubleValue();
+
+        if ((streamUpValue + streamDownValue) / 2 <= km)
+            return streamUp.getValue();
+
+        return streamDown.getValue();
+    }
+
+    private void reportProblem(final double km) {
+        if (this.problems == null)
+            return;
+
+        this.problems.addProblem(km, "soilkindkmvaluefinder.missing");
+
+        // report problem only once
+        this.problems = null;
+    }
+}
\ 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/tkhcalculation/TkhCalculator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,233 @@
+/** 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.tkhcalculation;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Gernot Belger
+ */
+public final class TkhCalculator {
+
+    private static final int VALID_BED_MEASUREMENT_YEARS = 20;
+
+    private final BedQualityD50KmValueFinder bedMeasurementsFinder;
+
+    private final SoilKindKmValueFinder soilKindFinder;
+
+    private final BedHeightsFinder bedHeightsProvider;
+
+    private final WaterlevelValuesFinder waterlevelProvider;
+
+    private final DischargeValuesFinder dischargeProvider;
+
+    private final FlowVelocityModelKmValueFinder flowVelocitiesFinder;
+
+    public static TkhCalculator buildTkhCalculator(final boolean useTkh, final Calculation problems, final String label,
+            final River river, final DoubleRange calcRange, final WaterlevelValuesFinder waterlevelProvider, final DischargeValuesFinder dischargeProvider,
+            final BedHeightsFinder bedHeightsProvider) {
+
+        if (!useTkh)
+            return new TkhCalculator(null, waterlevelProvider, dischargeProvider, bedHeightsProvider, null, null);
+
+        if (!dischargeProvider.isValid()) {
+            problems.addProblem("sinfo_calc_flow_depth.warning.missingQ", label);
+            return new TkhCalculator(null, waterlevelProvider, dischargeProvider, bedHeightsProvider, null, null);
+        }
+
+        /* access bed quality data */
+        final int soundingYear = bedHeightsProvider.getInfo().getYear();
+        final BedQualityD50KmValueFinder bedMeasurementsFinder = BedQualityD50KmValueFinder.loadBedMeasurements(problems, river, calcRange, soundingYear,
+                VALID_BED_MEASUREMENT_YEARS);
+        if (bedMeasurementsFinder == null)
+            return new TkhCalculator(null, waterlevelProvider, dischargeProvider, bedHeightsProvider, null, null);
+
+        /* access bed soil kind data */
+        final SoilKindKmValueFinder soilKindFinder = SoilKindKmValueFinder.loadValues(problems, river, calcRange);
+        if (soilKindFinder == null)
+            return new TkhCalculator(null, waterlevelProvider, dischargeProvider, bedHeightsProvider, null, null);
+
+        final DoubleRange qRange = dischargeProvider.getRange();
+        final FlowVelocityModelKmValueFinder flowVelocitiesFinder = FlowVelocityModelKmValueFinder.loadValues(problems, river, calcRange, qRange);
+        if (flowVelocitiesFinder == null)
+            return new TkhCalculator(null, waterlevelProvider, dischargeProvider, bedHeightsProvider, null, null);
+
+        return new TkhCalculator(bedMeasurementsFinder, waterlevelProvider, dischargeProvider, bedHeightsProvider, soilKindFinder,
+                flowVelocitiesFinder);
+    }
+
+    private TkhCalculator(final BedQualityD50KmValueFinder bedMeasurementsFinder, final WaterlevelValuesFinder waterlevelProvider,
+            final DischargeValuesFinder dischargeProvider, final BedHeightsFinder bedHeightsProvider, final SoilKindKmValueFinder soilKindFinder,
+            final FlowVelocityModelKmValueFinder flowVelocitiesFinder) {
+        this.bedMeasurementsFinder = bedMeasurementsFinder;
+        this.waterlevelProvider = waterlevelProvider;
+        this.dischargeProvider = dischargeProvider;
+        this.bedHeightsProvider = bedHeightsProvider;
+        this.soilKindFinder = soilKindFinder;
+        this.flowVelocitiesFinder = flowVelocitiesFinder;
+    }
+
+    public boolean hasTkh() {
+
+        if (this.dischargeProvider == null || !this.dischargeProvider.isValid())
+            return false;
+
+        if (this.bedMeasurementsFinder == null)
+            return false;
+
+        if (this.soilKindFinder == null)
+            return false;
+
+        if (this.flowVelocitiesFinder == null)
+            return false;
+
+        return true;
+    }
+
+    private SoilKind getSoilKind(final double km) {
+
+        if (this.soilKindFinder == null)
+            return null;
+
+        return this.soilKindFinder.findSoilKind(km);
+    }
+
+    private double getBedMeasurement(final double km) {
+        return this.bedMeasurementsFinder.findD50(km);
+    }
+
+    public boolean calculateTkh(final double km, final ResultRow row) {
+
+        row.putValue(GeneralResultType.station, km);
+
+        final SoilKind kind = getSoilKind(km);
+        row.putValue(SInfoResultType.soilkind, kind);
+
+        final double wst = this.waterlevelProvider.getWaterlevel(km);
+        row.putValue(SInfoResultType.waterlevel, wst);
+        if (Double.isNaN(wst))
+            return false;
+
+        final double meanBedHeight = this.bedHeightsProvider.getMeanBedHeight(km);
+        row.putValue(SInfoResultType.meanBedHeight, meanBedHeight);
+        if (Double.isNaN(meanBedHeight))
+            return false;
+
+        final double flowDepth = wst - meanBedHeight;
+        row.putValue(SInfoResultType.flowdepth, flowDepth);
+        if (Double.isNaN(flowDepth))
+            return false;
+
+        final double discharge = this.dischargeProvider.getDischarge(km);
+        row.putValue(SInfoResultType.discharge, discharge);
+
+        if (!this.hasTkh())
+            return true;
+
+        // Missing discharge or kind is only a problem if we want to calculate tkh
+        if (Double.isNaN(discharge))
+            return false;
+        if (kind == null)
+            return false;
+
+        final double d50 = getBedMeasurement(km);
+        row.putValue(SInfoResultType.d50, d50);
+        if (Double.isNaN(d50))
+            return false;
+
+        if (!this.flowVelocitiesFinder.findKmQValues(km, discharge))
+            return false;
+
+        final double velocity = this.flowVelocitiesFinder.getFindVmainFound();
+        row.putValue(SInfoResultType.velocity, velocity);
+        if (Double.isNaN(velocity))
+            return false;
+
+        final double tau = this.flowVelocitiesFinder.getFindTauFound();
+        row.putValue(SInfoResultType.tau, tau);
+        if (Double.isNaN(tau))
+            return false;
+
+        final double tkh = calculateTkh(wst - meanBedHeight, velocity, d50, tau);
+        row.putValue(SInfoResultType.tkh, tkh);
+        if (Double.isNaN(tkh))
+            return false;
+
+        switch (kind) {
+        case starr:
+            row.putValue(SInfoResultType.tkhup, tkh);
+            row.putValue(SInfoResultType.tkhdown, 0.0);
+            break;
+
+        case mobil:
+        default:
+            row.putValue(SInfoResultType.tkhup, tkh / 2);
+            row.putValue(SInfoResultType.tkhdown, -tkh / 2);
+            break;
+        }
+
+        final double flowDepthTkh = calculateFlowDepthTkh(tkh, kind, wst, meanBedHeight);
+        row.putValue(SInfoResultType.flowdepthtkh, flowDepthTkh);
+
+        return true;
+    }
+
+    /**
+     * Calculates a transport body height
+     *
+     * @param h
+     *            flow depth in m
+     * @param vm
+     *            flow velocity in m
+     * @param d50
+     *            grain diameter D50 in m (!)
+     * @param tau
+     *            shear stress in N/m^2
+     * @return transport body height in cm (!), never negative
+     */
+    private double calculateTkh(final double h, final double vm, final double d50, final double tau) {
+        final double PHYS_G = 9.81;
+        final double PHYS_SPECGRAV_S = 2.6;
+        final double PHYS_VELOCCOEFF_N = 6;
+        final double PHYS_FORMCOEFF_ALPHA = 0.7;
+        final double PHYS_VISCOSITY_NUE = 1.3e-6;
+        final double PHYS_GRAIN_DENSITY_RHOS = 2603;
+        final double PHYS_WATER_DENSITY_RHO = 999.97;
+
+        final double froude = vm / Math.sqrt(PHYS_G * h);
+        final double partReynolds = Math.sqrt((PHYS_SPECGRAV_S - 1) * PHYS_G * d50) / PHYS_VISCOSITY_NUE * d50;
+        final double critShields = 0.22 * Math.pow(partReynolds, -0.6) + 0.06 * Math.pow(10, -7.7 * Math.pow(partReynolds, -0.6));
+        final double critTau = critShields * (PHYS_GRAIN_DENSITY_RHOS - PHYS_WATER_DENSITY_RHO) * PHYS_G * d50;
+        final double tkh = 100 * h * (1 - Math.pow(froude, 2)) / (2 * PHYS_VELOCCOEFF_N * PHYS_FORMCOEFF_ALPHA) * (1 - critTau / tau);
+        // Some regular input values may give a negative calculation result; that is unwanted
+        if (tkh < 0.0)
+            return 0.0;
+
+        return tkh;
+    }
+
+    private double calculateFlowDepthTkh(final double tkhValue, final SoilKind tkhKind, final double wst, final double meanBedHeight) {
+
+        switch (tkhKind) {
+        case starr:
+            return wst - (meanBedHeight + tkhValue / 100);
+
+        case mobil:
+        default:
+            return wst - (meanBedHeight + tkhValue / 200);
+        }
+    }
+}
\ 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/tkhcalculation/WaterlevelValuesFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,38 @@
+/** 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.tkhcalculation;
+
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.WKms;
+import org.dive4elements.river.artifacts.sinfo.util.LinearInterpolator;
+
+/**
+ * Abstraction for access to waterlevels by station.
+ *
+ * @author Gernot Belger
+ */
+public class WaterlevelValuesFinder {
+
+    private static final double MAX_DSTANCE_KM = 1.0;
+
+    public static WaterlevelValuesFinder fromKms(final Calculation problems, final WKms wkms) {
+        return new WaterlevelValuesFinder(problems, wkms);
+    }
+
+    private final LinearInterpolator wstInterpolator;
+
+    private WaterlevelValuesFinder(final Calculation problems, final WKms wkms) {
+        this.wstInterpolator = LinearInterpolator.create(problems, wkms.allKms(), wkms.allWs(), MAX_DSTANCE_KM);
+    }
+
+    public double getWaterlevel(final double km) {
+        return this.wstInterpolator.value(km);
+    }
+}
\ 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/tkhstate/BedHeightsFinder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,199 @@
+/** 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.tkhstate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.BedHeightsArtifact;
+import org.dive4elements.river.artifacts.math.Linear;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
+import org.dive4elements.river.model.BedHeightValueType;
+import org.dive4elements.river.utils.RiverUtils;
+
+/**
+ * Provides bed heights for various calculations.
+ *
+ * @author Gernot Belger
+ */
+public final class BedHeightsFinder {
+
+    private static double MAX_DISTANCE_KM = 1;
+
+    private final BedHeightInfo info;
+
+    private final NavigableMap<Double, BedHeightValue> values;
+
+    private Calculation problems;
+
+    /**
+     * Create bed height finders from a collection of bed heights.
+     */
+    public static Collection<BedHeightsFinder> createTkhBedHeights(final Calculation problems, final DoubleRange range,
+            final Collection<BedHeight> bedHeights) {
+        final List<BedHeightsFinder> result = new ArrayList<>(bedHeights.size());
+
+        for (final BedHeight bedHeight : bedHeights) {
+            final BedHeightsFinder finder = createBedHeights(problems, bedHeight, range);
+            result.add(finder);
+        }
+
+        return result;
+    }
+
+    public static BedHeightsFinder forId(final CallContext context, final String soundingId, final DoubleRange calcRange, final Calculation problems) {
+
+        // REMARK: absolutely unbelievable....
+        // The way how bed-heights (and other data too) is accessed is different for nearly every calculation-type
+        // throughout flys.
+        // The knowledge on how to parse the datacage-ids is spread through 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");
+
+        // REMARK: 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");
+
+        // REMARK: BedDifferences uses this, but we also need the metadata of the BedHeight
+        // REMARK: 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);
+
+        final BedHeightsFinder bedHeight = bedheightId == null ? null : BedHeightsFinder.forId(problems, bedheightId, calcRange);
+        if (bedHeight == null) {
+            problems.addProblem("sinfo.bedheightsfinder.notfound", soundingId);
+            return null;
+        }
+
+        if (bedHeight.isEmpty()) {
+            problems.addProblem("sinfo.bedheightsfinder.empty");
+            return null;
+        }
+
+        return bedHeight;
+    }
+
+    /**
+     * Creates a {@link BedHeightsFinder} for a dataset from the database, specified by its id.
+     *
+     * @return <code>null</code> if no bed height with the given id exists.
+     */
+    private static BedHeightsFinder forId(final Calculation problems, final int id, final DoubleRange range) {
+
+        final BedHeight bedHeight = BedHeight.getBedHeightById(id);
+        if (bedHeight == null)
+            return null;
+
+        return BedHeightsFinder.createBedHeights(problems, bedHeight, range);
+    }
+
+    /**
+     * Create a finder for a given bed height.
+     *
+     */
+    private static BedHeightsFinder createBedHeights(final Calculation problems, final BedHeight bedHeight, final DoubleRange range) {
+
+        // FIXME: sort by station, but in what direction?
+        // FIXME: using river.getKmUp()?
+        final NavigableMap<Double, BedHeightValue> values = new TreeMap<>();
+
+        for (final BedHeightValue bedHeightValue : bedHeight.getValues()) {
+            final Double station = bedHeightValue.getStation();
+            if (station != null && range.containsDouble(station)) {
+
+                if (bedHeightValue.getHeight() != null)
+                    values.put(station, bedHeightValue);
+            }
+        }
+
+        final BedHeightInfo info = BedHeightInfo.from(bedHeight);
+
+        return new BedHeightsFinder(problems, info, values);
+    }
+
+    private BedHeightsFinder(final Calculation problems, final BedHeightInfo info, final NavigableMap<Double, BedHeightValue> values) {
+        this.info = info;
+        this.values = values;
+        this.problems = problems;
+    }
+
+    public boolean isEmpty() {
+        return this.values.isEmpty();
+    }
+
+    public BedHeightInfo getInfo() {
+        return this.info;
+    }
+
+    public Collection<Double> getStations() {
+        return this.values.keySet();
+    }
+
+    public double getMeanBedHeight(final double km) {
+        return interpolateBedHeights(km, BedHeightValueType.value);
+    }
+
+    public double getMinBedHeight(final double km) {
+        return interpolateBedHeights(km, BedHeightValueType.min);
+    }
+
+    public double getMaxBedHeight(final double km) {
+        return interpolateBedHeights(km, BedHeightValueType.max);
+    }
+
+    private double interpolateBedHeights(final double km, final BedHeightValueType type) {
+        if (this.values.containsKey(km))
+        {
+            final Double value = type.getValue(this.values.get(km));
+            return value == null ? Double.NaN : value.doubleValue();
+        }
+
+        final Entry<Double, BedHeightValue> floorEntry = this.values.floorEntry(km);
+        final Entry<Double, BedHeightValue> ceilingEntry = this.values.ceilingEntry(km);
+
+        if (floorEntry == null || ceilingEntry == null)
+            return Double.NaN;
+
+        final double floorKm = floorEntry.getKey().doubleValue();
+        final double ceilKm = ceilingEntry.getKey().doubleValue();
+
+        /* report once if the interpolation distance exceeds 1000m */
+        if (Math.abs(floorKm - ceilKm) > MAX_DISTANCE_KM && this.problems != null) {
+            this.problems.addProblem(km, "linearInterpolator.maxdistance", MAX_DISTANCE_KM * 1000);
+            this.problems = null;
+            return Double.NaN;
+        }
+
+        final Double floorHeight = type.getValue(floorEntry.getValue());
+        final Double ceilingHeight = type.getValue(ceilingEntry.getValue());
+
+        if (floorHeight == null || ceilingHeight == null)
+            return Double.NaN;
+
+        return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilingHeight);
+    }
+}
\ 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/tkhstate/DefaultBedHeights.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,116 @@
+/** 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.tkhstate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang.math.NumberRange;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.DefaultBedHeightsConfig.DefaultBedHeight;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.Range;
+import org.dive4elements.river.model.River;
+
+/**
+ * This class knows how to find the default bed heights defined for tkh calculation
+ *
+ * @author Gernot Belger
+ */
+final class DefaultBedHeights {
+
+    private final River river;
+
+    public DefaultBedHeights(final River river) {
+        this.river = river;
+    }
+
+    public List<BedHeight> getBedHeights(final Calculation problems) {
+        final Collection<DefaultBedHeight> defaults = DefaultBedHeightsConfig.getDefaults(this.river, problems);
+
+        final List<BedHeight> defaultBedHeights = loadBedHeightsByName(this.river, defaults, problems);
+        if (defaultBedHeights.isEmpty()) {
+            problems.addProblem("sinfo.bedheightsfinder.nobedheightsforriver", this.river.getName());
+            return Collections.emptyList();
+        }
+
+        /* check for overlapping ranges, N2-search, but we expect only have small numbers of bed heights */
+        final List<BedHeight> result = new ArrayList<>(defaultBedHeights.size());
+
+        for (int i = 0; i < defaultBedHeights.size(); i++) {
+            final BedHeight bedHeight = defaultBedHeights.get(i);
+
+            final Range range = bedHeight.getRange();
+            final NumberRange bedRange = new NumberRange(range.getA(), range.getB());
+
+            if (overlapsRange(bedRange, defaultBedHeights, i + 1))
+                problems.addProblem("sinfo.bedheightsfinder.overlappingrange", bedHeight.getDescription());
+            else
+                result.add(bedHeight);
+        }
+
+        final List<BedHeight> validBedHeights = new ArrayList<>(defaultBedHeights.size());
+
+        // REMARK: check for bad ranges because db schema allow for incomplete ranges, and ignore if this is the case
+        for (final BedHeight bedHeight : defaultBedHeights) {
+
+            final Range range = bedHeight.getRange();
+
+            if (range.getA() == null || range.getB() == null)
+                problems.addProblem("sinfo.bedheightsfinder.badrange", bedHeight.getDescription());
+            else
+                validBedHeights.add(bedHeight);
+        }
+
+        return result;
+    }
+
+
+    private static List<BedHeight> loadBedHeightsByName(final River river, final Collection<DefaultBedHeight> defaults, final Calculation problems) {
+
+        final List<BedHeight> bedHeights = new ArrayList<>(defaults.size());
+
+        for (final DefaultBedHeight heightDefault : defaults) {
+
+            final String description = heightDefault.description;
+            try {
+
+                final BedHeight bedHeight = BedHeight.getBedHeightByDescription(river, description, heightDefault.startKm, heightDefault.endKm);
+                if (bedHeight == null)
+                    problems.addProblem("sinfo.bedheightsfinder.missingdescription", river.getName(), description);
+                else
+                    bedHeights.add(bedHeight);
+            }
+            catch (final Exception e) {
+                e.printStackTrace();
+                problems.addProblem("sinfo.bedheightsfinder.missingdescription", river.getName(), description);
+            }
+        }
+
+        return bedHeights;
+    }
+
+    private static boolean overlapsRange(final NumberRange bedRange, final List<BedHeight> result, final int startIndex) {
+
+        for (int i = startIndex; i < result.size(); i++) {
+
+            final BedHeight compareBed = result.get(i);
+            final Range range = compareBed.getRange();
+            final NumberRange compareRange = new NumberRange(range.getA(), range.getB());
+
+            if (compareRange.overlapsRange(bedRange))
+                return true;
+        }
+
+        return false;
+    }
+}
\ 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/tkhstate/DefaultBedHeightsConfig.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,104 @@
+/** 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.tkhstate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.dive4elements.artifacts.common.utils.Config;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.model.River;
+
+/**
+ * Represents the contents of the 'bedheights.properties' files.
+ *
+ * @author Gernot Belger
+ */
+final class DefaultBedHeightsConfig {
+
+    private static final String CONFIG_FILE = "sinfo_tkh_sohlhoehen_%s.properties";
+
+
+    public static class DefaultBedHeight {
+
+        public final String description;
+        public final double startKm;
+        public final double endKm;
+
+        public DefaultBedHeight(final String description, final double startKm, final double endKm) {
+            this.description = description;
+            this.startKm = startKm;
+            this.endKm = endKm;
+        }
+    }
+
+    private static DefaultBedHeightsConfig INSTANCE = new DefaultBedHeightsConfig();
+
+    public static synchronized Collection<DefaultBedHeight> getDefaults(final River river, final Calculation problems) {
+        return INSTANCE.getBedHeightDefaultsForRiver(river, problems);
+    }
+
+    private final Map<String, Collection<DefaultBedHeight>> cache = new HashMap<>();
+
+    private DefaultBedHeightsConfig() {
+    }
+
+
+    private synchronized Collection<DefaultBedHeight> getBedHeightDefaultsForRiver(final River river, final Calculation problems) {
+
+        final String rivername = river.getName();
+        if (!this.cache.containsKey(rivername)) {
+            final Collection<DefaultBedHeight> newDefaults = loadBedHeightDefaultsForRiver(river, problems);
+            this.cache.put(rivername, newDefaults);
+            return newDefaults;
+        }
+
+        return this.cache.get(rivername);
+    }
+
+    private static Collection<DefaultBedHeight> loadBedHeightDefaultsForRiver(final River river, final Calculation problems) {
+
+        try {
+            final String rivername = river.getName();
+            final String filename = String.format(CONFIG_FILE, rivername);
+
+            final Properties properties = Config.loadProperties(filename);
+
+            final Set<String> keys = properties.stringPropertyNames();
+
+            final Collection<DefaultBedHeight> defaults = new ArrayList<>(keys.size());
+
+            for (final String key : keys) {
+
+                final String value = properties.getProperty(key);
+
+                final String[] split = StringUtils.split(StringUtils.trim(value), ';');
+
+                final double startKm = Double.parseDouble(split[0]);
+                final double endKm = Double.parseDouble(split[1]);
+
+                defaults.add(new DefaultBedHeight(key, startKm, endKm));
+            }
+
+            return defaults;
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+            problems.addProblem("sinfo.bedheightsfinder.configfile.loaderror", CONFIG_FILE, e.getMessage());
+            return Collections.emptyList();
+        }
+    }
+}
\ 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/tkhstate/TkhAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,34 @@
+/* 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.tkhstate;
+
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.SinfoCalcMode;
+
+/**
+ * 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
+ */
+final class TkhAccess extends RangeAccess {
+    public TkhAccess(final SINFOArtifact artifact) {
+        super(artifact);
+
+        /* assert calculation mode */
+        final SinfoCalcMode calculationMode = artifact.getCalculationMode();
+        assert (calculationMode == SinfoCalcMode.sinfo_calc_transport_bodies_heights);
+    }
+
+}
\ 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/tkhstate/TkhCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,232 @@
+/** 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.tkhstate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.commons.lang.math.NumberRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.Calculation.Problem;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.states.WaterlevelData;
+import org.dive4elements.river.exports.WaterlevelDescriptionBuilder;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Gernot Belger
+ */
+final class TkhCalculation {
+
+    private final CallContext context;
+
+    public TkhCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+
+        /* access input data */
+        final TkhAccess access = new TkhAccess(sinfo);
+        final River river = access.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+        final DoubleRange calcRange = access.getRange();
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
+        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
+
+        final Calculation problems = new Calculation();
+
+        /* find relevant bed-heights */
+        final List<BedHeight> defaultBedHeights = new DefaultBedHeights(river).getBedHeights(problems);
+        final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(problems, calcRange, defaultBedHeights);
+
+        if (defaultBedHeights.isEmpty()) {
+            final TkhCalculationResults results = new TkhCalculationResults(calcModeLabel, user, riverInfo, calcRange, "");
+            return new CalculationResult(results, problems);
+        }
+
+        final double[] stations = extractStations(bedHeights);
+
+        /* misuse winfo-artifact to calculate waterlevels in the same way */
+        final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo);
+
+        /* calculate waterlevels */
+        final WQKms[] kms = calculateWaterlevels(winfo, stations, problems);
+
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+
+        final WaterlevelDescriptionBuilder descBuilder = new WaterlevelDescriptionBuilder(winfo, this.context);
+        final String descriptionHeader = descBuilder.getColumnHeader();
+
+        /* for each waterlevel, do a tkh calculation */
+        final TkhCalculationResults results = new TkhCalculationResults(calcModeLabel, user, riverInfo, calcRange, descriptionHeader);
+
+        /* determine calculation steps */
+        final Collection<Double> allStations = determineCalculationSteps(bedHeights);
+
+        for (final WQKms wqKms : kms) {
+            final TkhCalculationResult result = calculateResult(calcRange, allStations, infoProvider, wqKms, bedHeights, descBuilder, problems);
+            results.addResult(result, problems);
+        }
+
+        return new CalculationResult(results, problems);
+    }
+
+    private double[] extractStations(final Collection<BedHeightsFinder> bedHeights) {
+
+        final Set<Double> allStations = new TreeSet<>();
+
+        for (final BedHeightsFinder bedHeight : bedHeights)
+            allStations.addAll(bedHeight.getStations());
+
+        return ArrayUtils.toPrimitive(allStations.toArray(new Double[allStations.size()]));
+    }
+
+    /**
+     * Calculation steps are simply the union of all stations of all involved bed-height datasets
+     */
+    private Collection<Double> determineCalculationSteps(final Collection<BedHeightsFinder> bedHeights) {
+
+        final Collection<Double> allStations = new TreeSet<>();
+
+        for (final BedHeightsFinder bedHeight : bedHeights) {
+            final Collection<Double> stations = bedHeight.getStations();
+            allStations.addAll(stations);
+        }
+
+        return allStations;
+    }
+
+    private WQKms[] calculateWaterlevels(final WINFOArtifact winfo, final double[] stations, final Calculation problems) {
+
+        final CalculationResult waterlevelData = winfo.computeWaterlevelData(stations);
+
+        /* copy all problems */
+        final Calculation winfoProblems = waterlevelData.getReport();
+        final List<Problem> problems2 = winfoProblems.getProblems();
+        if (problems2 != null) {
+            for (final Problem problem : problems2) {
+                problems.addProblem(problem);
+            }
+        }
+
+        return (WQKms[]) waterlevelData.getData();
+    }
+
+    private TkhCalculationResult calculateResult(final DoubleRange calcRange, final Collection<Double> allStations, final RiverInfoProvider riverInfo,
+            final WQKms wkms, final Collection<BedHeightsFinder> bedHeights, final WaterlevelDescriptionBuilder descBuilder, final Calculation problems) {
+
+        // We have no wst year as the wst is created by a calculation; we do not need it though
+        final int wspYear = -1;
+        // Remark: showAllGauges only true for Fixierungsanalyse, false for WInfo, so false here as well
+        final boolean showAllGauges = false;
+        final WaterlevelData waterlevel = new WaterlevelData(wkms, wspYear, showAllGauges);
+
+        final RiverInfoProvider riverInfoProvider = riverInfo.forWaterlevel(waterlevel);
+
+        final String waterlevelLabel = descBuilder.getDesc(wkms);
+
+        final WstInfo wstInfo = new WstInfo(waterlevelLabel, wspYear, riverInfoProvider.getReferenceGauge());
+
+        /* build tkh calculators per bedheight */
+        final Map<NumberRange, TkhCalculator> calculatorsByRanges = buildCalculators(calcRange, wkms, bedHeights, problems, riverInfoProvider, waterlevelLabel);
+        if (calculatorsByRanges.isEmpty()) {
+            /* there should already be some problems, so just abort */
+            return null;
+        }
+
+        final Collection<ResultRow> rows = new ArrayList<>();
+
+        for (final Double stationDbl : allStations) {
+
+            final double station = stationDbl;
+
+            /* find the right calculator (i.e. bed height) depending on station, there should only be one maximal */
+            final TkhCalculator tkhCalculator = findCalculator(calculatorsByRanges, station);
+            if (tkhCalculator == null)
+                continue;
+
+            final ResultRow row = ResultRow.create();
+
+            row.putValue(SInfoResultType.waterlevelLabel, waterlevelLabel);
+            row.putValue(SInfoResultType.gaugeLabel, riverInfoProvider.findGauge(station));
+            row.putValue(SInfoResultType.location, riverInfoProvider.getLocation(station));
+
+            if (tkhCalculator.calculateTkh(station, row))
+                rows.add(row);
+        }
+
+        return new TkhCalculationResult(waterlevelLabel, wstInfo, true, rows);
+    }
+
+    private TkhCalculator findCalculator(final Map<NumberRange, TkhCalculator> calculators, final double station) {
+
+        // REMAKR: linear search at this point, put we expect the number of bed heights to be very small (1-2 items)
+        final Set<Entry<NumberRange, TkhCalculator>> x = calculators.entrySet();
+        for (final Entry<NumberRange, TkhCalculator> entry : x) {
+            final NumberRange range = entry.getKey();
+            // FIXME: check if we need comparison with a tolerance
+            if (range.containsDouble(station))
+                return entry.getValue();
+        }
+
+        return null;
+    }
+
+    private Map<NumberRange, TkhCalculator> buildCalculators(final DoubleRange calcRange, final WQKms wkms, final Collection<BedHeightsFinder> bedHeights,
+            final Calculation problems, final RiverInfoProvider riverInfoProvider, final String wstLabel) {
+        final Map<NumberRange, TkhCalculator> calculatorByRanges = new HashMap<>();
+        for (final BedHeightsFinder bedHeightsProvider : bedHeights) {
+
+            final BedHeightInfo info = bedHeightsProvider.getInfo();
+
+            final NumberRange range = new NumberRange(info.getFrom(), info.getTo());
+
+            final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(problems, wkms);
+            final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wkms);
+
+            /* initialize tkh calculator */
+            final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, problems, wstLabel, riverInfoProvider.getRiver(), calcRange,
+                    waterlevelProvider, dischargeProvider, bedHeightsProvider);
+
+            if (tkhCalculator.hasTkh()) {
+                /* just ignore invalid ones, problems have already been updated by buildTkhCalculator() */
+                calculatorByRanges.put(range, tkhCalculator);
+            }
+        }
+
+        return calculatorByRanges;
+    }
+}
\ 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/tkhstate/TkhCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,138 @@
+/* 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.tkhstate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.common.AbstractTkhCalculationResult;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+
+/**
+ * Contains the results of a {@link FloodDurationCalculation}.
+ *
+ * @author Gernot Belger
+ */
+final class TkhCalculationResult extends AbstractTkhCalculationResult {
+
+    private static final long serialVersionUID = 1L;
+    private static final String JASPER_FILE = "/jasper/templates/sinfo.tkh.jrxml";
+
+    private enum ExportMode {
+        pdf, csv
+    }
+
+    public TkhCalculationResult(final String label, final WstInfo wst, final boolean hasTkh, final Collection<ResultRow> rows) {
+        super(label, wst, hasTkh, rows);
+
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContext, final RiverInfo river) {
+
+        final Collection<String> header = new ArrayList<>(11);
+
+        header.add(exportContext.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContext.msgUnitCSV(SInfoResultType.tkh));
+        header.add(exportContext.formatCsvHeader(SInfoResultType.soilkind));
+        header.add(exportContext.msgUnitCSV(SInfoResultType.meanBedHeight, river.getWstUnit()));
+        header.add(exportContext.msgUnitCSV(SInfoResultType.waterlevel, river.getWstUnit()));
+        header.add(exportContext.msgUnitCSV(SInfoResultType.discharge));
+
+        final TkhCalculationResults results = exportContext.getResults();
+        final String descriptionHeader = results.getDescriptionHeader();
+        if (descriptionHeader != null)
+            header.add(descriptionHeader);
+
+        header.add(exportContext.formatCsvHeader(SInfoResultType.gaugeLabel));
+        header.add(exportContext.formatCsvHeader(SInfoResultType.location));
+
+        exportContext.writeCSVLine(header.toArray(new String[header.size()]));
+
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        exportContextCSV.writeCSVWaterlevelMetadata(super.getWst());// TODO: move to super
+        exportContextCSV.writeBlankLine();
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return this.formatRow(exportContextCSV, row, ExportMode.csv);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContext, final ResultRow row) {
+
+        return this.formatRow(exportContext, row, ExportMode.pdf);
+    }
+
+    @Override
+    protected String getJasperFile() {
+        return JASPER_FILE;
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        /* column headings */
+        exportContext.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContext.addJRMetadata(source, "tkh_header", SInfoResultType.tkh);
+        exportContext.addJRMetadata(source, "tkhkind_header", SInfoResultType.soilkind);
+        exportContext.addJRMetadata(source, "bedheight_header", SInfoResultType.meanBedHeight);
+        exportContext.addJRMetadata(source, "waterlevel_header", SInfoResultType.waterlevel);
+        exportContext.addJRMetadata(source, "discharge_header", SInfoResultType.discharge);
+
+        // REMARK: actually the column makes no sense if description header is null. But (software symmetry...) WINFO also
+        // writes an empty column into the pdf in that case (most probably to avoid the need for two jasper templates).
+
+        final TkhCalculationResults results = exportContext.getResults();
+        final String descriptionHeader = results.getDescriptionHeader();
+
+        final String waterlevelNameHeader = descriptionHeader == null ? exportContext.msgPdf(SInfoResultType.waterlevelLabel) : descriptionHeader;
+        exportContext.addJRMetadata(source, "waterlevel_name_header", waterlevelNameHeader);
+
+        exportContext.addJRMetadata(source, "gauge_header", SInfoResultType.gaugeLabel);
+        exportContext.addJRMetadata(source, "location_header", SInfoResultType.location);
+
+    }
+
+    private String[] formatRow(final IExportContext exportContext, final ResultRow row, final ExportMode mode) {
+
+        final Collection<String> lines = new ArrayList<>(11);
+
+        lines.add(exportContext.formatRowValue(row, GeneralResultType.station));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.tkh));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.soilkind));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.meanBedHeight));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.waterlevel));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.discharge));
+
+        // REMARK: always export this column in pdf-mode, because WInfo also does it (no need for two jasper-templates).
+        final TkhCalculationResults results = exportContext.getResults();
+        final String descriptionHeader = results.getDescriptionHeader();
+        if (descriptionHeader != null || mode == ExportMode.pdf)
+            lines.add(exportContext.formatRowValue(row, SInfoResultType.waterlevelLabel));
+
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.gaugeLabel));
+        lines.add(exportContext.formatRowValue(row, SInfoResultType.location));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+}
\ 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/tkhstate/TkhCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,35 @@
+/** 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.tkhstate;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Gernot Belger
+ */
+final class TkhCalculationResults extends AbstractCalculationResults<TkhCalculationResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String descriptionHeader;
+
+    public TkhCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange,
+            final String descriptionHeader) {
+        super(calcModeLabel, user, river, calcRange);
+
+        this.descriptionHeader = descriptionHeader;
+    }
+
+    public String getDescriptionHeader() {
+        return this.descriptionHeader;
+    }
+}
\ 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/tkhstate/TkhExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,43 @@
+/* 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.tkhstate;
+
+import org.dive4elements.river.artifacts.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+
+/**
+ * Generates different output formats (csv, pdf) of data that resulted from a tkh computation.
+ *
+ * @author Gernot Belger
+ */
+// REMARK: must be public because its registered in generators.xml
+public class TkhExporter extends AbstractCommonExporter<TkhCalculationResult, TkhCalculationResults> {
+
+    private static final String CSV_META_CALCULATION_FORMULA = "sinfo.export.tkh.calculation.formula";
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final TkhCalculationResults results) {
+
+        /* write as csv */
+        exportContext.writeCSVGlobalMetadataDefaults(); // ggf auslagern innerhalb dieser Klasse
+
+        // "# Berechnungsgrundlage: Gleichung nach GILL (1971)"
+        exportContext.writeCSVMetaEntry(CSV_META_CALCULATION_FORMULA);
+    }
+
+    @Override
+    protected final void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+
+        source.addMetaData("calculation_label", msg("sinfo.export.flow_depth.pdf.meta.calculation.label"));
+        source.addMetaData("calculation_name", msg("sinfo.export.flow_depth.pdf.meta.calculation.name"));
+    }
+}
\ 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/tkhstate/TkhState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,117 @@
+/* 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.tkhstate;
+
+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.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.D50Processor;
+import org.dive4elements.river.artifacts.sinfo.common.FlowDepthProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.TauProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.TkhProcessor;
+import org.dive4elements.river.artifacts.sinfo.common.VelocityProcessor;
+import org.dive4elements.river.artifacts.states.DefaultState;
+
+/** State in which a waterlevel has been calculated. */
+public class TkhState extends DefaultState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FlowDepthState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 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 = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+
+        final TkhCalculationResults results = (TkhCalculationResults) res.getData();
+
+        /* add themes for chart, for each result */
+        final List<TkhCalculationResult> resultList = results.getResults();
+        for (int index = 0; index < resultList.size(); index++) {
+
+            final TkhCalculationResult result = resultList.get(index);
+
+            facets.add(TkhProcessor.createTkhFacet(context, hash, this.id, result, index));
+
+            facets.add(FlowDepthProcessor.createFlowDepthFilteredFacet(context, hash, this.id, result, index));
+            facets.add(FlowDepthProcessor.createFlowDepthRawFacet(context, hash, this.id, result, index));
+
+            facets.add(VelocityProcessor.createVelocityFacet(context, hash, this.id, result, index));
+            facets.add(D50Processor.createD50Facet(context, hash, this.id, result, index));
+            facets.add(TauProcessor.createTauFacet(context, hash, this.id, result, index));
+        }
+
+        if (!resultList.isEmpty()) {
+            facets.add(new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id));
+            facets.add(new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id));
+        }
+
+        final Calculation report = res.getReport();
+
+        if (report.hasProblems())
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final SINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new TkhCalculation(context).calculate(sinfo);
+    }
+}
\ 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/tkhstate/WinfoArtifactWrapper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,41 @@
+/** 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.tkhstate;
+
+import java.util.Collection;
+
+import org.dive4elements.artifactdatabase.data.DefaultStateData;
+import org.dive4elements.artifactdatabase.data.StateData;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+
+/**
+ * Ugly wrapper around WINfoArtifact in order to a) not to break serialization of WInfoArtifact b) be able to copy data
+ * into it.
+ *
+ * @author Gernot Belger
+ */
+public final class WinfoArtifactWrapper extends WINFOArtifact {
+
+    private static final long serialVersionUID = 1L;
+
+    public WinfoArtifactWrapper(final D4EArtifact dataSource) {
+        final Collection<StateData> allData = dataSource.getAllData();
+        for (final StateData stateData : allData) {
+
+            final DefaultStateData clonedData = new DefaultStateData();
+            clonedData.set(stateData);
+
+            addData(clonedData.getName(), clonedData);
+        }
+
+        addStringData("calculation_mode", "calc.surface.curve");
+    }
+}
\ 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/BedHeightInfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,102 @@
+/** 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.io.Serializable;
+import java.math.BigDecimal;
+
+import org.dive4elements.river.model.BedHeight;
+
+/**
+ * Basic infos about a {@link BedHeight}.
+ *
+ * @author Gernot Belger
+ */
+public final class BedHeightInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final int year;
+
+    private final String description;
+
+    private final String type;
+
+    private final String evaluationBy;
+
+    private final String locationSystem;
+
+    private final String curElevationModelUnit;
+
+    private final String oldElevationModelUnit;
+
+    private final BigDecimal from;
+
+    private final BigDecimal to;
+
+    public static BedHeightInfo from(final BedHeight bedHeight) {
+        return new BedHeightInfo(bedHeight);
+    }
+
+    private BedHeightInfo(final BedHeight bedHeight) {
+        final Integer bhYear = bedHeight.getYear();
+        if (bhYear == null) {
+            // REMARK: this should never happen, as we do not allow the user to select bed heights without a year information
+            throw new IllegalArgumentException("bedHeight has no year");
+        }
+
+        this.year = bhYear;
+        this.description = bedHeight.getDescription();
+        this.type = bedHeight.getType().getName();
+        this.evaluationBy = bedHeight.getEvaluationBy();
+        this.locationSystem = bedHeight.getLocationSystem().getName();
+        this.curElevationModelUnit = bedHeight.getCurElevationModel().getUnit().getName();
+        this.oldElevationModelUnit = bedHeight.getCurElevationModel().getUnit().getName();
+
+        this.from = bedHeight.getRange().getA();
+        this.to = bedHeight.getRange().getB();
+    }
+
+    public int getYear() {
+        return this.year;
+    }
+
+    public String getDescription() {
+        return this.description;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public String getEvaluationBy() {
+        return this.evaluationBy;
+    }
+
+    public String getLocationSystem() {
+        return this.locationSystem;
+    }
+
+    public String getCurElevationModelUnit() {
+        return this.curElevationModelUnit;
+    }
+
+    public String getOldElevationModelUnit() {
+        return this.oldElevationModelUnit;
+    }
+
+    public BigDecimal getFrom() {
+        return this.from;
+    }
+
+    public BigDecimal getTo() {
+        return this.to;
+    }
+}
\ 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/CalculationUtils.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,37 @@
+/** 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 org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactDatabase;
+import org.dive4elements.artifacts.CallContext;
+
+/**
+ * @author Gernot Belger
+ */
+public final class CalculationUtils {
+
+
+    private CalculationUtils() {
+        throw new UnsupportedOperationException("Helper class");
+    }
+
+    /**
+     * Find the the user of the given artifact, sadly this is not part of the calling context, so instead we determine the
+     * owner oft the artifact
+     *
+     * @param artifact
+     * @param context
+     */
+    public static String findArtifactUser(final CallContext context, final Artifact artifact) {
+        final ArtifactDatabase database = context.getDatabase();
+        return database.findArtifactUser(artifact.identifier());
+    }
+}
\ 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/LinearInterpolator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,77 @@
+/** 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.Map.Entry;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.dive4elements.river.artifacts.math.Linear;
+import org.dive4elements.river.artifacts.model.Calculation;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Helper for interpolating values from a piecewise linear function defined by discrete values.
+ *
+ * @author Gernot Belger
+ */
+public final class LinearInterpolator {
+
+    private final NavigableMap<Double, Double> data;
+    private final double maxDistance;
+
+    private Calculation problems;
+
+    public static LinearInterpolator create(final Calculation problems, final TDoubleArrayList xs, final TDoubleArrayList ys, final double maxDistance) {
+        if (xs.size() != ys.size())
+            throw new IllegalArgumentException("Array sizes must be equal");
+
+        if (xs.size() < 2)
+            throw new IllegalArgumentException("Array must have at least 2 values");
+
+        final NavigableMap<Double, Double> data = new TreeMap<>();
+
+        for (int i = 0; i < xs.size(); i++) {
+            final double x = xs.getQuick(i);
+            final double y = ys.getQuick(i);
+            data.put(x, y);
+        }
+
+        return new LinearInterpolator(problems, data, maxDistance);
+    }
+
+    private LinearInterpolator(final Calculation problems, final NavigableMap<Double, Double> data, final double maxDistance) {
+        this.problems = problems;
+        this.data = data;
+        this.maxDistance = maxDistance;
+    }
+
+    public double value(final double value) {
+
+        final Entry<Double, Double> floorEntry = this.data.floorEntry(value);
+        final Entry<Double, Double> ceilingEntry = this.data.ceilingEntry(value);
+
+        if (floorEntry == null || ceilingEntry == null)
+            return Double.NaN;
+
+        final double floorKey = floorEntry.getKey();
+        final double floorValue = floorEntry.getValue();
+        final double ceilingKey = ceilingEntry.getKey();
+        final double ceilingValue = ceilingEntry.getValue();
+
+        if (Math.abs(floorKey - ceilingKey) > this.maxDistance && this.problems != null) {
+            this.problems.addProblem(value, "linearInterpolator.maxdistance", this.maxDistance * 1000);
+            this.problems = null;
+        }
+
+        return Linear.linear(value, floorKey, ceilingKey, floorValue, ceilingValue);
+    }
+}
\ 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/RiverInfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,41 @@
+/** 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.io.Serializable;
+
+import org.dive4elements.river.model.River;
+
+/**
+ * Contains similar data as {@link River}, but is used in instead to avoid keeping database objects.
+ *
+ * @author Gernot Belger
+ */
+public class RiverInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String name;
+
+    private final String wstUnit;
+
+    public RiverInfo(final River river) {
+        this.name = river.getName();
+        this.wstUnit = river.getWstUnit().getName();
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getWstUnit() {
+        return this.wstUnit;
+    }
+}
\ 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/WstInfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,44 @@
+/** 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.io.Serializable;
+
+/**
+ * @author Gernot Belger
+ */
+public final class WstInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String label;
+
+    private final int year;
+
+    private final String gauge;
+
+    public WstInfo(final String label, final int year, final String refGauge) {
+        this.label = label;
+        this.year = year;
+        this.gauge = refGauge;
+    }
+
+    public String getLabel() {
+        return this.label;
+    }
+
+    public int getYear() {
+        return this.year;
+    }
+
+    public String getGauge() {
+        return this.gauge;
+    }
+}
\ 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/states/AddTableDataHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,101 @@
+/** 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.states;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.w3c.dom.Element;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class AddTableDataHelper {
+
+    private final ElementCreator creator;
+    private final Element select;
+    private final CallMeta callmeta;
+    // Create Metadata:
+    final Map<String, Map<String, String>> meta = new HashMap<>();
+    final List<String> columnValidList = new ArrayList<>();
+
+    public AddTableDataHelper(final ElementCreator creator, final Element select, final String pinKeyColumn, final CallMeta callMeta) {
+        this.creator = creator;
+        this.select = select;
+        this.callmeta = callMeta;
+        creator.addAttr(select, "type", "multiattribute", true);
+
+        final Map<String, String> metaTableInfo = new HashMap<>();
+        metaTableInfo.put("keycol", pinKeyColumn);
+        this.meta.put("meta_tableinfo", metaTableInfo);
+
+    }
+
+    public void submitMapToXml() {
+
+        final Element meta = this.creator.create("meta");
+
+        for (final Entry<String, Map<String, String>> entry : this.meta.entrySet()) {
+            final String name = entry.getKey(); // z.B. Spaltenname
+            final Map<String, String> keyValueMap = entry.getValue();
+            final Element element = this.creator.create(name);
+
+            for (final Entry<String, String> kventry : keyValueMap.entrySet()) {
+                this.creator.addAttr(element, kventry.getKey(), kventry.getValue());
+            }
+            meta.appendChild(element);
+        }
+
+        this.select.appendChild(meta);
+
+    }
+
+    public void addRow(final Map<String, String> colValMap) {
+
+        final Element item = this.creator.create("item");
+
+        for (final Entry<String, String> entry : colValMap.entrySet()) {
+            if (this.meta.containsKey(entry.getKey())) {
+                this.creator.addAttr(item, entry.getKey(), entry.getValue() != null ? entry.getValue().toString() : "");
+            } else {
+                try {
+                    throw new Exception("Error: No such column " + entry.getKey());
+                }
+                catch (final Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        this.select.appendChild(item);
+    }
+
+    public void addColumn(final int order, final String rootHashmapKey, final String colWidth, final String translationKeyFromMessages, final String type,
+            final String alignment, final String pinType) {
+
+        final Map<String, String> map = new HashMap<>();
+        map.put("colwidth", colWidth);
+        final String translation = Resources.getMsg(this.callmeta, translationKeyFromMessages);
+        map.put("translation", translation);
+        map.put("type", type);
+        map.put("alignment", alignment);
+        map.put("order", Integer.toString(order));
+        map.put("pin", pinType);
+        this.meta.put(rootHashmapKey, map);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/BooleanChoiceState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,100 @@
+/* Copyright (C) 2011, 2012, 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.states;
+
+import org.w3c.dom.Element;
+
+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.artifactdatabase.ProtocolUtils;
+
+import org.dive4elements.river.artifacts.resources.Resources;
+
+/**
+ * Generic state for a boolean choice. Only difference between real implementations are the human readable labels.
+ * 
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ * @author Gernot Belger
+ */
+public abstract class BooleanChoiceState extends DefaultState {
+
+	private String optionMsg;
+	private String activeMsg;
+	private String inactiveMsg;
+
+    public BooleanChoiceState( String optionMsg, String activeMsg, String inactiveMsg ) {
+		this.optionMsg = optionMsg;
+		this.activeMsg = activeMsg;
+		this.inactiveMsg = inactiveMsg;
+	}
+    
+    private static final Logger log =
+        Logger.getLogger(BooleanChoiceState.class);
+
+    @Override
+    protected String getUIProvider() {
+        return "boolean_panel";
+    }
+
+    @Override
+    protected Element[] createItems(
+        XMLUtils.ElementCreator cr,
+        Artifact    artifact,
+        String      name,
+        CallContext context)
+    {
+        CallMeta meta = context.getMeta();
+
+        Element option = createItem(
+            cr,
+            new String[] { Resources.getMsg(meta, optionMsg, optionMsg), "true" });
+
+        return new Element[] { option };
+    }
+
+
+    @Override
+    protected String getLabelFor(
+        CallContext cc,
+        String      name,
+        String      value,
+        String      type
+    ) {
+        log.debug("GET LABEL FOR '" + name + "' / '" + value + "'");
+        if (value != null && value.equals("true")) {
+            return Resources.getMsg(cc.getMeta(), activeMsg, activeMsg);
+        }
+        else {
+            return Resources.getMsg(cc.getMeta(), inactiveMsg, inactiveMsg);
+        }
+    }
+
+
+    protected Element createItem(XMLUtils.ElementCreator cr, Object obj) {
+        Element item  = ProtocolUtils.createArtNode(cr, "item", null, null);
+        Element label = ProtocolUtils.createArtNode(cr, "label", null, null);
+        Element value = ProtocolUtils.createArtNode(cr, "value", null, null);
+
+        String[] arr = (String[]) obj;
+
+        label.setTextContent(arr[0]);
+        value.setTextContent(arr[1]);
+
+        item.appendChild(label);
+        item.appendChild(value);
+
+        return item;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/ComputationRangeState.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/ComputationRangeState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,76 +9,66 @@
 package org.dive4elements.river.artifacts.states;
 
 import org.apache.log4j.Logger;
-
-import org.w3c.dom.Element;
-
+import org.dive4elements.artifactdatabase.ProtocolUtils;
+import org.dive4elements.artifactdatabase.data.StateData;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
-
 import org.dive4elements.artifacts.common.utils.XMLUtils;
-
-import org.dive4elements.artifactdatabase.ProtocolUtils;
-import org.dive4elements.artifactdatabase.data.StateData;
-
 import org.dive4elements.river.artifacts.D4EArtifact;
-
+import org.dive4elements.river.artifacts.access.RiverAccess;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.resources.Resources;
-import org.dive4elements.river.artifacts.access.RiverAccess;
-
+import org.w3c.dom.Element;
 
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class ComputationRangeState
-extends      RangeState
-implements   FacetTypes
-{
-    private static Logger log =
-        Logger.getLogger(ComputationRangeState.class);
+public class ComputationRangeState extends RangeState implements FacetTypes {
+    private static Logger log = Logger.getLogger(ComputationRangeState.class);
 
     /** The default step width. */
     public static final int DEFAULT_STEP = 100;
 
-
     public ComputationRangeState() {
     }
 
-
     @Override
-    protected Element createData(
-        XMLUtils.ElementCreator cr,
-        Artifact    artifact,
-        StateData   data,
-        CallContext context)
-    {
-        Element select = ProtocolUtils.createArtNode(
-            cr, "select", null, null);
+    protected Element createData(final XMLUtils.ElementCreator cr, final Artifact artifact, final StateData data, final CallContext context) {
+        final Element select = ProtocolUtils.createArtNode(cr, "select", null, null);
 
         cr.addAttr(select, "name", data.getName(), true);
 
-        Element label = ProtocolUtils.createArtNode(
-            cr, "label", null, null);
+        final Element label = ProtocolUtils.createArtNode(cr, "label", null, null);
 
-        label.setTextContent(Resources.getMsg(
-            context.getMeta(),
-            data.getName(),
-            data.getName()));
+        final String msg = getTitle(context);
 
+        label.setTextContent(msg);
+        // VORHER: data.getName(), data.getName())) (entsprach "ld_from", "ld_to" - unterschied zu jetzt: description wird
+        // anders gesetzt ("Wahl der Berechnungsstrecke")
+        // label bleibt "ld_from", "ld_to"; unklar, wo das gesetzt wird. unklar, warum das Element "label" die Description
+        // beeinflusst (und scheinbar nicht das Label)
+
+        final Element description = ProtocolUtils.createArtNode(cr, "description", null, null);
+        description.setTextContent("TEST");
+        select.appendChild(description);
         select.appendChild(label);
 
         return select;
     }
 
+    // REMARK: allows to overwrite the titel which is shown on the client side.
+    // TODO: instead of a fixed string, we should translate the 'id', but in that case we need to change all old workflows
+    // (reason is, that we have different texts for the title and the 'old' title, which in turn is the translation of
+    // 'description').
+
+    protected String getTitle(final CallContext context) {
+        // REMARK: that is how it should be: return Resources.getMsg(context.getMeta(), getID());
+        return Resources.getMsg(context.getMeta(), "state.title.distance_state");
+    }
 
     @Override
-    protected Element[] createItems(
-        XMLUtils.ElementCreator cr,
-        Artifact    artifact,
-        String      name,
-        CallContext context)
-    {
-        double[] minmax = getMinMax(artifact);
+    protected Element[] createItems(final XMLUtils.ElementCreator cr, final Artifact artifact, final String name, final CallContext context) {
+        final double[] minmax = getMinMax(artifact);
 
         double minVal = Double.MIN_VALUE;
         double maxVal = Double.MAX_VALUE;
@@ -86,41 +76,30 @@
         if (minmax != null) {
             minVal = minmax[0];
             maxVal = minmax[1];
-        }
-        else {
+        } else {
             log.warn("Could not read min/max distance values!");
         }
 
         if (name.equals("ld_from")) {
-            Element min = createItem(
-                cr,
-                new String[] {"min", new Double(minVal).toString()});
+            final Element min = createItem(cr, new String[] { "min", new Double(minVal).toString() });
 
             return new Element[] { min };
-        }
-        else if (name.equals("ld_to")) {
-            Element max = createItem(
-                cr,
-                new String[] {"max", new Double(maxVal).toString()});
+        } else if (name.equals("ld_to")) {
+            final Element max = createItem(cr, new String[] { "max", new Double(maxVal).toString() });
 
             return new Element[] { max };
-        }
-        else {
-            Element step = createItem(
-                cr,
-                new String[] {"step", String.valueOf(getDefaultStep())});
+        } else {
+            final Element step = createItem(cr, new String[] { "step", String.valueOf(getDefaultStep()) });
             return new Element[] { step };
         }
 
     }
 
     @Override
-    protected double[] getMinMax(Artifact artifact) {
-        return new RiverAccess((D4EArtifact)artifact).getRiver()
-            .determineMinMaxDistance();
+    protected double[] getMinMax(final Artifact artifact) {
+        return new RiverAccess((D4EArtifact) artifact).getRiver().determineMinMaxDistance();
     }
 
-
     protected double getDefaultStep() {
         return DEFAULT_STEP;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/DistanceOnlyInundationDurSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,22 @@
+/* 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.states;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.resources.Resources;
+
+public class DistanceOnlyInundationDurSelect extends DistanceOnlySelect {
+    @Override
+    protected String getTitle(final CallContext context) {
+        // REMARK: that is how it should be: return Resources.getMsg(context.getMeta(), getID());
+        return Resources.getMsg(context.getMeta(), "state.title.distance_only_inundationduration_state");
+    }
+
+}
+// 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/states/DistanceOnlyPartSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,30 @@
+/* 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.states;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.resources.Resources;
+
+public class DistanceOnlyPartSelect extends DistanceOnlySelect {
+
+    private static Logger log = Logger.getLogger(DistanceOnlyPartSelect.class);
+
+    @Override
+    protected String getUIProvider() {
+        return "distance_only_part_panel";
+    }
+
+    @Override
+    protected String getTitle(final CallContext context) {
+        // REMARK: that is how it should be: return Resources.getMsg(context.getMeta(), getID());
+        return Resources.getMsg(context.getMeta(), "state.title.distance_part_state");
+    }
+
+}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodplainChoice.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodplainChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -26,6 +26,7 @@
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
+// FIXME: inherit from BooleanChoiceState instead to remove duplicate code; BUT: this will probably break artifact serialization
 public class FloodplainChoice extends DefaultState {
 
     public static final String OPTION   = "floodplain.option";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/LoadSingleYearSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,87 @@
+/* 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.states;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.model.CollisionHibernateFactory;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.w3c.dom.Element;
+
+/** State in which to fetch years for sedminent load calculation. */
+public class LoadSingleYearSelectState extends DefaultState {
+    private static final long serialVersionUID = 1L;
+    /** The log used in this class. */
+    private static Logger log = Logger.getLogger(LoadSingleYearSelectState.class);
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadSingleYearSelectState() {
+    }
+
+    /** Year Select Widget. */
+    @Override
+    protected String getUIProvider() {
+        return "common.state.load_single_year_select";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+        final String dataKey = "singleyear";
+        try {
+            if (dataKey.equals(name)) {
+
+                final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta()); // pinKeycolum; nicht zu verweschseln mit
+                                                                                                                      // datakey..artifact.
+
+                helper.addColumn(0, "pinfrom", "60", "common.client.ui.selection", "ICON", "CENTER", "from");
+                helper.addColumn(1, "year", "60", "year", "INTEGER", "LEFT", null);
+
+                final RiverAccess access = new RiverAccess((D4EArtifact) artifact);
+                final List<Collision> collisions = CollisionHibernateFactory.getCollisionsByRiver(access.getRiver());// TODO: DATASOURCE?! Has to be
+                                                                                                                     // uinfo.inundation_duration
+                // (Ãœberflutungsdauern Aue) irgendwas...
+
+                for (final Collision coll : collisions) {
+                    final Integer year = coll.getYear();
+                    final Map<String, String> row = new HashMap<>();
+                    row.put("year", year.toString()); // Nullpointer-Check?
+                    helper.addRow(row);
+
+                }
+                helper.submitMapToXml();
+            }
+        }
+        catch (final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+
+    @Override
+    public boolean validate(final Artifact artifact) throws IllegalArgumentException {
+        return true;
+        // final CollisionLoadYearEpochAccess access = new CollisionLoadYearEpochAccess((D4EArtifact) artifact);
+        //
+        // // Second year should be later than first.
+        // if (access.getYears() == null || access.getYears().length == 0)
+        // return true; // TODO: richtig in CollisionLoadYear... implementieren
+        // // throw new IllegalArgumentException("error_years_wrong");
+        //
+        // return true;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/LocationDistanceSelect.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/LocationDistanceSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,23 +9,18 @@
 package org.dive4elements.river.artifacts.states;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.artifactdatabase.data.StateData;
 import org.dive4elements.artifacts.Artifact;
-
-import org.dive4elements.artifactdatabase.data.StateData;
-
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.WINFOArtifact;
-
 import org.dive4elements.river.artifacts.access.RangeAccess;
-
+import org.dive4elements.river.artifacts.resources.Resources;
 
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class LocationDistanceSelect
-extends      ComputationRangeState
-{
+public class LocationDistanceSelect extends ComputationRangeState {
 
     /** The log used in this class. */
     private static Logger log = Logger.getLogger(LocationDistanceSelect.class);
@@ -36,55 +31,46 @@
     /** The name of the 'locations' field. */
     public static final String LOCATIONS = "ld_locations";
 
-
     /**
      * The default constructor that initializes an empty State object.
      */
     public LocationDistanceSelect() {
     }
 
-
     @Override
     protected String getUIProvider() {
         return "location_distance_panel";
     }
 
-
     /** Validates the range (or location). */
     @Override
-    public boolean validate(Artifact artifact)
-    throws IllegalArgumentException
-    {
+    public boolean validate(final Artifact artifact) throws IllegalArgumentException {
         log.debug("LocationDistanceSelect.validate");
 
-        D4EArtifact flys = (D4EArtifact)artifact;
-        StateData mode = getData(flys, MODE);
-        String mValue = mode != null ? (String)mode.getValue() : null;
+        final D4EArtifact flys = (D4EArtifact) artifact;
+        final StateData mode = getData(flys, MODE);
+        final String mValue = mode != null ? (String) mode.getValue() : null;
         if (mValue != null) {
             if (mValue.equals("distance")) {
                 return super.validate(flys);
-            }
-            else {
+            } else {
                 return validateLocations(flys);
             }
         }
         return false;
     }
 
-
     /** Validate selected locations. */
-    protected boolean validateLocations(D4EArtifact flys)
-    throws    IllegalArgumentException
-    {
-        StateData dValues = getData(flys, LOCATIONS);
-        String    values  = dValues != null ? (String)dValues.getValue() : null;
+    protected boolean validateLocations(final D4EArtifact flys) throws IllegalArgumentException {
+        final StateData dValues = getData(flys, LOCATIONS);
+        final String values = dValues != null ? (String) dValues.getValue() : null;
 
         if (values == null || values.length() == 0) {
             throw new IllegalArgumentException("error_empty_state");
         }
 
-        double[] absMinMax = getMinMax(flys);
-        double[] relMinMax = getMinMaxFromString(values);
+        final double[] absMinMax = getMinMax(flys);
+        final double[] relMinMax = getMinMaxFromString(values);
 
         if (relMinMax[0] < absMinMax[0] || relMinMax[0] > absMinMax[1]) {
             throw new IllegalArgumentException("error_feed_from_out_of_range");
@@ -97,45 +83,46 @@
         return true;
     }
 
-
     /**
      * Extracts the min/max values from String <i>s</i>. An
      * IllegalArgumentException is thrown if there is a value that throws a
      * NumberFormatException.
      *
-     * @param s String that contains whitespace separated double values.
+     * @param s
+     *            String that contains whitespace separated double values.
      *
      * @return a 2dmin array [min,max].
      */
-    public static double[] getMinMaxFromString(String s)
-    throws IllegalArgumentException
-    {
-        String[] values = s.split(" ");
+    public static double[] getMinMaxFromString(final String s) throws IllegalArgumentException {
+        final String[] values = s.split(" ");
 
-        double[] minmax = new double[] {
-            Double.MAX_VALUE,
-            -Double.MAX_VALUE };
+        final double[] minmax = new double[] { Double.MAX_VALUE, -Double.MAX_VALUE };
 
-        for (String v: values) {
+        for (final String v : values) {
             try {
-                double value = Double.valueOf(v);
+                final double value = Double.valueOf(v);
 
                 minmax[0] = minmax[0] < value ? minmax[0] : value;
                 minmax[1] = minmax[1] > value ? minmax[1] : value;
             }
-            catch (NumberFormatException nfe) {
-                throw new IllegalArgumentException(
-                    "error_invalid_double_value");
+            catch (final NumberFormatException nfe) {
+                throw new IllegalArgumentException("error_invalid_double_value");
             }
         }
 
         return minmax;
     }
 
-
-    public static double[] getLocations(WINFOArtifact flys) {
-        RangeAccess ra = new RangeAccess(flys);
+    public static double[] getLocations(final WINFOArtifact flys) {
+        final RangeAccess ra = new RangeAccess(flys);
         return ra.getLocations();
     }
+
+    @Override
+    protected String getTitle(final CallContext context) {
+        // REMARK: that is how it should be: return Resources.getMsg(context.getMeta(), getID());
+        return Resources.getMsg(context.getMeta(), "state.title.location_distance_state");
+    }
+
 }
 // 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/states/RadioSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,71 @@
+/** 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.states;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+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.w3c.dom.Element;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class RadioSelect extends DefaultState {
+
+    private static final long serialVersionUID = 1L;
+    private Artifact artifact;
+
+    public RadioSelect() {
+
+    }
+
+    protected abstract LinkedHashMap<String, String> makeEntries(CallMeta meta, Artifact artifact); // AUSNAHMSWEISE EXPLIZITER TYP, damit Reihenfolge nicht
+                                                                                                    // verrutscht
+
+    @Override
+    protected final String getUIProvider() {
+        return "radio_panel";
+    }
+
+    @Override
+    protected Element[] createItems(final XMLUtils.ElementCreator ec, final Artifact artifact, final String name, final CallContext context) {
+
+        // REMEBER: we need it for getLabelFor later
+        this.artifact = artifact;
+
+        final CallMeta meta = context.getMeta();
+        final Map<String, String> entries = makeEntries(meta, artifact);
+
+        final Element[] elements = new Element[entries.size()];
+        int i = 0;
+        for (final String key : entries.keySet()) {
+            final String label = entries.get(key);
+            final String labelToSet = label != null ? label : Resources.getMsg(meta, key);
+            elements[i] = createItem(ec, new String[] { labelToSet, key });
+            i++;
+        }
+        return elements;
+    }
+
+    @Override
+    protected String getLabelFor(final CallContext cc, final String name, final String value, final String type) {
+        // artifacts must be set in "createItems" -> createItems has to be called first
+        final Map<String, String> entries = makeEntries(cc.getMeta(), this.artifact);
+
+        final String valueToSet = entries.get(value) != null ? entries.get(value) : value;
+        return super.getLabelFor(cc, name, valueToSet, type);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/RangeState.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/RangeState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,45 +8,33 @@
 
 package org.dive4elements.river.artifacts.states;
 
+import org.apache.log4j.Logger;
 import org.dive4elements.artifacts.Artifact;
-
 import org.dive4elements.river.artifacts.D4EArtifact;
-
 import org.dive4elements.river.artifacts.access.RangeAccess;
 
-import org.apache.log4j.Logger;
-
-
 /**
  * State in which km range is set.
+ * 
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
 public abstract class RangeState extends DefaultState {
 
     /** The log that is used in this class. */
-    private Logger log = Logger.getLogger(RangeState.class);
-
+    private final Logger log = Logger.getLogger(RangeState.class);
 
     public RangeState() {
     }
 
     protected abstract double[] getMinMax(Artifact artifact);
 
-
-    protected boolean validateBounds(
-        double fromValid, double toValid,
-        double from,      double to)
-    throws IllegalArgumentException
-    {
-        if (from < fromValid) {
-            log.error(
-                "Invalid 'from'. " + from + " is smaller than " + fromValid);
+    protected boolean validateBounds(final double fromValid, final double toValid, final double from, final double to) throws IllegalArgumentException {
+        if (from < fromValid || from > toValid) {
+            this.log.error("Invalid 'from'. " + from + " is smaller than " + fromValid);
             // error message used in client to resolve i18n
             throw new IllegalArgumentException("error_feed_from_out_of_range");
-        }
-        else if (to > toValid) {
-            log.error(
-                "Invalid 'to'. " + to + " is bigger than " + toValid);
+        } else if (to > toValid || to < fromValid) {
+            this.log.error("Invalid 'to'. " + to + " is bigger than " + toValid);
             // error message used in client to resolve i18n
             throw new IllegalArgumentException("error_feed_to_out_of_range");
         }
@@ -54,50 +42,48 @@
         return true;
     }
 
-
     /**
      * Validates a given range with a given valid range.
      *
-     * @param fromValid Valid lower value of the range.
-     * @param toValid Valid upper value of the range.
-     * @param from The lower value.
-     * @param to The upper value.
-     * @param step The step width.
+     * @param fromValid
+     *            Valid lower value of the range.
+     * @param toValid
+     *            Valid upper value of the range.
+     * @param from
+     *            The lower value.
+     * @param to
+     *            The upper value.
+     * @param step
+     *            The step width.
      *
      * @return true, if everything was fine, otherwise an exception is thrown.
      */
-    protected boolean validateBounds(
-        double fromValid, double toValid,
-        double from,      double to,      double step)
-    throws IllegalArgumentException
-    {
-        log.debug("RangeState.validateRange");
+    protected boolean validateBounds(final double fromValid, final double toValid, final double from, final double to, final double step)
+            throws IllegalArgumentException {
+        this.log.debug("RangeState.validateRange");
 
         // XXX The step width is not validated at the moment!
         return validateBounds(fromValid, toValid, from, to);
     }
 
-
     @Override
-    public boolean validate(Artifact artifact)
-    throws IllegalArgumentException
-    {
-        D4EArtifact flys = (D4EArtifact) artifact;
+    public boolean validate(final Artifact artifact) throws IllegalArgumentException {
+        final D4EArtifact flys = (D4EArtifact) artifact;
 
         try {
-            RangeAccess rangeAccess = new RangeAccess(flys);
-            double from = rangeAccess.getFrom();
-            double to   = rangeAccess.getTo();
-            double step = rangeAccess.getStep();
+            final RangeAccess rangeAccess = new RangeAccess(flys);
+            final double from = rangeAccess.getFrom();
+            final double to = rangeAccess.getTo();
+            final double step = rangeAccess.getStep();
 
-            double[] minmax = getMinMax(flys);
+            final double[] minmax = getMinMax(flys);
 
             return validateBounds(minmax[0], minmax[1], from, to, step);
         }
-        catch (NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             throw new IllegalArgumentException("error_invalid_double_value");
         }
-        catch (NullPointerException npe) {
+        catch (final NullPointerException npe) {
             throw new IllegalArgumentException("error_empty_state");
         }
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -25,6 +25,7 @@
 import org.dive4elements.river.artifacts.FixationArtifact;
 import org.dive4elements.river.artifacts.MINFOArtifact;
 import org.dive4elements.river.artifacts.StaticWKmsArtifact;
+import org.dive4elements.river.artifacts.StaticWQKmsArtifact;
 import org.dive4elements.river.artifacts.WINFOArtifact;
 
 import org.dive4elements.river.artifacts.math.WKmsOperation;
@@ -109,6 +110,8 @@
     /**
      * Access the data (wkms) of an artifact, coded in mingle.
      */
+    // FIXME: meanwhile used by several places outside this context; refactor into separate helper class to access waterlevels
+    // FIXME: use org.dive4elements.river.artifacts.states.WaterlevelFetcher instead
     public WKms getWKms(
         String mingle,
         CallContext context,
@@ -137,6 +140,16 @@
             WKms wkms = staticWKms.getWKms(idx, from, to);
             if (wkms == null) {
                 log.error("No WKms from Static artifact for this range.");
+                // FIXME: why does in error case we return Q's?
+                return new WQKms();
+            }
+            return wkms; /* No need for additional km filtering */
+        } else if (d4eArtifact instanceof StaticWQKmsArtifact) {
+            final StaticWQKmsArtifact staticWKms = (StaticWQKmsArtifact) d4eArtifact;
+            log.debug("WDifferencesState obtain data from StaticWQKms");
+            WQKms wkms = staticWKms.getWQKms(from, to);
+            if (wkms == null) {
+                log.error("No WKms from Static artifact for this range.");
                 return new WQKms();
             }
             return wkms; /* No need for additional km filtering */
@@ -148,6 +161,7 @@
                                               getData();
             if (wkms == null || wkms.length == 0) {
                 log.warn("no waterlevels in artifact");
+                // FIXME: fall through will lead to exception...
             }
             else if (wkms.length < idx+1) {
                 log.warn("Not enough waterlevels in artifact.");
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WQSelect.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WQSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -30,10 +30,10 @@
 import org.dive4elements.river.model.Wst;
 
 import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.WINFOArtifact;
 
 import org.dive4elements.river.artifacts.access.RangeAccess;
-
+import org.dive4elements.river.artifacts.access.RangeAccess.KM_MODE;
+import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
 import org.dive4elements.river.artifacts.model.WstFactory;
 import org.dive4elements.river.artifacts.model.WstValueTable;
 import org.dive4elements.river.artifacts.model.WstValueTableFactory;
@@ -104,8 +104,6 @@
         Boolean isQ = flys.getDataAsBoolean(WQ_MODE);
         Boolean isFree = flys.getDataAsBoolean(WQ_FREE);
 
-        WINFOArtifact winfo = (WINFOArtifact) flys;
-
         Element dataElement = creator.create("data");
         creator.addAttr(dataElement, "name", name, true);
         creator.addAttr(dataElement, "type", type, true);
@@ -116,10 +114,10 @@
         String label;
 
         if (!isQ || isFree) {
-            label = getLabel(winfo, cc, value);
+            label = getLabel(flys, cc, value);
         }
         else {
-            label = getSpecialLabel(winfo, cc, value);
+            label = getSpecialLabel(flys, cc, value);
         }
 
         creator.addAttr(itemElement, "label", label, true);
@@ -131,7 +129,7 @@
 
 
     protected static String getLabel(
-        WINFOArtifact winfo,
+        D4EArtifact winfo,
         CallContext   cc,
         String        raw
     ) {
@@ -167,7 +165,7 @@
 
 
     protected static String getSpecialLabel(
-        WINFOArtifact winfo,
+        D4EArtifact winfo,
         CallContext   cc,
         String        raw
     ) {
@@ -250,12 +248,12 @@
         String      name,
         CallContext context
     ){
-        WINFOArtifact winfo = (WINFOArtifact) artifact;
+        D4EArtifact flys = (D4EArtifact) artifact;
 
-        double[] minmaxW     = determineMinMaxW(winfo);
-        double[] minmaxWFree = determineMinMaxWFree(winfo);
-        double[] minmaxQ     = determineMinMaxQAtGauge(winfo);
-        double[] minmaxQFree = determineMinMaxQ(winfo);
+        double[] minmaxW     = determineMinMaxW(flys);
+        double[] minmaxWFree = determineMinMaxWFree(flys);
+        double[] minmaxQ     = determineMinMaxQAtGauge(flys);
+        double[] minmaxQFree = determineMinMaxQ(flys);
 
         if (name.equals("wq_from")) {
             Element minW = createItem(cr, new String[] {
@@ -400,7 +398,7 @@
      *
      * @return the min and max W values for the current gauge.
      */
-    protected double[] determineMinMaxW(WINFOArtifact winfo) {
+    protected double[] determineMinMaxW(D4EArtifact winfo) {
         log.debug("WQSelect.determineCurrentGauge");
 
         RangeAccess rangeAccess = new RangeAccess(winfo);
@@ -425,24 +423,20 @@
      *
      * @return the min and max W values.
      */
-    protected double[] determineMinMaxWFree(WINFOArtifact winfo) {
+    protected double[] determineMinMaxWFree(D4EArtifact winfo) {
         log.debug("WQSelect.determineMinMaxWFree");
 
         WstValueTable valueTable = WstValueTableFactory.getTable(
                 RiverUtils.getRiver(winfo));
 
+        ComputationRangeAccess access = new ComputationRangeAccess(winfo);
+        
         double[] minmaxW = null;
         if(valueTable != null) {
-            double[] km = null;
-            if(new RangeAccess(winfo).isRange()) {
-                km = winfo.getFromToStep();
-                // Use the start km to determine the min max values.
-                minmaxW = valueTable.getMinMaxW(km[0]);
-            }
-            else {
-                km = winfo.getKms();
-                minmaxW = valueTable.getMinMaxW(km[0]);
-            }
+
+            final double startKm = access.getStartKm();
+            // Use the start km to determine the min max values.
+            minmaxW = valueTable.getMinMaxW(startKm);
         }
         return minmaxW != null
             ? minmaxW
@@ -459,7 +453,7 @@
      *
      * @return the min and max Q values for the current gauge.
      */
-    protected double[] determineMinMaxQAtGauge(WINFOArtifact winfo) {
+    protected double[] determineMinMaxQAtGauge(D4EArtifact winfo) {
         log.debug("WQSelect.determineMinMaxQAtGauge");
 
         RangeAccess rangeAccess = new RangeAccess(winfo);
@@ -488,21 +482,31 @@
      *
      * @return the min and max Q values for the current kilometer range.
      */
-    protected double[] determineMinMaxQ(WINFOArtifact winfo) {
+    protected double[] determineMinMaxQ(D4EArtifact winfo) {
         log.debug("WQSelect.determineMinMaxQ");
 
-        WstValueTable valueTable = WstValueTableFactory.getTable(
-                RiverUtils.getRiver(winfo));
+        final WstValueTable valueTable = WstValueTableFactory.getTable(RiverUtils.getRiver(winfo));
 
+        final ComputationRangeAccess access = new ComputationRangeAccess(winfo);
+        
         double[] minmaxQ = null;
         if(valueTable != null) {
-            double[] km = null;
-            if(new RangeAccess(winfo).isRange()) {
-                km = winfo.getFromToStep();
+            
+            final KM_MODE mode = access.getKmRangeMode();
+            switch (mode) {
+            case RANGE: {
+                final double[] km =  access.getFromToStep();
                 minmaxQ = valueTable.getMinMaxQ(km[0], km[1], km[2]);
+                break;
             }
-            else {
-                km = winfo.getKms();
+            
+            case DISTANCE_ONLY: {
+                minmaxQ = valueTable.getMinMaxQ(access.getFrom(), access.getTo(), 0.1);
+                break;
+            }
+
+            default: {
+                final double[] km = access.getKms();
                 minmaxQ = valueTable.getMinMaxQ(km[0]);
                 for (int i = 1; i < km.length; i++) {
                     double[] tmp = valueTable.getMinMaxQ(km[i]);
@@ -513,6 +517,8 @@
                         minmaxQ[1] = tmp[1];
                     }
                 }
+                break;
+            }
             }
         }
         return minmaxQ != null
@@ -527,7 +533,7 @@
     {
         log.debug("WQSelect.validate");
 
-        WINFOArtifact flys = (WINFOArtifact) artifact;
+        D4EArtifact flys = (D4EArtifact) artifact;
 
         StateData data       = getData(flys, WQ_SELECTION);
         boolean isRange = data != null
@@ -567,7 +573,7 @@
     }
 
 
-    protected boolean validateSingle(WINFOArtifact artifact)
+    protected boolean validateSingle(D4EArtifact artifact)
     throws    IllegalArgumentException
     {
         log.debug("WQSelect.validateSingle");
@@ -623,7 +629,7 @@
     }
 
 
-    protected boolean validateRange(WINFOArtifact artifact)
+    protected boolean validateRange(D4EArtifact artifact)
     throws    IllegalArgumentException
     {
         log.debug("WQSelect.validateRange");
@@ -685,7 +691,7 @@
      * @return true, if everything was fine, otherwise an exception is thrown.
      */
     protected boolean validateGaugeW(
-        WINFOArtifact    artifact,
+        D4EArtifact    artifact,
         double from,
         double to,
         double step)
@@ -711,7 +717,7 @@
      * @return true, if everything was fine, otherwise an exception is thrown.
      */
     protected boolean validateGaugeQ(
-        WINFOArtifact artifact,
+        D4EArtifact artifact,
         double   from,
         double   to,
         double   step)
@@ -737,7 +743,7 @@
      * @return true, if everything was fine, otherwise an exception is thrown.
      */
     protected boolean validateFreeQ(
-        WINFOArtifact artifact,
+        D4EArtifact artifact,
         double   from,
         double   to,
         double   step)
@@ -763,7 +769,7 @@
      * @return true, if everything was fine, otherwise an exception is thrown.
      */
     protected boolean validateFreeW(
-        WINFOArtifact artifact,
+        D4EArtifact artifact,
         double   from,
         double   to,
         double   step)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelData.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,93 @@
+/** 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.states;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.model.WKms;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Represents a waterlevel fetched with the {@link WaterlevelFetcher}.
+ *
+ * @author Gernot Belger
+ */
+public class WaterlevelData {
+    private final WKms wkms;
+
+    private final String name;
+
+    private final int year;
+
+    /** If <code>true</code>, tabular export will show gauges for every station, else only for the first gauge */
+    private final boolean showAllGauges;
+
+    public WaterlevelData(final WKms wkms, final int year) {
+        this(wkms, year, false);
+    }
+
+    public WaterlevelData(final WKms wkms, final int year, final boolean showAllGauges) {
+        this(wkms.getName(), wkms, year, showAllGauges);
+    }
+
+    private WaterlevelData(final String name, final WKms wkms, final int year, final boolean showAllGauges) {
+        this.name = name;
+        this.wkms = wkms;
+        this.year = year;
+        this.showAllGauges = showAllGauges;
+    }
+
+    public WaterlevelData filterByRange(final double from, final double to) {
+        if (Double.isNaN(from) || Double.isNaN(to)) {
+            return this;
+        }
+
+        final WKms filteredWkms = this.wkms.filteredKms(from, to);
+        return new WaterlevelData(this.name, filteredWkms, this.year, this.showAllGauges);
+    }
+
+    public WaterlevelData withName(final String nameToSet) {
+        return new WaterlevelData(nameToSet, this.wkms, this.year, this.showAllGauges);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public WKms getWkms() {
+        return this.wkms;
+    }
+
+    public boolean isShowAllGauges() {
+        return this.showAllGauges;
+    }
+
+    public int getYear() {
+        return this.year;
+    }
+
+    public boolean covers(final DoubleRange simulationRange) {
+
+        final TDoubleArrayList allKms = this.wkms.allKms();
+
+        if (allKms.isEmpty())
+            return false;
+
+        final double min = allKms.min();
+        if (min > simulationRange.getMaximumDouble())
+            return false;
+
+        final double max = allKms.max();
+        if (max < simulationRange.getMinimumDouble())
+            return false;
+
+        return true;
+    }
+}
\ 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/states/WaterlevelFetcher.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,204 @@
+/** 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.states;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.FixationArtifact;
+import org.dive4elements.river.artifacts.StaticWKmsArtifact;
+import org.dive4elements.river.artifacts.StaticWQKmsArtifact;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.access.FixRealizingAccess;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.Segment;
+import org.dive4elements.river.artifacts.model.WKms;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.model.WstColumnFactory;
+import org.dive4elements.river.artifacts.model.fixings.FixRealizingCalculationExtended;
+import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.model.TimeInterval;
+import org.dive4elements.river.model.WstColumn;
+import org.dive4elements.river.utils.RiverUtils;
+
+/**
+ * Helper class that accesses existing waterlevels (in most cases) from the data-cage.
+ * This is mainly a refaktoring of org.dive4elements.river.artifacts.states.WDifferencesState.getWKms(String,
+ * CallContext, double, double), adding more infos to the fetched water levels.
+ *
+ * @author Gernot Belger
+ */
+public class WaterlevelFetcher {
+    private static Logger log = Logger.getLogger(WaterlevelFetcher.class);
+
+    /**
+     * @param simulationRange
+     *            This range is used to check if the found waterlevel covers it. It is NOT used to reduce the fetched data,
+     *            because in case of waterlevels we always need to full set in order to determine the relevant gauge.
+     */
+    public WaterlevelData findWaterlevel(final CallContext context, final String mingle, final DoubleRange simulationRange, final Calculation problems) {
+
+        final String[] def = mingle.split(";");
+        final String uuid = def[0];
+        // final String factory = def[1];
+        final int idx = Integer.parseInt(def[2]);
+        final String name = def[3];
+        final D4EArtifact d4eArtifact = RiverUtils.getArtifact(uuid, context);
+        if (d4eArtifact == null)
+            return null;
+
+        final WaterlevelData data = fetchWaterlevelFromArtifact(context, d4eArtifact, idx, Double.NaN, Double.NaN);
+        if (data == null) {
+            problems.addProblem("waterlevelfetcher.missing", mingle);
+            return null;
+        }
+
+        if (!data.covers(simulationRange)) {
+            problems.addProblem("waterlevelfetcher.empty", data.getName());
+            return null;
+        }
+
+        return data.withName(name);
+    }
+
+    private WaterlevelData fetchWaterlevelFromArtifact(final CallContext context, final D4EArtifact d4eArtifact, final int idx, final double from,
+            final double to) {
+
+        if (d4eArtifact instanceof StaticWKmsArtifact) {
+            return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, idx, from, to);
+        }
+
+        if (d4eArtifact instanceof StaticWQKmsArtifact) {
+            return fetchStaticWQKmsArtifactWaterlevel((StaticWQKmsArtifact) d4eArtifact, from, to);
+        }
+
+        if (d4eArtifact instanceof WINFOArtifact)
+            return fetchWINFOArtifactWaterlevel(context, (WINFOArtifact) d4eArtifact, idx, from, to);
+
+        if (d4eArtifact instanceof FixationArtifact)
+            return fetchFixationArtifactWaterlevel(context, (FixationArtifact) d4eArtifact, idx, from, to);
+
+        log.warn(String.format("Get Waterlevel from %s not implemented!", d4eArtifact.getClass().getSimpleName()));
+        return null;
+    }
+
+    // REMARK: instead of several helper methods here this would be a good place for abstraction, in order to push
+    // this logic back to the corresponding artifacts. However this will most certainly break existing
+    // artifact-serialization
+
+    private WaterlevelData fetchStaticWKmsArtifactWaterlevel(final StaticWKmsArtifact staticWKms, final int idx, final double from, final double to) {
+
+        log.debug("WDifferencesState obtain data from StaticWKms");
+
+        final WKms wkms = staticWKms.getWKms(idx, from, to);
+
+        if (wkms != null) {
+            final int year = fetchStaticWKmsYear(staticWKms);
+            return new WaterlevelData(wkms, year);
+        }
+
+        log.error("No WKms from Static artifact for this range.");
+        return null;
+    }
+
+    private WaterlevelData fetchStaticWQKmsArtifactWaterlevel(final StaticWQKmsArtifact staticWKms, final double from, final double to) {
+
+        log.debug("WDifferencesState obtain data from StaticWQKms");
+
+        final WQKms wkms = staticWKms.getWQKms(from, to);
+
+        if (wkms != null) {
+            final int year = fetchStaticWKmsYear(staticWKms);
+            return new WaterlevelData(wkms, year);
+        }
+
+        log.error("No WKms from Static artifact for this range.");
+        return null;
+    }
+
+    private WaterlevelData fetchWINFOArtifactWaterlevel(final CallContext context, final WINFOArtifact flys, final int idx, final double from,
+            final double to) {
+        log.debug("Get WKms from WINFOArtifact");
+
+        final WKms[] wkms = (WKms[]) flys.getWaterlevelData(context).getData();
+
+        if (wkms == null || wkms.length == 0) {
+            log.warn("no waterlevels in artifact");
+            return null;
+        }
+
+        if (wkms.length < idx + 1) {
+            log.warn("Not enough waterlevels in artifact.");
+            return null;
+        }
+
+        // REAMRK: W_INFO results does not know any 'year'
+        final int year = -1;
+        return new WaterlevelData(wkms[idx], year).filterByRange(from, to);
+    }
+
+    private WaterlevelData fetchFixationArtifactWaterlevel(final CallContext context, final FixationArtifact fixation, final int idx, final double from,
+            final double to) {
+
+        log.debug("Get WKms from FixationArtifact.");
+
+        final CalculationResult r = (CalculationResult) fixation.compute(context, ComputeType.ADVANCE, false);
+        final FixRealizingResult frR = (FixRealizingResult) r.getData();
+
+        // Get W/Q input per gauge for this case.
+        final FixRealizingAccess fixAccess = new FixRealizingAccess(fixation);
+        final List<Segment> segments = fixAccess.getSegments();
+        final boolean isFixRealize = (segments != null && !segments.isEmpty());
+
+        /* ugly but necessary to keep this logic at least a bit inside the FixRealizing stuff */
+        final FixRealizingCalculationExtended calculation = new FixRealizingCalculationExtended(fixAccess);
+        final int year = calculation.determineMeanYear();
+
+        // REMARK: same logic as in WaterlevelExporter
+        final boolean showAllGauges = isFixRealize;
+
+        return new WaterlevelData(frR.getWQKms()[idx], year, showAllGauges).filterByRange(from, to);
+    }
+
+    /**
+     * Fetches the 'year' for a staticXXX-artifact.
+     * REMARK: actually this should happen inside the staticWKms artifact and eventually in the WKmsFactory, but the code
+     * there is already awful and it will also break the old artifact-serialization...
+     */
+    private int fetchStaticWKmsYear(final D4EArtifact staticWKms) {
+
+        final int colPos = Integer.parseInt(staticWKms.getDataAsString("col_pos"));
+        final int wstId = Integer.parseInt(staticWKms.getDataAsString("wst_id"));
+
+        final WstColumn wstColumn = WstColumnFactory.getWstColumn(wstId, colPos);
+        final TimeInterval timeInterval = wstColumn.getTimeInterval();
+        if (timeInterval == null)
+            return -1;
+
+        final Date startTime = timeInterval.getStartTime();
+        if (startTime == null)
+            return -1;
+
+        // REMARK: the times are stored without timezone in the DB, so it is unclear what hibernate makes of it.
+        // We simply use the default timezone here and hope we never get problems...
+        // Actually we always have 12:00 as time in the db data, so a smal timeshift due to winter/sommertime or UTC/GMT+1 will
+        // no change anything regarding the year.
+        final Calendar cal = Calendar.getInstance();
+        cal.setTime(startTime);
+        return cal.get(Calendar.YEAR);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelPairSelectState.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelPairSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -48,7 +48,7 @@
     /** Specify to display a datacage_twin_panel. */
     @Override
     protected String getUIProvider() {
-        return "datacage_twin_panel";
+        return "waterlevel_twin_panel";
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java	Fri Jul 13 11:56:22 2018 +0200
@@ -14,7 +14,6 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifactdatabase.state.FacetActivity;
 import org.dive4elements.artifacts.Artifact;
@@ -49,15 +48,11 @@
 /**
  * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public class FixAnalysisCompute
-extends      DefaultState
-implements   FacetTypes
-{
+public class FixAnalysisCompute extends DefaultState implements FacetTypes {
     /** The log used in this class. */
     private static Logger log = Logger.getLogger(FixAnalysisCompute.class);
 
-    private static final String I18N_REFERENCEPERIOD_SHORT =
-        "fix.reference.period.event.short";
+    private static final String I18N_REFERENCEPERIOD_SHORT = "fix.reference.period.event.short";
 
     private static final String I18N_ANALYSISPERIODS = "fix.analysis.periods";
 
@@ -69,84 +64,54 @@
 
     private static final String I18N_DEVIATION = "fix.deviation";
 
-    private static final String I18N_REFERENCEDEVIATION =
-        "fix.reference.deviation";
-
-    private static final String I18N_REFERENCEPERIOD =
-        "state.fix.analysis.referenceperiod";
+    private static final String I18N_REFERENCEDEVIATION = "fix.reference.deviation";
 
-    public static final String [] SECTOR_LABELS = {
-        "fix.mnq",
-        "fix.mq",
-        "fix.mhq",
-        "fix.hq5"
-    };
+    private static final String I18N_REFERENCEPERIOD = "state.fix.analysis.referenceperiod";
+
+    public static final String[] SECTOR_LABELS = { "fix.mnq", "fix.mq", "fix.mhq", "fix.hq5" };
 
     static {
         // Active/deactivate facets.
-        FacetActivity.Registry.getInstance().register(
-            "fixanalysis",
-            new FacetActivity() {
-                @Override
-                public Boolean isInitialActive(
-                    Artifact artifact,
-                    Facet    facet,
-                    String   output
-                ) {
-                    if (
-                        output.contains(FacetTypes.ChartType.FLSC.toString())
-                    ) {
-                        // Longitudinal section chart
-                        String name = facet.getName();
+        FacetActivity.Registry.getInstance().register("fixanalysis", new FacetActivity() {
+            @Override
+            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String output) {
+                if (output.contains(FacetTypes.ChartType.FLSC.toString())) {
+                    // Longitudinal section chart
+                    final String name = facet.getName();
 
-                        if (name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_DWT)
-                         || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_LS)
-                         || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_WQ)
-                         || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_DWT)
-                         || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_LS)
-                         || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_WQ)
-                        ) {
-                            return Boolean.FALSE;
-                        }
-                    }
-                    if (output.contains(FacetTypes.ChartType.FDWC.toString())
-                        && facet.getName().contains(
-                            FacetTypes.FIX_SECTOR_AVERAGE_DWT)) {
+                    if (name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_DWT) || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_LS)
+                            || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_WQ) || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_DWT)
+                            || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_LS) || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_WQ)) {
                         return Boolean.FALSE;
                     }
-
-                    return Boolean.TRUE;
                 }
-            });
+                if (output.contains(FacetTypes.ChartType.FDWC.toString()) && facet.getName().contains(FacetTypes.FIX_SECTOR_AVERAGE_DWT)) {
+                    return Boolean.FALSE;
+                }
+
+                return Boolean.TRUE;
+            }
+        });
     }
 
-
     /**
      * The default constructor that initializes an empty State object.
      */
     public FixAnalysisCompute() {
     }
 
-
     @Override
-    public Object computeAdvance(
-        D4EArtifact artifact,
-        String       hash,
-        CallContext  context,
-        List<Facet>  facets,
-        Object       old
-    ) {
+    public Object computeAdvance(final D4EArtifact artifact, final String hash, final CallContext context, final List<Facet> facets, final Object old) {
         log.debug("FixAnalysisCompute.computeAdvance");
 
         CalculationResult res;
 
-        FixAnalysisAccess access = new FixAnalysisAccess(artifact);
+        final FixAnalysisAccess access = new FixAnalysisAccess(artifact);
 
         if (old instanceof CalculationResult) {
-            res = (CalculationResult)old;
-        }
-        else {
-            FixAnalysisCalculation calc = new FixAnalysisCalculation(access);
+            res = (CalculationResult) old;
+        } else {
+            final FixAnalysisCalculation calc = new FixAnalysisCalculation(access);
             res = calc.calculate();
         }
 
@@ -155,40 +120,35 @@
         }
 
         if (res.getReport().hasProblems()) {
-            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id));
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
         }
 
-        FixAnalysisResult fr = (FixAnalysisResult)res.getData();
+        final FixAnalysisResult fr = (FixAnalysisResult) res.getData();
         if (fr == null) {
             return res;
         }
 
-        facets.add(
-            new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id));
-        facets.add(
-            new DataFacet(
-                FIX_PARAMETERS, "parameters", ComputeType.ADVANCE, hash, id));
-        facets.add(
-            new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id));
+        facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, this.id));
+        facets.add(new DataFacet(FIX_PARAMETERS, "parameters", ComputeType.ADVANCE, hash, this.id));
+        facets.add(new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, this.id));
+        facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, this.id));
 
         int maxId = -100;
 
-        int sectorMask = fr.getUsedSectorsInAnalysisPeriods();
-
-        int qsS = access.getQSectorStart();
-        int qsE = access.getQSectorEnd();
+        final int sectorMask = fr.getUsedSectorsInAnalysisPeriods();
 
-        DateFormat df = Formatter.getDateFormatter(
-            context.getMeta(), "dd.MM.yyyy");
-        DateFormat lf = Formatter.getDateFormatter(
-            context.getMeta(), "dd.MM.yyyy'T'HH:mm");
+        final int qsS = access.getQSectorStart();
+        final int qsE = access.getQSectorEnd();
 
-        DateRange [] periods = access.getAnalysisPeriods();
+        final DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy");
+        final DateFormat lf = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy'T'HH:mm");
+
+        final DateRange[] periods = access.getAnalysisPeriods();
 
         for (int i = 0; i < periods.length; i++) {
-            DateRange period = periods[i];
-            String startDate = df.format(period.getFrom());
-            String endDate   = df.format(period.getTo());
+            final DateRange period = periods[i];
+            final String startDate = df.format(period.getFrom());
+            final String endDate = df.format(period.getTo());
 
             for (int j = qsS; j <= qsE; j++) {
 
@@ -197,14 +157,10 @@
                     continue;
                 }
 
-                String sector = SECTOR_LABELS[j];
-                String description = "\u0394W (" +
-                    Resources.getMsg(context.getMeta(),
-                        sector,
-                        sector) +
-                        ")";
+                final String sector = SECTOR_LABELS[j];
+                final String description = "\u0394W (" + Resources.getMsg(context.getMeta(), sector, sector) + ")";
 
-                int sectorNdx = j - qsS;
+                final int sectorNdx = j - qsS;
                 int facetNdx = i << 2;
                 facetNdx = facetNdx | j;
 
@@ -212,139 +168,75 @@
                     maxId = facetNdx;
                 }
 
+                facets.add(new FixAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_DWT + "_" + sectorNdx, description));
                 facets.add(
-                    new FixAvSectorFacet(
-                        facetNdx,
-                        FIX_SECTOR_AVERAGE_DWT + "_" + sectorNdx,
-                        description));
-                facets.add(
-                    new FixLongitudinalAvSectorFacet(
-                        facetNdx,
-                        FIX_SECTOR_AVERAGE_LS + "_" + sectorNdx,
-                        description + ":" + startDate + " - " + endDate));
+                        new FixLongitudinalAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_LS + "_" + sectorNdx, description + ":" + startDate + " - " + endDate));
                 // TODO: i18n
-                String dev = "Abweichung: " + description;
-                facets.add(
-                    new FixLongitudinalAvSectorFacet(
-                        facetNdx,
-                        FIX_SECTOR_AVERAGE_LS_DEVIATION + "_" + sectorNdx,
-                        dev));
-                facets.add(
-                    new FixAvSectorFacet(
-                        facetNdx,
-                        FIX_SECTOR_AVERAGE_WQ + "_" + sectorNdx,
-                        description));
+                final String dev = "Abweichung: " + description;
+                facets.add(new FixLongitudinalAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_LS_DEVIATION + "_" + sectorNdx, dev));
+                facets.add(new FixAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_WQ + "_" + sectorNdx, description));
 
             }
 
-            String eventDesc =
-                Resources.getMsg(context.getMeta(),
-                                 I18N_ANALYSIS,
-                                 I18N_ANALYSIS);
+            final String eventDesc = Resources.getMsg(context.getMeta(), I18N_ANALYSIS, I18N_ANALYSIS);
 
-            Collection<Date> aeds = fr.getAnalysisEventsDates(i);
-            UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, aeds);
+            final Collection<Date> aeds = fr.getAnalysisEventsDates(i);
+            final UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, aeds);
 
             int k = 0;
-            for (Date d: aeds) {
+            for (final Date d : aeds) {
                 int anaNdx = i << 8;
                 anaNdx = anaNdx | k;
-                facets.add(new FixAnalysisEventsFacet(anaNdx,
-                    FIX_ANALYSIS_EVENTS_DWT,
-                    eventDesc + (i+1) + " - " + cf.format(d)));
-                facets.add(new FixLongitudinalAnalysisFacet(anaNdx,
-                    FIX_ANALYSIS_EVENTS_LS,
-                    eventDesc + (i+1) + " - " + cf.format(d)));
-                facets.add(new FixAnalysisEventsFacet(anaNdx,
-                    FIX_ANALYSIS_EVENTS_WQ,
-                    eventDesc + (i+1) +" - " + cf.format(d)));
+                facets.add(new FixAnalysisEventsFacet(anaNdx, FIX_ANALYSIS_EVENTS_DWT, eventDesc + (i + 1) + " - " + cf.format(d)));
+                facets.add(new FixLongitudinalAnalysisFacet(anaNdx, FIX_ANALYSIS_EVENTS_LS, eventDesc + (i + 1) + " - " + cf.format(d)));
+                facets.add(new FixAnalysisEventsFacet(anaNdx, FIX_ANALYSIS_EVENTS_WQ, eventDesc + (i + 1) + " - " + cf.format(d)));
                 k++;
             }
         }
 
-        IdGenerator idg = new IdGenerator(maxId + 1);
+        final IdGenerator idg = new IdGenerator(maxId + 1);
 
-        String i18n_ref = Resources.getMsg(context.getMeta(),
-                I18N_REFERENCEPERIOD_SHORT,
-                I18N_REFERENCEPERIOD_SHORT);
-        String i18n_dev = Resources.getMsg(context.getMeta(),
-                I18N_REFERENCEDEVIATION,
-                I18N_REFERENCEDEVIATION);
+        final String i18n_ref = Resources.getMsg(context.getMeta(), I18N_REFERENCEPERIOD_SHORT, I18N_REFERENCEPERIOD_SHORT);
+        final String i18n_dev = Resources.getMsg(context.getMeta(), I18N_REFERENCEDEVIATION, I18N_REFERENCEDEVIATION);
 
-        Collection<Date> reds = fr.getReferenceEventsDates();
-        UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, reds);
+        final Collection<Date> reds = fr.getReferenceEventsDates();
+        final UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, reds);
 
         int i = 0;
-        for (Date d: reds) {
+        for (final Date d : reds) {
             int refNdx = idg.next() << 8;
-            refNdx |=  i;
-            facets.add(new FixReferenceEventsFacet(refNdx,
-                FIX_REFERENCE_EVENTS_DWT,
-                i18n_ref + " - " + cf.format(d)));
+            refNdx |= i;
+            facets.add(new FixReferenceEventsFacet(refNdx, FIX_REFERENCE_EVENTS_DWT, i18n_ref + " - " + cf.format(d)));
             refNdx = idg.next() << 8;
             refNdx = refNdx | i;
-            facets.add(new FixLongitudinalReferenceFacet(refNdx,
-                FIX_REFERENCE_EVENTS_LS,
-                i18n_ref + " - " + cf.format(d)));
+            facets.add(new FixLongitudinalReferenceFacet(refNdx, FIX_REFERENCE_EVENTS_LS, i18n_ref + " - " + cf.format(d)));
             refNdx = idg.next() << 8;
             refNdx |= i;
-            facets.add(new FixReferenceEventsFacet(refNdx,
-                FIX_REFERENCE_EVENTS_WQ,
-                i18n_ref + " - " + cf.format(d)));
+            facets.add(new FixReferenceEventsFacet(refNdx, FIX_REFERENCE_EVENTS_WQ, i18n_ref + " - " + cf.format(d)));
             i++;
         }
 
-        facets.add(new FixLongitudinalDeviationFacet(idg.next(),
-            FIX_DEVIATION_LS,
-            i18n_dev));
+        facets.add(new FixLongitudinalDeviationFacet(idg.next(), FIX_DEVIATION_LS, i18n_dev));
 
-        String i18n_ana = Resources.getMsg(context.getMeta(),
-                I18N_ANALYSISPERIODS,
-                I18N_ANALYSISPERIODS);
-        facets.add(new FixAnalysisPeriodsFacet(idg.next(),
-            FIX_ANALYSIS_PERIODS_DWT,
-            i18n_ana));
-        facets.add(new FixAnalysisPeriodsFacet(idg.next(),
-            FIX_ANALYSIS_PERIODS_LS,
-            i18n_ana));
-        facets.add(new FixAnalysisPeriodsFacet(idg.next(),
-            FIX_ANALYSIS_PERIODS_WQ,
-            i18n_ana));
+        final String i18n_ana = Resources.getMsg(context.getMeta(), I18N_ANALYSISPERIODS, I18N_ANALYSISPERIODS);
+        facets.add(new FixAnalysisPeriodsFacet(idg.next(), FIX_ANALYSIS_PERIODS_DWT, i18n_ana));
+        facets.add(new FixAnalysisPeriodsFacet(idg.next(), FIX_ANALYSIS_PERIODS_LS, i18n_ana));
+        facets.add(new FixAnalysisPeriodsFacet(idg.next(), FIX_ANALYSIS_PERIODS_WQ, i18n_ana));
 
-        String i18n_refp = Resources.getMsg(context.getMeta(),
-                I18N_REFERENCEPERIOD,
-                I18N_REFERENCEPERIOD);
-        facets.add(new DataFacet(idg.next(),
-            FIX_REFERENCE_PERIOD_DWT,
-            i18n_refp,
-            ComputeType.ADVANCE, null, null));
+        final String i18n_refp = Resources.getMsg(context.getMeta(), I18N_REFERENCEPERIOD, I18N_REFERENCEPERIOD);
+        facets.add(new DataFacet(idg.next(), FIX_REFERENCE_PERIOD_DWT, i18n_refp, ComputeType.ADVANCE, null, null));
 
         facets.add(new FixWQCurveFacet(idg.next(), "W/Q"));
 
-        Boolean preprocessing = access.getPreprocessing();
+        final Boolean preprocessing = access.getPreprocessing();
 
         if (preprocessing != null && preprocessing) {
-            facets.add(new FixOutlierFacet(
-                idg.next(),
-                FIX_OUTLIER,
-                Resources.getMsg(
-                    context.getMeta(), I18N_OUTLIER, I18N_OUTLIER)));
+            facets.add(new FixOutlierFacet(idg.next(), FIX_OUTLIER, Resources.getMsg(context.getMeta(), I18N_OUTLIER, I18N_OUTLIER)));
         }
 
-        facets.add(new FixDerivateFacet(
-            idg.next(),
-            FIX_DERIVATE_CURVE,
-            Resources.getMsg(
-                context.getMeta(),
-                I18N_DERIVATIVE,
-                I18N_DERIVATIVE)));
+        facets.add(new FixDerivateFacet(idg.next(), FIX_DERIVATE_CURVE, Resources.getMsg(context.getMeta(), I18N_DERIVATIVE, I18N_DERIVATIVE)));
 
-        facets.add(new FixDeviationFacet(
-            idg.next(),
-            FIX_DEVIATION_DWT,
-            Resources.getMsg(context.getMeta(),
-                I18N_DEVIATION,
-                I18N_DEVIATION)));
+        facets.add(new FixDeviationFacet(idg.next(), FIX_DEVIATION_DWT, Resources.getMsg(context.getMeta(), I18N_DEVIATION, I18N_DEVIATION)));
         return res;
     }
 }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixRealizingCompute.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixRealizingCompute.java	Fri Jul 13 11:56:22 2018 +0200
@@ -14,7 +14,6 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.CallMeta;
@@ -58,26 +57,18 @@
     public FixRealizingCompute() {
     }
 
-
     @Override
-    public Object computeAdvance(
-        D4EArtifact artifact,
-        String       hash,
-        CallContext  context,
-        List<Facet>  facets,
-        Object       old
-    ) {
+    public Object computeAdvance(final D4EArtifact artifact, final String hash, final CallContext context, final List<Facet> facets, final Object old) {
         log.debug("FixRealizingCompute.computeAdvance");
 
         CalculationResult res;
 
-        FixRealizingAccess access = new FixRealizingAccess(artifact);
+        final FixRealizingAccess access = new FixRealizingAccess(artifact);
 
         if (old instanceof CalculationResult) {
             res = (CalculationResult) old;
-        }
-        else {
-            FixRealizingCalculation calc = new FixRealizingCalculation(access);
+        } else {
+            final FixRealizingCalculation calc = new FixRealizingCalculation(access);
             res = calc.calculate();
         }
 
@@ -89,11 +80,11 @@
             facets.add(new ReportFacet());
         }
 
-        String   id   = getID();
-        CallMeta meta = context.getMeta();
+        final String id = getID();
+        final CallMeta meta = context.getMeta();
 
-        FixRealizingResult fixRes = (FixRealizingResult) res.getData();
-        WQKms [] wqkms = fixRes != null ? fixRes.getWQKms() : new WQKms[0];
+        final FixRealizingResult fixRes = (FixRealizingResult) res.getData();
+        final WQKms[] wqkms = fixRes != null ? fixRes.getWQKms() : new WQKms[0];
 
         for (int i = 0; i < wqkms.length; i++) {
             String nameW = null;
@@ -102,21 +93,17 @@
             if (access.isQ()) {
                 nameQ = wqkms[i].getName();
                 nameW = "W(" + nameQ + ")";
-            }
-            else {
+            } else {
                 nameW = wqkms[i].getName();
                 nameQ = "Q(" + nameW + ")";
             }
 
-            Facet wq = new FixWaterlevelFacet(
-                i, FIX_WQ_LS, nameW, ComputeType.ADVANCE, hash, id);
+            final Facet wq = new FixWaterlevelFacet(i, FIX_WQ_LS, nameW, ComputeType.ADVANCE, hash, id);
 
-            Facet w = new FixWaterlevelFacet(
-                i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, hash, id);
+            final Facet w = new FixWaterlevelFacet(i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, hash, id);
 
-            Facet q = new FixWaterlevelFacet(
-                i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, hash, id);
-            Facet csFacet = new CrossSectionWaterLineFacet(i, nameW);
+            final Facet q = new FixWaterlevelFacet(i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, hash, id);
+            final Facet csFacet = new CrossSectionWaterLineFacet(i, nameW);
 
             facets.add(wq);
             facets.add(w);
@@ -125,61 +112,42 @@
 
             // XXX: THIS CAN NOT HAPPEN! REMOVE IT!
             if (wqkms[i] instanceof WQCKms) {
-                String nameC = nameW.replace(
-                    "benutzerdefiniert",
-                    "benutzerdefiniert [korrigiert]");
+                final String nameC = nameW.replace("benutzerdefiniert", "benutzerdefiniert [korrigiert]");
 
-                Facet c = new FixWaterlevelFacet(
-                    i, DISCHARGE_LONGITUDINAL_C, nameC);
+                final Facet c = new FixWaterlevelFacet(i, DISCHARGE_LONGITUDINAL_C, nameC);
 
                 facets.add(c);
             }
         }
 
         if (wqkms.length > 0) {
-            DateFormat df = Formatter.getDateFormatter(context.getMeta(),
-                "dd.MM.yyyy");
-            DateFormat lf = Formatter.getDateFormatter(context.getMeta(),
-                "dd.MM.yyyy'T'HH:mm");
+            final DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy");
+            final DateFormat lf = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy'T'HH:mm");
 
-            Collection<Date> reds = fixRes.getReferenceEventsDates();
-            UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, reds);
+            final Collection<Date> reds = fixRes.getReferenceEventsDates();
+            final UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, reds);
 
             int i = 0;
-            for (Date d: reds) {
-                facets.add(new FixReferenceEventsFacet(
-                        (1 << 9) | i,
-                    FIX_EVENTS,
-                    cf.format(d)));
+            for (final Date d : reds) {
+                facets.add(new FixReferenceEventsFacet((1 << 9) | i, FIX_EVENTS, cf.format(d)));
                 i++;
             }
 
-            facets.add(
-                new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id));
+            facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id));
 
-            facets.add(
-                new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id));
+            facets.add(new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id));
 
-            facets.add(
-                new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id));
+            facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id));
         }
 
-        facets.add(
-            new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id));
+        facets.add(new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id));
 
-        facets.add(new FixWQCurveFacet(
-            0,
-            Resources.getMsg(meta, I18N_WQ_CURVE, I18N_WQ_CURVE) + " ("
-                + access.getFunction() + ")"));
+        facets.add(new FixWQCurveFacet(0, Resources.getMsg(meta, I18N_WQ_CURVE, I18N_WQ_CURVE) + " (" + access.getFunction() + ")"));
 
         if (access.getPreprocessing()) {
-            facets.add(new FixOutlierFacet(
-                0,
-                FIX_OUTLIER,
-                Resources.getMsg(meta, I18N_WQ_OUTLIER, I18N_WQ_OUTLIER)));
+            facets.add(new FixOutlierFacet(0, FIX_OUTLIER, Resources.getMsg(meta, I18N_WQ_OUTLIER, I18N_WQ_OUTLIER)));
         }
 
         return res;
     }
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDistanceSelect.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadDistanceSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,12 +10,12 @@
 
 import org.dive4elements.river.artifacts.states.DistanceOnlySelect;
 
-
-public class SedimentLoadDistanceSelect
-extends DistanceOnlySelect
-{
+public class SedimentLoadDistanceSelect extends DistanceOnlySelect {
     @Override
     protected String getUIProvider() {
         return "minfo.sedimentload_distance_select";
     }
+
+    // title müsste distance_state sein; schon in CompuatationRange
+
 }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/YearEpochSelect.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/YearEpochSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,19 +8,18 @@
 
 package org.dive4elements.river.artifacts.states.minfo;
 
-import org.w3c.dom.Element;
-
 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 <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public class YearEpochSelect extends DefaultState {
+public class YearEpochSelect extends DefaultState {// TODO: RadioSelect-class; more flexible Implementation
 
     /**
      * The default constructor that initializes an empty State object.
@@ -34,49 +33,34 @@
     }
 
     @Override
-    protected Element[] createItems(
-        XMLUtils.ElementCreator ec,
-        Artifact                artifact,
-        String                  name,
-        CallContext             context)
-    {
-        CallMeta meta = context.getMeta();
+    protected Element[] createItems(final XMLUtils.ElementCreator ec, final Artifact artifact, final String name, final CallContext context) {
+        final CallMeta meta = context.getMeta();
         Element[] elements;
 
-        /* Disable calculation of official epochs
-        if (((D4EArtifact)artifact).getCurrentStateId()
-            .equals("state.minfo.sediment.load.year_epoch")
-        ) {
-            elements = new Element[3];
-            elements[2] = createItem(
-                ec,
-                new String[] {
-                    Resources.getMsg(meta,
-                        "state.minfo.off_epoch",
-                        "state.minfo.off_epoch"),
-                    "off_epoch"});
-        }
-        else {
-            elements = new Element[2];
-            } */
+        /*
+         * Disable calculation of official epochs
+         * if (((D4EArtifact)artifact).getCurrentStateId()
+         * .equals("state.minfo.sediment.load.year_epoch")
+         * ) {
+         * elements = new Element[3];
+         * elements[2] = createItem(
+         * ec,
+         * new String[] {
+         * Resources.getMsg(meta,
+         * "state.minfo.off_epoch",
+         * "state.minfo.off_epoch"),
+         * "off_epoch"});
+         * }
+         * else {
+         * elements = new Element[2];
+         * }
+         */
         elements = new Element[2];
-        elements[0] = createItem(
-                ec,
-                new String[] {
-                    Resources.getMsg(meta,
-                        "state.minfo.year",
-                        "state.minfo.year"),
-                    "year"});
+        elements[0] = createItem(ec, new String[] { Resources.getMsg(meta, "state.minfo.year", "state.minfo.year"), "year" });
 
-        elements[1] = createItem(
-            ec,
-            new String[] {
-                Resources.getMsg(meta,
-                    "state.minfo.epoch",
-                    "state.minfo.epoch"),
-                "epoch"});
+        elements[1] = createItem(ec, new String[] { Resources.getMsg(meta, "state.minfo.epoch", "state.minfo.epoch"), "epoch" });
 
-       return elements;
+        return elements;
     }
 }
 // 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/uinfo/CalculationSelectUinfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,70 @@
+/* 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.uinfo;
+
+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.dive4elements.river.artifacts.uinfo.inundationduration.UedauernPropertiesHelper;
+import org.w3c.dom.Element;
+
+/**
+ * @author Gernot Belger
+ */
+public class CalculationSelectUinfo extends DefaultState {
+
+    private static final long serialVersionUID = 1L;
+
+    /** The log that is used in this class. */
+    private static Logger log = Logger.getLogger(CalculationSelectUinfo.class);
+
+    @Override
+    protected Element[] createItems(final XMLUtils.ElementCreator cr, final Artifact artifact, final String name, final CallContext context) {
+        final CallMeta meta = context.getMeta();
+
+        final Collection<Element> calcs = new ArrayList<>(UinfoCalcMode.values().length);
+
+        for (final UinfoCalcMode calcMode : UinfoCalcMode.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(final Artifact artifact) throws IllegalArgumentException {
+        log.debug("CalculationSelect.validate");
+        /* throws an exception if calculation mode is invalid */
+
+        final UINFOArtifact uinfo = (UINFOArtifact) artifact;
+        final String calcmode = uinfo.getCalculationMode().toString(); // "toString()" is important
+        if (calcmode.equals("uinfo_inundation_duration")) {
+
+            final String river = uinfo.getRiver();
+            if (!UedauernPropertiesHelper.fileExistsForRiver(river)) {
+                throw new IllegalArgumentException("error_no_data_for_river");
+            }
+        }
+
+        return true;
+    }
+}
\ 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/uinfo/UINFOArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.uinfo;
+
+import org.apache.commons.lang.StringUtils;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.river.artifacts.D4EArtifact;
+
+/**
+ * The default UINFO artifact.
+ *
+ * @author Gernot Belger
+ */
+public class UINFOArtifact extends D4EArtifact {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 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 = "uinfo";
+
+    private static final String FIELD_RIVER = "river";
+
+    private static final String FIELD_MODE = "calculation_mode";
+
+    static {
+        // Active/deactivate facets.
+        // BEWARE: we can only define one activity for "sinfo", so we use the artifact
+        // as place for this
+        FacetActivity.Registry.getInstance().register(ARTIFACT_NAME, new FacetActivity() {
+            @Override
+            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String output) {
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Default constructor, because it's serializable.
+     */
+    public UINFOArtifact() {
+    }
+
+    /**
+     * Returns the name of the concrete artifact.
+     *
+     * @return the name of the concrete artifact.
+     */
+    @Override
+    public String getName() {
+        return ARTIFACT_NAME;
+    }
+
+    public UinfoCalcMode getCalculationMode() {
+
+        final String calc = getDataAsString(FIELD_MODE);
+        if (calc == null) {
+            throw new IllegalArgumentException(ERROR_NO_CALCULATION_MODE);
+        }
+
+        try {
+            return UinfoCalcMode.valueOf(StringUtils.trimToEmpty(calc).toLowerCase());
+        }
+        catch (final Exception e) {
+            throw new IllegalArgumentException(ERROR_INVALID_CALCULATION_MODE, e);
+        }
+    }
+
+    public String getRiver() {
+        return getDataAsString(FIELD_RIVER);
+    }
+}
\ 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/uinfo/UinfoCalcMode.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,17 @@
+/* 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.uinfo;
+
+public enum UinfoCalcMode{
+	uinfo_salix_line,
+	uinfo_inundation_duration,
+	uinfo_vegetation_zones
+}
\ 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/uinfo/commons/UInfoResultType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,188 @@
+/** 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.uinfo.commons;
+
+import java.text.NumberFormat;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.AbstractResultType;
+import org.dive4elements.river.utils.Formatter;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class UInfoResultType extends AbstractResultType {
+
+    private static final long serialVersionUID = 1L;
+
+    public UInfoResultType(final String unit, final String csvHeader) {
+        super(unit, csvHeader, csvHeader);
+
+    }
+
+    @Override
+    public String exportValue(final CallContext context, final Object value) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    protected NumberFormat createFormatter(final CallContext context) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static final UInfoResultType customMultiRowColSalixRegionalValue_Dwspl = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.scenario") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final UInfoResultType salix_line_scenario = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.scenario") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of
+            // digits.
+            return Formatter.getSalixLine(context);
+        }
+    };
+
+    public static final UInfoResultType salix_line_scenario_dwspl = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.scenario_dwspl") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final String valueStr = String.valueOf(value);
+            return exportStringValue(valueStr);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+
+            return Formatter.getIntegerFormatter(context);
+        }
+    };
+    public static final UInfoResultType salix_delta_mw = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.delta_mw") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of
+            // digits.
+            return Formatter.getSalixLine(context);
+        }
+    };
+
+    public static final UInfoResultType salixline = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.salix_line") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of
+            // digits.
+            return Formatter.getSalixLine(context);
+        }
+    };
+
+    public static final UInfoResultType salixlinehist = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.hist") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of
+            // digits.
+            return Formatter.getSalixLine(context);
+        }
+    };
+
+    public static final UInfoResultType vegname = new UInfoResultType(null, "uinfo.export.csv.meta.header.veg.name") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            return exportStringValue(value);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    public static final UInfoResultType vegdauervon = new UInfoResultType(null, "uinfo.export.csv.meta.header.veg.dauervon") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of
+            // digits.
+            return Formatter.getUeberflutungsdauer(context);
+        }
+    };
+
+    public static final UInfoResultType vegdauerbis = new UInfoResultType(null, "uinfo.export.csv.meta.header.veg.dauerbis") {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of
+            // digits.
+            return Formatter.getUeberflutungsdauer(context);
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/inundationduration/InundationDurationAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,108 @@
+/* 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.uinfo.inundationduration;
+
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.common.EpochYearAccessHelper;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.UinfoCalcMode;
+
+/**
+ * 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
+ */
+final class InundationDurationAccess extends RangeAccess {
+
+    // IMMER ABGLEICHEN MIT SuperVegZonesTablePanel.TABLE_CELL_SEPARATOR
+    public static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR";
+    public static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR";
+
+    private final EpochYearAccessHelper helper;
+
+    // Fields from state:
+    //
+    // calculation_mode (String)
+    // ld_from, ld_to
+    // ye_select (String; state.uinfo.totalepoch oder state.uinfo.year)
+    // singleyear (String)
+    // totalepoch (String; TODO: minmax totalEpoch herausfinden und setzen (nicht hier.. aber trotzdem die Erinnerung hier))
+    // use_scenario boolean (danach kommt kein radioBtn, sondern sedimentheight-Eingabe)
+    // sedimentheight String
+    //
+    // vegzones (String) TODO: MIT VegetationzonesAccess zusammenlegen
+
+    public InundationDurationAccess(final UINFOArtifact uinfo) {
+        super(uinfo);
+        /* assert calculation mode */
+        final UinfoCalcMode calculationMode = uinfo.getCalculationMode();
+        this.helper = new EpochYearAccessHelper(uinfo);
+        assert (calculationMode == UinfoCalcMode.uinfo_inundation_duration);
+    }
+
+    public Integer getYear() {
+        final int[] years = this.helper.getYears("state.uinfo.year", "singleyear");
+        if (years != null) {
+            return years[0];
+        }
+        return null;
+    }
+
+    public String getWMSUrl() {
+
+        final UedauernPropertiesHelper helper = UedauernPropertiesHelper.getInstance(getRiverName());
+        if (this.getYear() != null) {
+            return helper.urlFromYear(this.getYear());
+        } else {
+            return helper.getMittelUrl(); // nur 2 cases...
+        }
+
+    }
+
+    public String getWMSScenarioUrl() {
+        if (getIsUseScenario()) {
+            final UedauernPropertiesHelper helper = UedauernPropertiesHelper.getInstance(getRiverName());
+            if (this.getYear() != null) {
+                return helper.getScenarioUrlFromYear(this.getYear(), this.getDwspl());
+            } else {
+                return helper.getMittelScenarioUrl(this.getDwspl()); // nur 2 cases...
+            }
+        }
+        return "";
+    }
+
+    public Integer getDwspl() {
+        if (getIsUseScenario()) {
+            return super.getInteger("sedimentheight");
+        }
+        return null;
+    }
+
+    public String getVegZones() {
+        // mit VegetationzonesAccess zusammenlegen (eine Zeile sparen...)
+        return super.getString("vegzones");
+    }
+
+    public boolean getIsUseScenario() {
+        return super.getBoolean("use_scenario");
+    }
+
+    public Integer[] mittelStartEndYears() {
+        if (getIsUseScenario()) {
+            final UedauernPropertiesHelper helper = UedauernPropertiesHelper.getInstance(getRiverName());
+            return helper.getMittelStartEnd();
+        }
+        return null;
+    }
+}
\ 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/uinfo/inundationduration/InundationDurationCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,81 @@
+/** 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.uinfo.inundationduration;
+
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZone;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+final class InundationDurationCalculation {
+
+    private final CallContext context;
+
+    public InundationDurationCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final UINFOArtifact uinfo) {
+        final Calculation problems = new Calculation();
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name());
+        final String user = CalculationUtils.findArtifactUser(this.context, uinfo);
+
+        final RiverAccess access = new RiverAccess(uinfo);
+
+        final InundationDurationAccess indurax = new InundationDurationAccess(uinfo);
+        final River river = indurax.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+        final DoubleRange calcRange = indurax.getRange();
+        final String url = indurax.getWMSUrl();
+        final Integer year = indurax.getYear(); // null bei year -> Integer
+        final String zonesRaw = indurax.getVegZones();
+        final List<VegetationZone> zones = VegetationZone.parse(zonesRaw);
+        final String scenarioUrl = indurax.getWMSScenarioUrl();
+        final String scenarioStr = String.valueOf(indurax.getDwspl());
+
+        // TODO: add vegetationzone-values as parameter to url and use this url as veg'zone'url
+
+        final boolean isUseScenario = indurax.getIsUseScenario();
+        final Integer[] mittelStartEndYears = indurax.mittelStartEndYears();
+        final InundationDurationCalculationResult result = new InundationDurationCalculationResult();
+
+        final String rangeDuration = year != null ? String.valueOf(year)
+                : new StringBuilder().append(String.valueOf(mittelStartEndYears[0])).append("-").append(mittelStartEndYears[1]).toString();
+
+        result.addLayer(Resources.getMsg(this.context.getMeta(), "uinfo.export.url.inundationduration.inundationduration", new Object[] { rangeDuration }), url,
+                true);
+        // TODO: add vegetationzone-values as parameter to url and use this url as veg'zone'url
+        result.addLayer(Resources.getMsg(this.context.getMeta(), "uinfo.export.url.inundationduration.vegetation", new Object[] { rangeDuration }), url, false);
+        if (isUseScenario) {
+            result.addLayer(
+                    Resources.getMsg(this.context.getMeta(), "uinfo.export.url.inundationduration.scenario", new Object[] { rangeDuration, scenarioStr }),
+                    scenarioUrl, true);
+            // TODO: add vegetationzone-values as parameter to url and use this url as veg'zone'url
+            result.addLayer(Resources.getMsg(this.context.getMeta(), "uinfo.export.url.inundationduration.vegetation_scenario",
+                    new Object[] { rangeDuration, scenarioStr }), scenarioUrl, false);
+        }
+
+        return new CalculationResult(result, problems);
+    }
+}
\ 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/uinfo/inundationduration/InundationDurationCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,56 @@
+/** 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.uinfo.inundationduration;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+final class InundationDurationCalculationResult implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final List<WmsLayer> layers = new ArrayList<>();
+
+    public final static class WmsLayer {
+        private final String label;
+        private final String url;
+        private final boolean showLayerLink;
+
+        public WmsLayer(final String label, final String url, final boolean showLayerLink) {
+            this.label = label;
+            this.url = url;
+            this.showLayerLink = showLayerLink;
+        }
+
+        public String getLabel() {
+            return this.label;
+        }
+
+        public String getUrl() {
+            return this.url;
+        }
+
+        public boolean isShowLayerLink() {
+            return this.showLayerLink;
+        }
+    }
+
+    public void addLayer(final String label, final String url, final boolean showLayerLink) {
+        this.layers.add(new WmsLayer(label, url, showLayerLink));
+    }
+
+    public List<WmsLayer> getLayers() {
+        return this.layers;
+    }
+}
\ 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/uinfo/inundationduration/InundationDurationState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,128 @@
+/** 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.uinfo.inundationduration;
+
+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.MapArtifact.MapState;
+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.ReportFacet;
+import org.dive4elements.river.artifacts.model.map.WMSLayerFacet;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.inundationduration.InundationDurationCalculationResult.WmsLayer;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class InundationDurationState extends MapState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FlowDepthState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String LABEL_URL_SEPARATOR = ";";// always sync with client (ExportPanel)
+
+    /**
+     * 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((UINFOArtifact) artifact, context, ComputeType.FEED, 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;
+        }
+
+        if (facets != null)
+            super.computeAdvance(artifact, hash, context, facets, old);
+
+        return compute((UINFOArtifact) artifact, context, ComputeType.ADVANCE, hash, facets, old);
+
+    }
+
+    /**
+     * Compute result or returned object from cache, create facets.
+     *
+     * @param old
+     *            Object that was cached.
+     */
+    private Object compute(final UINFOArtifact sinfo, final CallContext context, final ComputeType type, final String hash, final List<Facet> facets,
+            final Object old) {
+
+        final CalculationResult res = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+
+        final InundationDurationCalculationResult result = (InundationDurationCalculationResult) res.getData();
+        final List<WmsLayer> layers = result.getLayers();
+
+        int index = 1; // 1 because super.computeAdvance adds the river theme with index 0
+        for (final WmsLayer layer : layers) {
+
+            final String label = layer.getLabel();
+            final String url = layer.getUrl();
+
+            final WMSLayerFacet wmsFacet = new WMSLayerFacet(index, FLOODMAP_EXTERNAL_WMS_INUNDATIONDUR + index, label, type, getID(), hash, url);
+            facets.add(wmsFacet);
+
+            wmsFacet.addLayer("OSM-WMS-Dienst");
+
+            // wmsFacet.setExtent(getExtent(false));
+            // wmsFacet.setOriginalExtent(getExtent(true));
+            wmsFacet.setSrid(getSrid());
+
+            if (layer.isShowLayerLink())
+                facets.add(new DataFacet("wms_url", label + LABEL_URL_SEPARATOR + url, ComputeType.ADVANCE, hash, this.id));
+
+            index++; // because super.computeAdvance adds the river theme with index 0
+        }
+
+        // tODO: create layer links: filter by "showLayerLink"
+
+        // tODO: create layer links: filter by "showLayerLink"
+
+        final Calculation report = res.getReport();
+        if (report.hasProblems())
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final UINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new InundationDurationCalculation(context).calculate(sinfo);
+    }
+}
\ 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/uinfo/inundationduration/LoadScenarioSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,72 @@
+/* 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.uinfo.inundationduration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.states.AddTableDataHelper;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.w3c.dom.Element;
+
+/** State in which to fetch years for sedminent load calculation. */
+public class LoadScenarioSelect extends DefaultState {
+    private static final long serialVersionUID = 1L;
+    /** The log used in this class. */
+    private static Logger log = Logger.getLogger(LoadScenarioSelect.class);
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadScenarioSelect() {
+    }
+
+    /** Year Select Widget. */
+    @Override
+    protected String getUIProvider() {
+        return "uinfo.sedimentheight_select";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+        final String datakey = "sedimentheight";
+        try {
+            if (datakey.equals(name)) {
+
+                final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "cm", context.getMeta());
+
+                helper.addColumn(0, "pinfrom", "40", "common.client.ui.from", "ICON", "CENTER", "from");
+                // helper.addColumn(1, "pinto", "40", "common.client.ui.to", "ICON", "CENTER", "to");
+                helper.addColumn(1, "cm", "60", "Delta [cm]", "INTEGER", "RIGHT", null);
+
+                for (int i = -200; i < 210; i = i + 10) {
+                    final Map<String, String> row = new HashMap<>();
+                    row.put("cm", Integer.toString(i));
+                    helper.addRow(row);
+
+                }
+                helper.submitMapToXml();
+            }
+        }
+        catch (final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+
+    @Override
+    public boolean validate(final Artifact artifact) throws IllegalArgumentException {
+        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/uinfo/inundationduration/LoadSingleYearSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,65 @@
+/* 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.uinfo.inundationduration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.states.AddTableDataHelper;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.w3c.dom.Element;
+
+/** State in which to fetch years for sedminent load calculation. */
+public class LoadSingleYearSelectState extends DefaultState {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadSingleYearSelectState() {
+    }
+
+    /** Year Select Widget. */
+    @Override
+    protected String getUIProvider() {
+        return "common.state.load_single_year_select";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+        final String dataKey = "singleyear";
+        try {
+            if (dataKey.equals(name)) {
+                final InundationDurationAccess access = new InundationDurationAccess((UINFOArtifact) artifact);
+                final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta()); // pinKeycolum; nicht zu verweschseln mit
+                // datakey..artifact.
+
+                helper.addColumn(0, "pinfrom", "60", "common.client.ui.selection", "ICON", "CENTER", "from");
+                helper.addColumn(1, "year", "60", "year", "INTEGER", "LEFT", null);
+                final UedauernPropertiesHelper properties = UedauernPropertiesHelper.getInstance(access.getRiverName());
+
+                for (final String year : properties.getEinzeljahre()) {
+                    final Map<String, String> row = new HashMap<>();
+                    row.put("year", year);
+                    helper.addRow(row);
+
+                }
+                helper.submitMapToXml();
+            }
+        }
+        catch (final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+
+}
\ 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/uinfo/inundationduration/UedauernPropertiesHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,150 @@
+/** 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.uinfo.inundationduration;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.common.utils.Config;
+import org.dive4elements.river.artifacts.resources.Resources;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class UedauernPropertiesHelper {
+
+    private static UedauernPropertiesHelper instance;
+    private final String CONFIG_FILE;
+    private final String rivername;
+    private Integer[] mittelStartEnde = null;
+    private String[] einzeljahre = null;
+    private String mittelUrl = null;
+    private Properties properties = null;
+
+    public UedauernPropertiesHelper(final String rivername) {
+        this.rivername = rivername;
+        this.CONFIG_FILE = makeFileName(rivername);
+    }
+
+    public static synchronized UedauernPropertiesHelper getInstance(final String rivername) {
+        if (UedauernPropertiesHelper.instance == null || !UedauernPropertiesHelper.instance.getRivername().equals(rivername)) {
+
+            UedauernPropertiesHelper.instance = new UedauernPropertiesHelper(rivername);
+        }
+        return UedauernPropertiesHelper.instance;
+    }
+
+    private String getRivername() {
+        return this.rivername;
+    }
+
+    private static final String makeFileName(final String river) {
+        return "uinfo_uedauern_aue_" + river + ".properties";
+    }
+
+    public LinkedHashMap<String, String> getExtraLayers(final CallMeta meta) {
+        final LinkedHashMap<String, String> entries = new LinkedHashMap<>();
+
+        final Integer[] totalEpoch = getMittelStartEnd();
+        final Object[] args = new Object[] { String.valueOf(totalEpoch[0]), String.valueOf(totalEpoch[1]) };
+
+        entries.put("state.uinfo.totalepoch", Resources.getMsg(meta, "state.uinfo.totalepoch", args)); //
+        // String.valueOf: avoid formatting
+        // (3.333,00
+
+        return entries;
+    }
+
+    private Properties getProperties() {
+        if (this.properties == null) {
+            try {
+                this.properties = Config.loadProperties(this.CONFIG_FILE);
+            }
+            catch (final IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return this.properties;
+    }
+
+    final Integer[] getMittelStartEnd() {
+        if (this.mittelStartEnde == null) {
+            final Integer mittel_start = Integer.valueOf(getProperties().get("mittel_start").toString());
+            final Integer mittel_ende = Integer.valueOf(getProperties().get("mittel_ende").toString());
+            this.mittelStartEnde = new Integer[] { mittel_start, mittel_ende }; // lazy
+
+        }
+        return this.mittelStartEnde;
+    }
+
+    public String[] getEinzeljahre() {
+        if (this.einzeljahre == null) { // lazy
+            final Object years = getProperties().get("jahre");
+            if (years != null) {
+                this.einzeljahre = years.toString().split(",");
+            }
+        }
+        return this.einzeljahre;
+    }
+
+    public final String getMittelUrl() {
+        if (this.mittelUrl == null) { // lazy
+            this.mittelUrl = getProperties().get("mittel_url").toString();
+        }
+        return this.mittelUrl;
+    }
+
+    public final String urlFromYear(final int year) {
+        // besser kein lazy-loading, da der user nochmal zurück gehen und das Jahr ändern könnte...
+        final String templateUrl = getProperties().get("url").toString();
+        final Map<String, String> tokens = new HashMap<>();
+        tokens.put("jahr", String.valueOf(year));
+        final StrSubstitutor subst = new StrSubstitutor(tokens);
+        final String yearUrl = subst.replace(templateUrl);
+        return yearUrl;
+    }
+
+    public static boolean fileExistsForRiver(final String river) {
+        try {
+            Config.loadProperties(makeFileName(river));
+            return true;
+        }
+        catch (final IOException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public String getScenarioUrlFromYear(final Integer year, final Integer dMwspl) {
+        // besser kein lazy-loading, da der user nochmal zurück gehen und das Jahr ändern könnte...
+        final String templateUrl = getProperties().get("scenario_url").toString();
+        final Map<String, String> tokens = new HashMap<>();
+        tokens.put("jahr", String.valueOf(year));
+        tokens.put("scenario", String.valueOf(dMwspl));
+        final StrSubstitutor subst = new StrSubstitutor(tokens);
+        final String yearUrl = subst.replace(templateUrl);
+        return yearUrl;
+    }
+
+    public String getMittelScenarioUrl(final Integer dMwspl) {
+        final Map<String, String> tokens = new HashMap<>();
+        tokens.put("scenario", String.valueOf(dMwspl));
+        final String templateUrl = getProperties().get("mittel_scenario_url").toString();
+        final StrSubstitutor subst = new StrSubstitutor(tokens);
+        final String url = subst.replace(templateUrl);
+        return url;
+    }
+}
\ 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/uinfo/inundationduration/YearChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,39 @@
+/* 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.uinfo.inundationduration;
+
+import java.util.LinkedHashMap;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.states.RadioSelect;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class YearChoice extends RadioSelect {
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected LinkedHashMap<String, String> makeEntries(final CallMeta meta, final Artifact artifact) {
+        // in helper-klasse; dann hier label lazy loaden
+        final LinkedHashMap<String, String> entries = new LinkedHashMap<>();
+        if (artifact != null) {// necessary; otherwise crashes randomly when reloading old calculations
+            final InundationDurationAccess access = new InundationDurationAccess((UINFOArtifact) artifact);
+
+            final UedauernPropertiesHelper helper = UedauernPropertiesHelper.getInstance(access.getRiverName());
+            final LinkedHashMap<String, String> extras = helper.getExtraLayers(meta);
+            entries.put("state.uinfo.year", null);
+            entries.putAll(extras);
+        }
+        return entries;
+    }
+
+}
\ 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/uinfo/salix/DistanceOnlyPartHistoricalSelect.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,188 @@
+/* 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.uinfo.salix;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.states.AddTableDataHelper;
+import org.dive4elements.river.artifacts.states.DistanceOnlySelect;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.utils.Formatter;
+import org.w3c.dom.Element;
+
+public class DistanceOnlyPartHistoricalSelect extends DistanceOnlySelect {
+
+    private static final long serialVersionUID = 1L;
+    private static Logger log = Logger.getLogger(DistanceOnlyPartHistoricalSelect.class);
+
+    List<BedHeight> bhs = null;
+    Integer epoch = null;
+    Integer year = null;
+    Double lowerKm = null;
+    Double upperKm = null;
+    River river = null;
+
+    @Override
+    protected String getUIProvider() {
+        return "distance_only_part_historical_panel";
+    }
+
+    @Override
+    protected String getTitle(final CallContext context) {
+        // REMARK: that is how it should be: return Resources.getMsg(context.getMeta(), getID());
+        return Resources.getMsg(context.getMeta(), "state.title.distance_part_state");
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+        final String datakey = "bedheights_for_part";
+
+        try {
+            if (datakey.equals(name)) {
+                makeDataSourceYearEpoch(artifact, creator, select, context, getBedheights(artifact)); // ist nur n test
+            } else if (name.equals("ld_from_part")) {
+
+                final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact);
+                final double lowerSoundings = this.getLowerUpperKmRange(getBedheights(artifact))[0];
+                final double lowerKm = access.getLowerKm() > lowerSoundings ? access.getLowerKm() : lowerSoundings;
+
+                creator.addAttr(select, "type", "options", true);
+
+                final Element item = creator.create("item");
+                creator.addAttr(item, "label", "from_test", true);
+                creator.addAttr(item, "value", String.valueOf(lowerKm), true);
+
+                select.appendChild(item);
+            }
+
+            else if (name.equals("ld_to_part")) {
+                final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact);
+                final double upperSoundings = this.getLowerUpperKmRange(getBedheights(artifact))[1];
+                final double upperKm = access.getUpperKm() < upperSoundings ? access.getUpperKm() : upperSoundings;
+
+                creator.addAttr(select, "type", "options", true);
+
+                final Element item = creator.create("item");
+                creator.addAttr(item, "label", "to_test", true);
+                creator.addAttr(item, "value", String.valueOf(upperKm), true);
+
+                select.appendChild(item);
+
+            }
+        }
+        catch (
+
+        final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+
+    private List<BedHeight> getBedheights(final Artifact artifact) {
+
+        final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact); // improved lazy-loading
+        final Integer year = access.getYear();
+        final Integer epoch = access.getEpoch();
+        final River river = access.getRiver(); // comparable? workflow does not allow return and change anyway...
+        final Double lower = access.getLowerKm();
+        final Double upper = access.getUpperKm();
+        if (!(this.year == year && this.epoch == epoch && this.river == river && this.lowerKm == lower && this.upperKm == upper)) {
+            this.bhs = null;
+        }
+        if (this.bhs == null) {
+            final boolean isEpoch = epoch == null ? false : true;
+            this.bhs = BedHeight.getBedHeightYearEpoch(isEpoch, isEpoch ? epoch : year, river, lower, upper);
+            this.year = year;
+            this.epoch = epoch;
+            this.river = river;
+            this.lowerKm = lower;
+            this.upperKm = upper;
+        }
+        return this.bhs;
+
+    }
+
+    private static final void makeDataSourceYearEpoch(final Artifact artifact, final ElementCreator creator, final Element select, final CallContext context,
+            final List<BedHeight> bedheights) {
+
+        final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta());
+
+        // TODO: probably aggregating results, no sound-row, output as single row
+
+        int year = 0; // hässlich, aber kommt vermutlich eh bald weg
+        if (bedheights != null && bedheights.size() > 0)
+            year = bedheights.get(0).getYear(); // das jahr/epoche ist immer dasselbe
+
+        helper.addColumn(0, "year", "60", "year", "INTEGER", "LEFT", null);
+        helper.addColumn(1, "range", "130", "state.uinfo.salix.historical.km_range_part", "STRING", "LEFT", null);
+        helper.addColumn(2, "description", "500", "uinfo.salix.sounding", "STRING", "LEFT", null);
+
+        final TreeMap<String, String> bedHeightSorted = new TreeMap<>();
+        final double min = Double.MAX_VALUE;
+        final double max = -Double.MAX_VALUE;
+        final java.text.NumberFormat formatter = Formatter.getCalculationKm(context.getMeta());
+
+        for (final BedHeight bh : bedheights) {
+            final org.dive4elements.river.model.Range range = BedHeight.getRangeFromBedHeights(bh);
+            final Double from = range.getA().doubleValue(); // NullPointer check??
+            final Double to = range.getB().doubleValue();
+
+            bedHeightSorted.put(bh.getDescription(), formatter.format(from) + " - " + formatter.format(to));
+        }
+        final Iterator<String> iterator = bedHeightSorted.keySet().iterator();
+        while (iterator.hasNext()) {
+            final String descr = iterator.next();
+            final String fromTo = bedHeightSorted.get(descr);
+            final Map<String, String> row = new HashMap<>();
+            row.put("year", String.valueOf(year));
+            row.put("range", fromTo);
+            row.put("description", descr);
+            helper.addRow(row);
+        }
+
+        helper.submitMapToXml();
+    }
+
+    private double[] getLowerUpperKmRange(final List<BedHeight> bedheights) {
+        double min = Double.MAX_VALUE;
+        double max = -Double.MAX_VALUE;
+
+        for (final BedHeight bh : bedheights) {
+            final org.dive4elements.river.model.Range range = BedHeight.getRangeFromBedHeights(bh);
+            try {
+                final Double from = range.getA().doubleValue(); // NullPointer check?? -> try catch
+                final Double to = range.getB().doubleValue();
+
+                final double upper = to > from ? to : from;
+                final double lower = from < to ? from : to;
+                if (upper > max)
+                    max = upper;
+
+                if (lower < min)
+                    min = lower;
+            }
+            catch (final Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+        return new double[] { min, max };
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadScenarioSelectLimit5.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,67 @@
+/* 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.uinfo.salix;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.states.AddTableDataHelper;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.w3c.dom.Element;
+
+/** State in which to fetch years for sedminent load calculation. */
+public class LoadScenarioSelectLimit5 extends DefaultState {
+    private static final long serialVersionUID = 1L;
+    /** The log used in this class. */
+    private static Logger log = Logger.getLogger(LoadScenarioSelectLimit5.class);
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadScenarioSelectLimit5() {
+    }
+
+    /** Year Select Widget. */
+    @Override
+    protected String getUIProvider() {
+        return "uinfo.sedimentheight_select.limit5";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+        final String datakey = "sedimentheight";
+
+        try {
+            if (datakey.equals(name)) {
+
+                final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "cm", context.getMeta());
+                for (int i = -200; i < 210; i = i + 10) {
+                    final Map<String, String> row = new HashMap<>();
+                    row.put("cm", Integer.toString(i));
+                    helper.addRow(row);
+                }
+                helper.submitMapToXml();
+            }
+        }
+        catch (final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+
+    @Override
+    public boolean validate(final Artifact artifact) throws IllegalArgumentException {
+        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/uinfo/salix/LoadSingleEpochSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,90 @@
+/* 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.uinfo.salix;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.states.AddTableDataHelper;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.model.BedHeight;
+import org.w3c.dom.Element;
+
+public class LoadSingleEpochSelectState extends DefaultState {
+    private static final long serialVersionUID = 1L;
+    /** The log used in this class. */
+    private static Logger log = Logger.getLogger(LoadSingleEpochSelectState.class);
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadSingleEpochSelectState() {
+    }
+
+    @Override
+    protected String getUIProvider() {
+        return "uinfo.salix.load_single_year_pseudo_epoch_select";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+        final String datakey = "singleepoch";
+
+        try {
+            if (datakey.equals(name)) {
+                final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact);
+                final List<BedHeight> bhs = BedHeight.getBedHeightEpochs(access.getRiver(), access.getLowerKm(), access.getUpperKm());
+                makeDataSourceYearEpoch(artifact, creator, select, context, bhs);
+            }
+        }
+        catch (
+
+        final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+    }
+
+    public static final void makeDataSourceYearEpoch(final Artifact artifact, final ElementCreator creator, final Element select, final CallContext context,
+            final List<BedHeight> bedheights) { // TODO: maybe move to appropriate helper...
+
+        final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta());
+
+        helper.addColumn(0, "pinfrom", "40", "common.client.ui.from", "ICON", "CENTER", "from");
+        helper.addColumn(1, "year", "60", "year", "INTEGER", "LEFT", null);
+        helper.addColumn(2, "sounding", "500", "uinfo.salix.soundings", "STRING", "LEFT", null);
+
+        final TreeMap<Integer, String> bedHeightSorted = new TreeMap<>();
+
+        for (final BedHeight bh : bedheights) {
+            final int year = bh.getYear();
+            final String soundings = bedHeightSorted.containsKey(year) ? bedHeightSorted.get(year) + ", " : "";
+            bedHeightSorted.put(year, soundings + bh.getDescription());
+        }
+        final Iterator<Integer> iterator = bedHeightSorted.keySet().iterator();
+        while (iterator.hasNext()) {
+            final int year = iterator.next();
+            final String soundings = bedHeightSorted.get(year);
+            final Map<String, String> row = new HashMap<>();
+            row.put("year", String.valueOf(year));
+            row.put("sounding", soundings);
+            helper.addRow(row);
+        }
+
+        helper.submitMapToXml();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadSingleYearSelectState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,59 @@
+/* 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.uinfo.salix;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.model.BedHeight;
+import org.w3c.dom.Element;
+
+/** State in which to fetch years for sedminent load calculation. */
+public class LoadSingleYearSelectState extends DefaultState {
+    private static final long serialVersionUID = 1L;
+    /** The log used in this class. */
+    private static Logger log = Logger.getLogger(LoadSingleYearSelectState.class);
+
+    /**
+     * The default constructor that initializes an empty State object.
+     */
+    public LoadSingleYearSelectState() {
+    }
+
+    /** Year Select Widget. */
+    @Override
+    protected String getUIProvider() {
+        return "common.state.load_single_year_select";
+    }
+
+    @Override
+    protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) {
+
+        final String dataKeyofState = "singleyear";// siehe .xml
+        try {
+            if (dataKeyofState.equals(name)) {
+                final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact);
+                final List<BedHeight> bhs = BedHeight.getBedHeightYear(access.getRiver(), access.getLowerKm(), access.getUpperKm());
+                LoadSingleEpochSelectState.makeDataSourceYearEpoch(artifact, creator, select, context, bhs);
+            }
+        }
+        catch (
+
+        final IllegalArgumentException iae) {
+            iae.printStackTrace();
+        }
+
+    }
+}
+// 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/uinfo/salix/SalixLineAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,93 @@
+/* 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.uinfo.salix;
+
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.UinfoCalcMode;
+
+/**
+ * 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
+ */
+final class SalixLineAccess extends RangeAccess {
+
+    static final String FIELD_DIFFID_CURRENT = "diffid_current";
+    static final String FIELD_DIFFID_HIST = "diffid_historical";
+    // calculation_mode
+    // ld_from , ld_to
+    // use_scenario (boolean)
+    // ld_from_part; ld_to_part
+    // scenario_selection (mögliche Werte:"scenarioType.option1" "scenarioType.option2" "scenarioType.option3"
+
+    public SalixLineAccess(final UINFOArtifact artifact) {
+        super(artifact);
+
+        /* assert calculation mode */
+        final UinfoCalcMode calculationMode = artifact.getCalculationMode();
+        assert (calculationMode == UinfoCalcMode.uinfo_salix_line);
+    }
+
+    public boolean getUseScenario() {
+        return super.getBoolean("use_scenario");
+    }
+
+    public String getScenario() {
+        if (getUseScenario()) {
+            return getString("scenario_selection");
+        }
+        return null;
+    }
+
+    public Double getFromPart() {
+        return getDouble("ld_from_part");
+    }
+
+    public Double getToPart() {
+        return getDouble("ld_to_part");
+    }
+
+    public int[] getRegionalScenarioIntegers() {
+        // super.getIntArray("sedimentheight"); DOES NOT WORK!
+        final String ints = super.getString("sedimentheight");
+        if (ints != null) {
+            final String[] intsSplit = ints.split(" ");
+            final int[] values = new int[intsSplit.length];
+            for (int i = 0; i < intsSplit.length; i++) {
+                values[i] = Integer.valueOf(intsSplit[i]);
+            }
+            return values;
+        }
+        return null;
+    }
+
+    public String getSupraRegionalString() {
+        return super.getString("supraregional_table");
+    }
+
+    public Integer getYear() {
+        if (getString("ye_select").equals("state.uinfo.year")) {
+            return super.getInteger("singleyear");
+        }
+        return null;
+    }
+
+    public Integer getEpoch() {
+        if (getString("ye_select").equals("state.uinfo.epoch")) {
+            return super.getInteger("singleepoch");
+        }
+        return null;
+    }
+}
\ 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/uinfo/salix/SalixLineCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,158 @@
+/** 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.uinfo.salix;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+final class SalixLineCalculation {
+
+    private final CallContext context;
+
+    public SalixLineCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final UINFOArtifact uinfo) {
+        final Calculation problems = new Calculation();
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name());
+        final String user = CalculationUtils.findArtifactUser(this.context, uinfo);
+
+        final SalixLineAccess accessSalix = new SalixLineAccess(uinfo);
+
+        final River river = accessSalix.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+
+        final DoubleRange range = accessSalix.getRange();
+        final boolean useScenario = accessSalix.getUseScenario();
+        final String selectedScenario = accessSalix.getScenario();
+        final Double fromPart = accessSalix.getFromPart();
+        final Double toPart = accessSalix.getToPart();
+
+        final boolean useSCenario = accessSalix.getUseScenario();
+        final String scenario = accessSalix.getScenario();
+        // calculation_mode
+        // ld_from , ld_to
+        // use_scenario (boolean)
+        // ld_from_part; ld_to_part
+        // scenario_selection (mögliche Werte:"scenarioType.option1" "scenarioType.option2" "scenarioType.option3"
+
+        // FIXME: real calculation
+
+        final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, range);
+
+        final Collection<ResultRow> rows = new ArrayList<>();
+        SalixLineCalculationNoScenarioResult result = null; // verzweigung etwas ungünstig. möglicherweise auch die Abstraktion. ist erstmal nur ne idee
+        final ResultRow row1 = ResultRow.create(). //
+                putValue(GeneralResultType.station, 100).//
+                putValue(UInfoResultType.salixline, 28).//
+                putValue(UInfoResultType.salix_delta_mw, 2);
+
+        if (!useScenario) {
+
+            rows.add(row1);
+            result = new SalixLineCalculationNoScenarioResult("Ergebnis 1", null, rows);
+        } else {
+
+            if (scenario.equals("scenarioType.option1")) { // REGIONAL
+
+                final int[] scenarios = accessSalix.getRegionalScenarioIntegers();
+                final List<SalixScenario> list = new ArrayList<>();
+                for (final int scen_val : scenarios) {
+                    list.add(new SalixScenario(scen_val, 666.));// TODO: replace 666 by real calculated value
+                }
+                row1.putValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl, list);//
+                rows.add(row1);
+                result = new SalixLineCalculationRegionalResult("Ergebnis 1 regional test", null, rows, scenarios);
+
+            } else if (scenario.equals("scenarioType.option2")) { // SUPRA-REGIONAL
+
+                final String supraRegional = accessSalix.getSupraRegionalString();
+                final List<SalixZone> list = SalixZone.parse(supraRegional);
+
+                final Map<DoubleRange, SalixScenario> rangeScenarioMap = new HashMap<>();
+                // make double range
+                for (int i = 0; i < list.size(); i++) {
+                    final SalixZone zone = list.get(i);
+                    final double upper = i < list.size() - 1 ? (zone.getUpperFromTo() - 0.0001) : zone.getUpperFromTo() + 0.0001;// "halboffenes Intervall
+
+                    final DoubleRange zonerange = new DoubleRange((double) zone.getLowerFromTo(), upper);
+                    final double salixValue = 666.;// TODO: calculate the salix value
+                    final SalixScenario salixscen = new SalixScenario(zone.getDwsplValue(), salixValue);
+
+                    rangeScenarioMap.put(zonerange, salixscen);
+                }
+
+                // make calculation
+                double currentKm = range.getMinimumDouble();
+                final double step = 0.1; // TODO: get from global setting?
+                while (currentKm < range.getMaximumDouble()) {
+                    final ResultRow rowSupraRegional = ResultRow.create(). //
+                            putValue(GeneralResultType.station, currentKm).//
+                            putValue(UInfoResultType.salixline, 28).//
+                            putValue(UInfoResultType.salix_delta_mw, 2);
+
+                    final SalixScenario scenarioCurrentKm = findScenarioByKm(currentKm, rangeScenarioMap);
+
+                    if (scenarioCurrentKm != null) { // should not happen, scenarioCurrentKm == null -> BUG
+                        rowSupraRegional.putValue(UInfoResultType.salix_line_scenario, scenarioCurrentKm.getSalixValue());
+                        rowSupraRegional.putValue(UInfoResultType.salix_line_scenario_dwspl, scenarioCurrentKm.getDwspl());
+                    }
+                    rows.add(rowSupraRegional);
+
+                    currentKm = currentKm + step;
+                }
+
+                result = new SalixLineCalculationSupraRegionalResult("Ergebnis 1 supra regional test", null, rows);
+
+            } else if (scenario.equals("scenarioType.option3")) { // HISTORICAL
+                row1.putValue(UInfoResultType.salixlinehist, 66).//
+                        putValue(UInfoResultType.salix_line_scenario_dwspl, 88);
+                rows.add(row1);
+                result = new SalixLineCalculationHistoricalResult("Ergebnis 1 historical test", null, rows);
+            }
+        }
+        results.addResult(result, problems);
+        return new CalculationResult(results, problems);
+    }
+
+    private SalixScenario findScenarioByKm(final double km, final Map<DoubleRange, SalixScenario> rangeScenarioMap) {
+        final Iterator<DoubleRange> rangeIterator = rangeScenarioMap.keySet().iterator();
+        while (rangeIterator.hasNext()) {
+            final DoubleRange range = rangeIterator.next();
+            if (range.containsDouble(km + 0.0001)) {
+                return rangeScenarioMap.get(range);
+            }
+        }
+        return null;
+    }
+}
\ 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/uinfo/salix/SalixLineCalculationHistoricalResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,89 @@
+/** 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.uinfo.salix;
+
+import java.text.NumberFormat;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+final class SalixLineCalculationHistoricalResult extends SalixLineCalculationNoScenarioResult {
+
+    private static final long serialVersionUID = 1L;
+
+    public SalixLineCalculationHistoricalResult(final String label, final WstInfo wst, final Collection<ResultRow> rows) {
+        super(label, wst, rows);
+
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final Collection<String> header = super.writeNoScenarioHeader(exportContextCSV);
+
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salixlinehist));
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_line_scenario_dwspl));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        writeHistoricalViewCSVMetadata(exportContextCSV);
+        exportContextCSV.writeBlankLine();
+
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return formatRow(exportContextCSV, row);
+    }
+
+    private String[] formatRow(final IExportContext context, final ResultRow row) {
+
+        final Collection<String> lines = super.getNoScenarioFormat(row, context);
+
+        if (context instanceof ExportContextCSV) { // enum gespart - pdf-export hat ja nur die drei spalten
+            final NumberFormat formatter = ((ExportContextCSV) context).getSalixScenFormatter();
+
+            lines.add(context.formatRowValue(row, UInfoResultType.salixlinehist));
+            lines.add(context.formatRowValue(row, UInfoResultType.salix_line_scenario_dwspl));
+
+        }
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    // TODO: move to historical class and delete here
+    private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) {
+        final String main = "uinfo.export.csv.meta.header.salix.historical";
+        // "##Historische Betrachtung"
+        exportContextCSV.writeCSVMetaEntry(main);
+
+        final String mainSub = "uinfo.export.csv.meta.header.salix";
+        // "# Szenariotyp: "
+        exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp");
+        // "# Teilabschnitt: "
+        exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt");
+
+        // "# Art des Zeitraums: "
+        exportContextCSV.writeCSVMetaEntry(main + ".zeitart");
+        // "# Historischer Zeitpunkt: "
+        exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt");
+    }
+}
\ 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/uinfo/salix/SalixLineCalculationNoScenarioResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,136 @@
+/** 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.uinfo.salix;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+class SalixLineCalculationNoScenarioResult extends AbstractCalculationExportableResult {
+
+    private static final long serialVersionUID = 1L;
+    private static final String JASPER_FILE = "/jasper/templates/uinfo.salixline.jrxml";
+
+    public SalixLineCalculationNoScenarioResult(final String label, final WstInfo wst, final Collection<ResultRow> rows) {
+        super(label, rows);
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+        final Collection<String> header = writeNoScenarioHeader(exportContextCSV);
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+
+    }
+
+    protected final Collection<String> writeNoScenarioHeader(final ExportContextCSV exportContextCSV) {
+        final Collection<String> header = new ArrayList<>();
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salixline));
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_delta_mw));
+        return header;
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return formatRow(exportContextCSV, row);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) {
+
+        return formatRow(exportContextPDF, row);
+    }
+
+    @Override
+    protected String getJasperFile() {
+
+        return this.JASPER_FILE;
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
+
+        /* additional column headings */
+        exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station);
+        exportContextPDF.addJRMetadata(source, "salix_line", UInfoResultType.salixline);
+        exportContextPDF.addJRMetadata(source, "salix_delta_mw", UInfoResultType.salix_delta_mw);
+
+    }
+
+    private String[] formatRow(final IExportContext context, final ResultRow row) {
+
+        final Collection<String> lines = getNoScenarioFormat(row, context);
+
+        // // ??
+        // // wenn "historisch" gewählt wurde, nur "historisch" anzeigen; sonst für jeden scen-wert ne neue Spalte und "hist"
+        // // ausblenden!...!..!!
+        // lines.add(context.formatRowValue(row, UInfoResultType.salixlinehist));
+        // lines.add(context.formatRowValue(row, UInfoResultType.salixlinescen));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    protected final Collection<String> getNoScenarioFormat(final ResultRow row, final IExportContext context) {
+        final Collection<String> lines = new ArrayList<>();
+        lines.add(context.formatRowValue(row, GeneralResultType.station));
+        lines.add(context.formatRowValue(row, UInfoResultType.salixline));
+        lines.add(context.formatRowValue(row, UInfoResultType.salix_delta_mw));
+
+        return lines;
+
+    }
+
+    protected final void writeRegionalCommonCSVMeta(final ExportContextCSV exportContextCSV) {
+        final String main = "uinfo.export.csv.meta.header.salix";
+        // "# Szenariotyp: "
+        exportContextCSV.writeCSVMetaEntry(main + ".szenariotyp");
+        // "# Teilabschnitt: "
+        exportContextCSV.writeCSVMetaEntry(main + ".teilabschnitt");
+        // "# Mittelwasserspiegellagenänderung: "
+        exportContextCSV.writeCSVMetaEntry(main + ".mwspiegellaenderung");
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        // do nothing. subclass may override
+
+    }
+
+    // private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) {
+    // final String main = "uinfo.export.csv.meta.header.salix.historical";
+    // // "##Historische Betrachtung"
+    // exportContextCSV.writeCSVMetaEntry(main);
+    //
+    // final String mainSub = "uinfo.export.csv.meta.header.salix";
+    // // "# Szenariotyp: "
+    // exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp");
+    // // "# Teilabschnitt: "
+    // exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt");
+    //
+    // // "# Art des Zeitraums: "
+    // exportContextCSV.writeCSVMetaEntry(main + ".zeitart");
+    // // "# Historischer Zeitpunkt: "
+    // exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt");
+    // }
+}
\ 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/uinfo/salix/SalixLineCalculationRegionalResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,113 @@
+/** 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.uinfo.salix;
+
+import java.text.NumberFormat;
+import java.util.Collection;
+import java.util.List;
+
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+final class SalixLineCalculationRegionalResult extends SalixLineCalculationNoScenarioResult {
+
+    private static final long serialVersionUID = 1L;
+    private final int[] scenarioValues;
+
+    public SalixLineCalculationRegionalResult(final String label, final WstInfo wst, final Collection<ResultRow> rows, final int[] scenarioValues) {
+        super(label, wst, rows);
+        this.scenarioValues = scenarioValues; // TODO: diese values müssen eigentlich nur ne anzahl sein, oder so. Ergibt sihc in der Berech
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final Collection<String> header = super.writeNoScenarioHeader(exportContextCSV);
+
+        for (int i = 0; i < this.scenarioValues.length; i++) {
+            // index wurde verworfen, stattdessen 2 spalten
+
+            header.add(exportContextCSV.msg(SalixScenario.getScenarioValueHeader()) + " (" + (i + 1) + ")"); // index kann auch weg, war nur ne idee
+            header.add(exportContextCSV.msg(SalixScenario.getDwsplHeader()) + " (" + (i + 1) + ")");
+        }
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        writeRegionalEffectsCSVMetadata(exportContextCSV);
+        exportContextCSV.writeBlankLine();
+
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return formatRow(exportContextCSV, row);
+    }
+
+    private String[] formatRow(final IExportContext context, final ResultRow row) {
+
+        final Collection<String> lines = super.getNoScenarioFormat(row, context);
+
+        if (context instanceof ExportContextCSV) { // enum gespart - pdf-export hat ja nur die drei spalten
+            final NumberFormat formatter = ((ExportContextCSV) context).getSalixScenFormatter();
+            final List<SalixScenario> scenList = (List<SalixScenario>) row.getValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl);
+
+            for (final SalixScenario scenario : scenList) {
+                // scenario unused; index wurde ja verworfen, stattdessen 2 spalten
+                lines.add(scenario.getSalixValueFormatted(formatter));
+                lines.add(scenario.getDwsplFormatted());
+            }
+        }
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    private void writeRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) {
+        final String main = "uinfo.export.csv.meta.header.salix.regional";
+        // "##Regional wirkende Eingriffe"
+        exportContextCSV.writeCSVMetaEntry(main);
+        writeRegionalCommonCSVMeta(exportContextCSV);
+    }
+
+    // TODO: move to SupraRegionalEffectsResult-Class; remove here
+    // private void writeExtendedRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) {
+    // final String main = "uinfo.export.csv.meta.header.salix.regionalextended";
+    // // "##Ãœberregional wirkende Eingriffe"
+    // exportContextCSV.writeCSVMetaEntry(main);
+    //
+    // writeRegionalCommonCSVMeta(exportContextCSV);
+    // }
+
+    // TODO: move to historical class and delete here
+    // private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) {
+    // final String main = "uinfo.export.csv.meta.header.salix.historical";
+    // // "##Historische Betrachtung"
+    // exportContextCSV.writeCSVMetaEntry(main);
+    //
+    // final String mainSub = "uinfo.export.csv.meta.header.salix";
+    // // "# Szenariotyp: "
+    // exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp");
+    // // "# Teilabschnitt: "
+    // exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt");
+    //
+    // // "# Art des Zeitraums: "
+    // exportContextCSV.writeCSVMetaEntry(main + ".zeitart");
+    // // "# Historischer Zeitpunkt: "
+    // exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt");
+    // }
+}
\ 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/uinfo/salix/SalixLineCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.uinfo.salix;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+final class SalixLineCalculationResults extends AbstractCalculationResults<SalixLineCalculationNoScenarioResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    public SalixLineCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) {
+        super(calcModeLabel, user, river, calcRange);
+    }
+}
\ 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/uinfo/salix/SalixLineCalculationSupraRegionalResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,97 @@
+/** 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.uinfo.salix;
+
+import java.text.NumberFormat;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+final class SalixLineCalculationSupraRegionalResult extends SalixLineCalculationNoScenarioResult {
+
+    private static final long serialVersionUID = 1L;
+
+    public SalixLineCalculationSupraRegionalResult(final String label, final WstInfo wst, final Collection<ResultRow> rows) {
+        super(label, wst, rows);
+
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final Collection<String> header = super.writeNoScenarioHeader(exportContextCSV);
+
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_line_scenario));
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_line_scenario_dwspl));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        writeExtendedRegionalEffectsCSVMetadata(exportContextCSV);
+        exportContextCSV.writeBlankLine();
+
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+
+        return formatRow(exportContextCSV, row);
+    }
+
+    private String[] formatRow(final IExportContext context, final ResultRow row) {
+
+        final Collection<String> lines = super.getNoScenarioFormat(row, context);
+
+        if (context instanceof ExportContextCSV) { // enum gespart - pdf-export hat ja nur die drei spalten
+            final NumberFormat formatter = ((ExportContextCSV) context).getSalixScenFormatter();
+
+            lines.add(context.formatRowValue(row, UInfoResultType.salix_line_scenario));
+            lines.add(context.formatRowValue(row, UInfoResultType.salix_line_scenario_dwspl));
+
+        }
+        return lines.toArray(new String[lines.size()]);
+    }
+
+    private void writeExtendedRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) {
+        final String main = "uinfo.export.csv.meta.header.salix.regionalextended";
+        // "##Ãœberregional wirkende Eingriffe"
+        exportContextCSV.writeCSVMetaEntry(main);
+
+        writeRegionalCommonCSVMeta(exportContextCSV);
+    }
+
+    // TODO: move to historical class and delete here
+    // private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) {
+    // final String main = "uinfo.export.csv.meta.header.salix.historical";
+    // // "##Historische Betrachtung"
+    // exportContextCSV.writeCSVMetaEntry(main);
+    //
+    // final String mainSub = "uinfo.export.csv.meta.header.salix";
+    // // "# Szenariotyp: "
+    // exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp");
+    // // "# Teilabschnitt: "
+    // exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt");
+    //
+    // // "# Art des Zeitraums: "
+    // exportContextCSV.writeCSVMetaEntry(main + ".zeitart");
+    // // "# Historischer Zeitpunkt: "
+    // exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt");
+    // }
+}
\ 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/uinfo/salix/SalixLineExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,45 @@
+/** 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.uinfo.salix;
+
+import org.dive4elements.river.artifacts.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SalixLineExporter extends AbstractCommonExporter<SalixLineCalculationNoScenarioResult, SalixLineCalculationResults> {
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContextCSV, final SalixLineCalculationResults results) {
+        /* write as csv */
+        exportContextCSV.writeCSVGlobalMetadataDefaults();
+
+        // Add Auswerter, Bezugspegel, Jahr/Zeitraum der Wasserspiegellage
+
+        // "# Auswerter: "
+        exportContextCSV.writeCSVMetaEntry("uinfo.export.salix_line.csv.meta.header.evaluator", "sounding.getEvaluationBy()");
+        // "# Bezugspegel: "
+        exportContextCSV.writeCSVMetaEntry("uinfo.export.salix_line.csv.meta.header.waterlevel.gauge", "wst.getGauge()");
+
+        // "# Jahr/Zeitraum der Wasserspiegellage: "
+        exportContextCSV.writeCSVMetaEntry("uinfo.export.salix_line.csv.meta.header.waterlevel.year", "TODO...");
+
+    }
+
+    @Override
+    protected void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+    }
+
+}
\ 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/uinfo/salix/SalixLineState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,104 @@
+/** 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.uinfo.salix;
+
+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.states.DefaultState;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class SalixLineState extends DefaultState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FlowDepthState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 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((UINFOArtifact) 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((UINFOArtifact) artifact, context, hash, facets, old);
+    }
+
+    /**
+     * Compute result or returned object from cache, create facets.
+     *
+     * @param old
+     *            Object that was cached.
+     */
+    private Object compute(final UINFOArtifact sinfo, final CallContext context, final String hash, final List<Facet> facets, final Object old) {
+
+        final CalculationResult res = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+
+        final SalixLineCalculationResults results = (SalixLineCalculationResults) res.getData();
+
+        final List<SalixLineCalculationNoScenarioResult> resultList = results.getResults();
+
+        if (!resultList.isEmpty()) {
+            final Facet csv = new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id);
+            final Facet pdf = new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id);
+
+            facets.add(csv);
+            facets.add(pdf);
+        }
+
+        final Calculation report = res.getReport();
+
+        if (report.hasProblems())
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final UINFOArtifact sinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new SalixLineCalculation(context).calculate(sinfo);
+    }
+}
\ 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/uinfo/salix/SalixScenario.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,55 @@
+/** 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.uinfo.salix;
+
+import java.io.Serializable;
+import java.text.NumberFormat;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SalixScenario implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final double salix_value;
+    private final int dwspl;
+
+    public SalixScenario(final int scen_val, final double salix_value) {
+        this.dwspl = scen_val;
+        this.salix_value = salix_value;
+    }
+
+    public double getSalixValue() {
+        return this.salix_value;
+    }
+
+    public int getDwspl() {
+        return this.dwspl;
+    }
+
+    public String getDwsplFormatted() {
+        return String.valueOf(this.dwspl);
+    }
+
+    public String getSalixValueFormatted(final NumberFormat formatter) {
+        return formatter.format(this.salix_value);
+    }
+
+    public static final String getScenarioValueHeader() {
+        return "uinfo.export.salix_line.csv.header.scenario";
+    }
+
+    public static final String getDwsplHeader() {
+        return "uinfo.export.salix_line.csv.header.scenario_dwspl";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixZone.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,176 @@
+/** 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.uinfo.salix;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SalixZone implements Comparable<SalixZone> {
+
+    // IMMER ABGLEICHEN Server Client SalixZone.java
+    private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR";
+    private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR";
+    private final int dwsplValue;
+    private final double fromKm;
+    private final double toKm;
+
+    private final static double DELTA = 0.0001;
+
+    public static List<SalixZone> parse(final String zonesRaw) {
+        final List<SalixZone> resultList = new ArrayList<>();
+
+        final List<String[]> results = new ArrayList<>();
+        if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) {
+            final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR);
+            for (final String row : rows) {
+                if (row.contains(TABLE_CELL_SEPARATOR)) {
+                    final String[] result = row.split(TABLE_CELL_SEPARATOR);
+                    results.add(result);
+                }
+            }
+        }
+        for (final String[] zone : results) {
+            final SalixZone helper = new SalixZone(Integer.valueOf(zone[0]), Double.valueOf(zone[1]), Double.valueOf(zone[2]));
+            resultList.add(helper);
+        }
+        return resultList;
+    }
+
+    public static SalixZone createFromTableEntry(final String dwspl, final String from, final String to) {
+        return new SalixZone(Integer.valueOf(dwspl), Double.valueOf(from), Double.valueOf(to)); // Error-Handling?
+    }
+
+    private SalixZone(final int dwsplValue, final double fromKm, final double toKm) {
+        this.dwsplValue = dwsplValue;
+        this.fromKm = fromKm;
+        this.toKm = toKm;
+    }
+
+    public Double getToKm() {
+        return this.toKm;
+    }
+
+    public int getDwsplValue() {
+        return this.dwsplValue;
+    }
+
+    public Double getFromKm() {
+        return this.fromKm;
+    }
+
+    public static final String parseListToDataString(final List<SalixZone> list) {
+
+        java.util.Collections.sort(list);
+        final StringBuilder builder = new StringBuilder();
+        for (final SalixZone zone : list) {
+            builder.append(zone.getDwsplValue());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getFromKm());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getToKm());
+            builder.append(TABLE_ROW_SEPARATOR);
+        }
+        return builder.toString();
+    }
+
+    public static final boolean zonesAreOverlapping(final List<SalixZone> list) {
+        for (final SalixZone zone : list) {
+            for (final SalixZone zoneOther : list) {
+                if (zone != zoneOther) {
+                    final boolean overlaps = zone.overlaps(zoneOther);
+                    if (overlaps) {
+                        return overlaps; // cancel. only one zone has to overlap
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public static final boolean hasGaps(final List<SalixZone> list, final double lower, final double upper) {
+
+        if (((upper - lower) > DELTA) && list.size() == 0)
+            return true;
+
+        final TreeSet<SalixZone> treeList = new TreeSet<>();
+        treeList.addAll(list);
+        double lowerCompare = lower + DELTA;
+        for (final SalixZone zone : treeList) {
+            if ((zone.getUpperFromTo() - zone.getLowerFromTo()) > DELTA) {
+                if (zone.getLowerFromTo() > lowerCompare) {
+                    return true;
+                }
+                lowerCompare = zone.getUpperFromTo() + DELTA;
+            }
+        }
+        if ((lowerCompare + DELTA) < upper)
+            return true; // am Ende nicht geschlossen
+
+        return false;
+    }
+
+    public Double getLowerFromTo() {
+        return this.fromKm < this.toKm ? this.fromKm : this.toKm; // Math. is forbidden :-(
+    }
+
+    public Double getUpperFromTo() {
+        return this.fromKm > this.toKm ? this.fromKm : this.toKm;// Math. is forbidden :-(
+    }
+
+    private boolean overlaps(final SalixZone otherZone) {
+        final double otherLower = otherZone.getLowerFromTo();
+        final double otherUpper = otherZone.getUpperFromTo();
+
+        final double upper = getUpperFromTo();
+        final double lower = getLowerFromTo();
+        final double otherSchwerpunkt = (otherLower + otherUpper) / 2;
+        if ((otherUpper < upper && otherUpper > lower)) {
+            return true;
+        } else if (otherLower > lower && otherLower < upper) {
+            return true;
+        } else if (otherSchwerpunkt > (lower - DELTA) && otherSchwerpunkt < (upper + DELTA)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int compareTo(final SalixZone o) {
+        final int basicCompare = this.getLowerFromTo().compareTo(o.getLowerFromTo());
+        if (basicCompare == 0) {
+            return 1; // necessary for the treeSet!
+        }
+        return basicCompare;
+    }
+
+    public static boolean isValidAnschlussRange(final double fromTest, final double toTest, final List<SalixZone> list, final double minKm) {
+        final SalixZone zone = new SalixZone(0, fromTest, toTest);
+        final double lower = zone.getLowerFromTo();
+        final double anschluss = getAnschluss(list, minKm);
+        final double differenceAbs = (lower - anschluss) > 0 ? (lower - anschluss) : (anschluss - lower); // no Math.abs allowed :-(
+        if (differenceAbs > DELTA) {
+            return false;
+        }
+        return true;
+    }
+
+    private static double getAnschluss(final List<SalixZone> list, final double minKm) {
+        if (list.size() > 0) {
+            return list.get(list.size() - 1).getUpperFromTo();
+        }
+        return minKm;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/ScenarioTypeState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,29 @@
+
+package org.dive4elements.river.artifacts.uinfo.salix;
+
+import java.util.LinkedHashMap;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.states.RadioSelect;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class ScenarioTypeState extends RadioSelect {
+    private static final long serialVersionUID = 1L;
+
+    public ScenarioTypeState() {
+        super();
+    }
+
+    @Override
+    protected LinkedHashMap<String, String> makeEntries(final CallMeta meta, final Artifact artifact) {
+        final LinkedHashMap<String, String> entries = new LinkedHashMap<>();
+        entries.put("scenarioType.option1", null);
+        entries.put("scenarioType.option2", null);
+        entries.put("scenarioType.option3", null);
+        return entries;
+
+    }
+}
\ 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/uinfo/salix/SupraRegionalTableState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,54 @@
+/** 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.uinfo.salix;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.w3c.dom.Element;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class SupraRegionalTableState extends DefaultState {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected String getUIProvider() {
+        return "uinfo.salix.supraregional.table";
+    }
+
+    @Override
+    protected Element[] createItems(final ElementCreator cr, final Artifact artifact, final String name, final CallContext context) {
+        final String datakey = "supraregional_table";
+        if (name.equals(datakey)) {
+
+            final D4EArtifact flys = (D4EArtifact) artifact;
+            final String s = flys.getDataAsString(datakey);
+
+            final RangeAccess ra = new RangeAccess((D4EArtifact) artifact);
+
+            final Element item = createItem(cr, new String[] { "salix_zones", s });
+            final Element min = createItem(cr, new String[] { "salix_zones_min", new Double(ra.getFrom()).toString() });
+
+            final Element max = createItem(cr, new String[] { "salix_zones_max", new Double(ra.getTo()).toString() });
+
+            return new Element[] { min, max, item };
+
+        }
+
+        return new Element[] {};
+    }
+
+}
\ 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/uinfo/salix/UseScenarioChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,23 @@
+/* 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.uinfo.salix;
+
+import org.dive4elements.river.artifacts.states.BooleanChoiceState;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class UseScenarioChoice extends BooleanChoiceState {
+
+    private static final long serialVersionUID = 1L;
+
+    public UseScenarioChoice() {
+        super("useScenario.option", "useScenario.active", "useScenario.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/uinfo/salix/YearChoice.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,35 @@
+/* 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.uinfo.salix;
+
+import java.util.LinkedHashMap;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.states.RadioSelect;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class YearChoice extends RadioSelect {
+    private static final long serialVersionUID = 1L;
+
+    public YearChoice() {
+        super();
+    }
+
+    @Override
+    protected LinkedHashMap<String, String> makeEntries(final CallMeta meta, final Artifact artifact) {
+        final LinkedHashMap<String, String> entries = new LinkedHashMap<>();
+        entries.put("state.uinfo.year", null);
+        entries.put("state.uinfo.epoch", null);
+        return entries;
+    }
+
+}
\ 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/uinfo/vegetationzones/VegetationZone.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,112 @@
+/** 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.uinfo.vegetationzones;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class VegetationZone implements Comparable<VegetationZone> {
+
+    // IMMER ABGLEICHEN MIT VEGETATIONZONE IM CLIENT SuperVegZonesTablePanel.TABLE_CELL_SEPARATOR
+    private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR";
+    private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR";
+    private final String zoneName;
+    private final int min_day_overflow;
+    private final int max_day_overflow;
+
+    public static List<VegetationZone> parse(final String zonesRaw) {
+        final List<VegetationZone> resultList = new ArrayList<>();
+
+        final List<String[]> results = new ArrayList<>();
+        if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) {
+            final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR);
+            for (final String row : rows) {
+                if (row.contains(TABLE_CELL_SEPARATOR)) {
+                    final String[] result = row.split(TABLE_CELL_SEPARATOR);
+                    results.add(result);
+                }
+            }
+        }
+        for (final String[] zone : results) {
+
+            final VegetationZone helper = new VegetationZone(zone[0], Integer.valueOf(zone[1]), Integer.valueOf(zone[2]));
+            resultList.add(helper);
+        }
+
+        return resultList;
+    }
+
+    public static VegetationZone createFromTableEntry(final String zone, final String min_day_overflow, final String max_day_overflow) {
+        return new VegetationZone(zone, Integer.valueOf(min_day_overflow), Integer.valueOf(max_day_overflow)); // Error-Handling?
+    }
+
+    private VegetationZone(final String zone, final Integer min_day_overflow, final Integer max_day_overflow) {
+        this.zoneName = zone;
+        this.min_day_overflow = min_day_overflow;
+        this.max_day_overflow = max_day_overflow;
+    }
+
+    public int getMax_day_overflow() {
+        return this.max_day_overflow;
+    }
+
+    public String getZoneName() {
+        return this.zoneName;
+    }
+
+    public int getMin_day_overflow() {
+        return this.min_day_overflow;
+    }
+
+    public static final List<VegetationZone> getStandardList() {
+
+        final List<VegetationZone> list = new ArrayList<>();
+        list.add(new VegetationZone("Zonaler Wald", 0, 5));
+        list.add(new VegetationZone("Hartholzaue, trocken", 5, 40));
+        list.add(new VegetationZone("Hartholzaue, feucht", 40, 80));
+        list.add(new VegetationZone("Silberweidenwald", 80, 140));
+        list.add(new VegetationZone("Weidengebüsch", 140, 200));
+        list.add(new VegetationZone("Uferröhricht", 200, 260));
+        list.add(new VegetationZone("Uferpioniere", 260, 320));
+        list.add(new VegetationZone("Vegetationslos", 320, 365));
+        list.add(new VegetationZone("Wasserfläche", 365, 365));
+
+        return list;
+    }
+
+    public static final String parseListToDataString(final List<VegetationZone> list) {
+
+        java.util.Collections.sort(list);
+        final StringBuilder builder = new StringBuilder();
+        for (final VegetationZone zone : list) {
+            builder.append(zone.getZoneName());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getMin_day_overflow());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getMax_day_overflow());
+            builder.append(TABLE_ROW_SEPARATOR);
+        }
+        return builder.toString();
+
+    }
+
+    @Override
+    public int compareTo(final VegetationZone o) {
+        final int basicCompare = Integer.valueOf(this.getMin_day_overflow()).compareTo(o.getMin_day_overflow());
+        if (basicCompare == 0)
+            return Integer.compare(this.getMax_day_overflow(), o.getMax_day_overflow()); // wenn min==min && max==max, alphabetisch sortieren?
+        return basicCompare;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCalculation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,70 @@
+/** 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.uinfo.vegetationzones;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+final class VegetationZonesCalculation {
+
+    private final CallContext context;
+
+    public VegetationZonesCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final UINFOArtifact uinfo) {
+        final Calculation problems = new Calculation();
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name());
+        final String user = CalculationUtils.findArtifactUser(this.context, uinfo);
+
+        final VegetationzonesAccess vAccess = new VegetationzonesAccess(uinfo);
+        final River river = vAccess.getRiver();
+        final DoubleRange calcRange = vAccess.getRange();
+        final RiverInfo riverInfo = new RiverInfo(river);
+
+        final String zonesRaw = vAccess.getVegZones();
+        final List<VegetationZone> helpers = VegetationZone.parse(zonesRaw);
+        final VegetationZonesCalculationResults results = new VegetationZonesCalculationResults(calcModeLabel, user, riverInfo, calcRange);
+
+        final Collection<ResultRow> rows = new ArrayList<>();
+        for (final VegetationZone zone : helpers) {
+            final ResultRow row2 = ResultRow.create().//
+                    putValue(UInfoResultType.vegname, zone.getZoneName()).//
+                    putValue(UInfoResultType.vegdauervon, zone.getMin_day_overflow()).//
+                    putValue(UInfoResultType.vegdauerbis, zone.getMax_day_overflow());
+            rows.add(row2);
+        }
+
+        final VegetationZonesCalculationResult result = new VegetationZonesCalculationResult("Ergebnis 1", rows);
+
+        results.addResult(result, problems);
+
+        return new CalculationResult(results, problems);
+    }
+}
\ 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/uinfo/vegetationzones/VegetationZonesCalculationResult.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,91 @@
+/** 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.uinfo.vegetationzones;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.IExportContext;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+final class VegetationZonesCalculationResult extends AbstractCalculationExportableResult {
+    private static final long serialVersionUID = 1L;
+
+    private static final String JASPER_FILE = "/jasper/templates/uinfo.vegetationzones.jrxml";
+
+    public VegetationZonesCalculationResult(final String label, final Collection<ResultRow> rows) {
+        super(label, rows);
+    }
+
+    @Override
+    public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
+
+        final Collection<String> header = new ArrayList<>(11);
+
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.vegname));
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.vegdauervon));
+        header.add(exportContextCSV.formatCsvHeader(UInfoResultType.vegdauerbis));
+
+        exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+    }
+
+    @Override
+    protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) {
+        // no metadata
+
+    }
+
+    @Override
+    protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
+        return formatRow(exportContextCSV, row);
+    }
+
+    @Override
+    protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) {
+
+        return formatRow(exportContextPDF, row);
+    }
+
+    @Override
+    protected String getJasperFile() {
+
+        return JASPER_FILE;
+    }
+
+    @Override
+    protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
+        /* additional column headings */
+        exportContextPDF.addJRMetadata(source, "veg_name", UInfoResultType.vegname);
+        exportContextPDF.addJRMetadata(source, "veg_dauervon", UInfoResultType.vegdauervon);
+        exportContextPDF.addJRMetadata(source, "veg_dauerbis", UInfoResultType.vegdauerbis);
+
+    }
+
+    protected String[] formatRow(final IExportContext context, final ResultRow row) {
+
+        final Collection<String> lines = new ArrayList<>(11);
+
+        lines.add(context.formatRowValue(row, UInfoResultType.vegname));
+        lines.add(context.formatRowValue(row, UInfoResultType.vegdauervon));
+        lines.add(context.formatRowValue(row, UInfoResultType.vegdauerbis));
+
+        return lines.toArray(new String[lines.size()]);
+    }
+
+}
\ 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/uinfo/vegetationzones/VegetationZonesCalculationResults.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.uinfo.vegetationzones;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+final class VegetationZonesCalculationResults extends AbstractCalculationResults<VegetationZonesCalculationResult> {
+
+    private static final long serialVersionUID = 1L;
+
+    public VegetationZonesCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) {
+        super(calcModeLabel, user, river, calcRange);
+    }
+}
\ 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/uinfo/vegetationzones/VegetationZonesExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,33 @@
+/** 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.uinfo.vegetationzones;
+
+import org.dive4elements.river.artifacts.common.AbstractCommonExporter;
+import org.dive4elements.river.artifacts.common.ExportContextCSV;
+import org.dive4elements.river.artifacts.common.ExportContextPDF;
+import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class VegetationZonesExporter extends AbstractCommonExporter<VegetationZonesCalculationResult, VegetationZonesCalculationResults> {
+
+    @Override
+    protected void writeCSVGlobalMetadata(final ExportContextCSV exportContext, final VegetationZonesCalculationResults results) {
+        exportContext.writeCSVGlobalMetadataDefaults();
+
+    }
+
+    @Override
+    protected void writePDFGlobalMetadata(final ExportContextPDF exportContext, final MetaAndTableJRDataSource source) {
+        exportContext.addJRMetaDataUSINFO(source);
+    }
+}
\ 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/uinfo/vegetationzones/VegetationZonesState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,103 @@
+/** 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.uinfo.vegetationzones;
+
+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.states.DefaultState;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class VegetationZonesState extends DefaultState {
+
+    /// ** The log that is used in this state. */
+    // private static Logger log = Logger.getLogger(FlowDepthState.class);
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 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((UINFOArtifact) 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((UINFOArtifact) artifact, context, hash, facets, old);
+    }
+
+    /**
+     * Compute result or returned object from cache, create facets.
+     *
+     * @param old
+     *            Object that was cached.
+     */
+    private Object compute(final UINFOArtifact sinfo, final CallContext context, final String hash, final List<Facet> facets, final Object old) {
+
+        final CalculationResult res = doCompute(sinfo, context, old);
+
+        if (facets == null)
+            return res;
+
+        final VegetationZonesCalculationResults results = (VegetationZonesCalculationResults) res.getData();
+
+        final List<VegetationZonesCalculationResult> resultList = results.getResults();
+
+        if (!resultList.isEmpty()) {
+            final Facet csv = new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id);
+            final Facet pdf = new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id);
+
+            facets.add(csv);
+            facets.add(pdf);
+        }
+
+        final Calculation report = res.getReport();
+
+        if (report.hasProblems())
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
+
+        return res;
+    }
+
+    private CalculationResult doCompute(final UINFOArtifact uinfo, final CallContext context, final Object old) {
+        if (old instanceof CalculationResult)
+            return (CalculationResult) old;
+
+        return new VegetationZonesCalculation(context).calculate(uinfo);
+    }
+}
\ 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/uinfo/vegetationzones/VegetationZonesTableEditState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,93 @@
+/** 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.uinfo.vegetationzones;
+
+import org.dive4elements.artifactdatabase.ProtocolUtils;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.w3c.dom.Element;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class VegetationZonesTableEditState extends DefaultState {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected String getUIProvider() {
+        return "uinfo.vegetationzones.table.edit";
+    }
+
+    @Override
+    protected Element[] createItems(final ElementCreator cr, final Artifact artifact, final String name, final CallContext context) {
+        final String datakey = "vegzones";
+        if (name.equals(datakey)) {
+            final Element item = ProtocolUtils.createArtNode(cr, "item", null, null);
+            final Element label = ProtocolUtils.createArtNode(cr, "label", null, null);
+            final Element value = ProtocolUtils.createArtNode(cr, "value", null, null);
+            final D4EArtifact flys = (D4EArtifact) artifact;
+            final String s = flys.getDataAsString(datakey) == null ? VegetationZone.parseListToDataString(VegetationZone.getStandardList())
+                    : flys.getDataAsString(datakey);
+
+            value.setTextContent(s);
+            item.appendChild(label);
+            item.appendChild(value);
+            return new Element[] { item };
+        }
+        return new Element[] {};
+    }
+
+    @Override
+    public boolean validate(final Artifact artifact) throws IllegalArgumentException {
+        // TODO: check verstehen
+
+        // final InundationDurationAccess access = new InundationDurationAccess((SINFOArtifact) artifact);
+
+        // Second year should be later than first.
+
+        // if (access.getYears() == null || access.getYears().length == 0)
+        return true;
+        // throw new IllegalArgumentException("error_years_wrong");
+
+        // return true;
+    }
+
+    /**
+     * Creats the data element used for the static part of DESCRIBE document.
+     */
+    // @Override
+    // protected Element createStaticData(final D4EArtifact flys, final ElementCreator creator, final CallContext cc, final
+    // String name, final String value,
+    // final String type) {
+    // final Element dataElement = creator.create("data");
+    // creator.addAttr(dataElement, "name", name, true);
+    // creator.addAttr(dataElement, "type", type, true);
+    //
+    // final Element itemElement = creator.create("item");
+    // creator.addAttr(itemElement, "value", value, true);
+    //
+    // final String[] labels = getLabels(cc, value);
+    // final Object[] obj = new Object[] { labels[0] };
+    //
+    // // TODO own i18n
+    // final String attrValue = Resources.getMsg(cc.getMeta(), "wsp.selected.string", "wsp.selected.string", obj);
+    // // I18N_STATIC_KEY, I18N_STATIC_KEY, obj);
+    //
+    // creator.addAttr(itemElement, "label", attrValue, true);
+    // dataElement.appendChild(itemElement);
+    //
+    // return dataElement;
+    // }
+
+}
\ 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/uinfo/vegetationzones/VegetationZonesTableState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,51 @@
+/** 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.uinfo.vegetationzones;
+
+import org.dive4elements.artifactdatabase.ProtocolUtils;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.states.DefaultState;
+import org.w3c.dom.Element;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public class VegetationZonesTableState extends DefaultState {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected String getUIProvider() {
+        return "uinfo.vegetationzones.table";
+    }
+
+    // TODO GET REAL DATA
+    @Override
+    protected Element[] createItems(final ElementCreator cr, final Artifact artifact, final String name, final CallContext context) {
+        final String datakey = "vegzones";
+        if (name.equals(datakey)) {
+            final Element item = ProtocolUtils.createArtNode(cr, "item", null, null);
+            final Element label = ProtocolUtils.createArtNode(cr, "label", null, null);
+            final Element value = ProtocolUtils.createArtNode(cr, "value", null, null);
+            final D4EArtifact flys = (D4EArtifact) artifact;
+            final String s = flys.getDataAsString(datakey) == null ? VegetationZone.parseListToDataString(VegetationZone.getStandardList())
+                    : flys.getDataAsString(datakey);
+
+            value.setTextContent(s);
+            item.appendChild(label);
+            item.appendChild(value);
+            return new Element[] { item };
+        }
+        return new Element[] {};
+    }
+}
\ 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/uinfo/vegetationzones/VegetationzonesAccess.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,48 @@
+/* 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.uinfo.vegetationzones;
+
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.common.EpochYearAccessHelper;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.UinfoCalcMode;
+
+/**
+ * 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
+ */
+final class VegetationzonesAccess extends RangeAccess {
+
+    private final EpochYearAccessHelper helper;
+
+    // Fields from state:
+    // calculation_mode (String)
+    // ld_from, ld_to,ld_step
+    // vegzones (String)
+
+    public VegetationzonesAccess(final UINFOArtifact uinfo) {
+        super(uinfo);
+
+        /* assert calculation mode */
+        final UinfoCalcMode calculationMode = uinfo.getCalculationMode();
+        this.helper = new EpochYearAccessHelper(uinfo);
+        assert (calculationMode == UinfoCalcMode.uinfo_vegetation_zones);
+    }
+
+    public String getVegZones() {
+        return super.getString("vegzones");
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/AbstractChartGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,1309 @@
+/** 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.exports;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Paint;
+import java.awt.Stroke;
+import java.awt.TexturePaint;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.xml.xpath.XPathConstants;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Settings;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.ArtifactNamespaceContext;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.PreferredLocale;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.FLYS;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.collections.D4EArtifactCollection;
+import org.dive4elements.river.jfree.AxisDataset;
+import org.dive4elements.river.jfree.Bounds;
+import org.dive4elements.river.jfree.DoubleBounds;
+import org.dive4elements.river.jfree.EnhancedLineAndShapeRenderer;
+import org.dive4elements.river.jfree.RiverAnnotation;
+import org.dive4elements.river.jfree.StableXYDifferenceRenderer;
+import org.dive4elements.river.jfree.Style;
+import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
+import org.dive4elements.river.jfree.StyledSeries;
+import org.dive4elements.river.themes.ThemeDocument;
+import org.dive4elements.river.utils.Formatter;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.LegendItem;
+import org.jfree.chart.LegendItemCollection;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.chart.title.TextTitle;
+import org.jfree.data.Range;
+import org.jfree.data.general.Series;
+import org.jfree.data.xy.XYDataset;
+import org.jfree.ui.RectangleInsets;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * This class re-unites the tremendous copy/paste code from ChartGenerator and ChartGenerator2. Code is still awful and
+ * encapsulation is broken in too many places.
+ * TODO: instead of deep inheritances, delegate to classes that define the various behaviors.
+ *
+ * @author Gernot Belger
+ */
+abstract class AbstractChartGenerator implements OutGenerator {
+
+    protected static final Logger log = Logger.getLogger(AbstractChartGenerator.class);
+
+    private static final int DEFAULT_CHART_WIDTH = 600;
+
+    private static final int DEFAULT_CHART_HEIGHT = 400;
+
+    private static final Color DEFAULT_GRID_COLOR = Color.GRAY;
+
+    private static final float DEFAULT_GRID_LINE_WIDTH = 0.3f;
+
+    protected static final String DEFAULT_FONT_NAME = "Tahoma";
+
+    protected static final int DEFAULT_FONT_SIZE = 12;
+
+    private static final String DEFAULT_CHART_FORMAT = "png";
+
+    private static final String XPATH_CHART_EXPORT = "/art:action/art:attributes/art:export/@art:value";
+
+    private static final String XPATH_CHART_SIZE = "/art:action/art:attributes/art:size";
+
+    private static final String XPATH_CHART_FORMAT = "/art:action/art:attributes/art:format/@art:value";
+
+    private static final String XPATH_CHART_X_RANGE = "/art:action/art:attributes/art:xrange";
+
+    private static final String XPATH_CHART_Y_RANGE = "/art:action/art:attributes/art:yrange";
+
+    /** The document of the incoming out() request. */
+    private Document request;
+
+    /** The output stream where the data should be written to. */
+    private OutputStream out;
+
+    /** Artifact that is used to decorate the chart with meta information. */
+    private Artifact master;
+
+    /** Map of datasets ("index"). */
+    private final SortedMap<Integer, AxisDataset> datasets = new TreeMap<>();
+
+    /** List of annotations to insert in plot. */
+    private final List<RiverAnnotation> annotations = new ArrayList<>();
+
+    private String outName;
+
+    /** The settings that should be used during output creation. */
+    private Settings settings;
+
+    /** The CallContext object. */
+    private CallContext context;
+
+    @Override
+    public void init(final String outName, final Document request, final OutputStream out, final CallContext context) {
+        log.debug("ChartGenerator.init");
+
+        this.outName = outName;
+        this.request = request;
+        this.out = out;
+        this.context = context;
+    }
+
+    @Override
+    public void setup(final Object config) {
+    }
+
+    /** Sets the master artifact. */
+    @Override
+    public void setMasterArtifact(final Artifact master) {
+        this.master = master;
+    }
+
+    /**
+     * Gets the master artifact.
+     *
+     * @return the master artifact.
+     */
+    public Artifact getMaster() {
+        return this.master;
+    }
+
+    protected final Map<Integer, AxisDataset> getDatasets() {
+        return this.datasets;
+    }
+
+    @Override
+    public void setCollection(final D4EArtifactCollection collection) {
+        /* we do not need it */
+    }
+
+    protected final D4EArtifact getArtifact() {
+        // FIXME: should already made sure when this member is set
+        return (D4EArtifact) this.master;
+    }
+
+    public final CallContext getContext() {
+        return this.context;
+    }
+
+    /** The document of the incoming out() request. */
+    protected final Document getRequest() {
+        return this.request;
+    }
+
+    /**
+     * Adds annotations to list. The given annotation will be visible.
+     */
+    public final void addAnnotations(final RiverAnnotation annotation) {
+        this.annotations.add(annotation);
+    }
+
+    /**
+     * This method needs to be implemented by concrete subclasses to create new
+     * instances of JFreeChart.
+     *
+     * @param context2
+     *
+     * @return a new instance of a JFreeChart.
+     */
+    protected abstract JFreeChart generateChart(CallContext context2);
+
+    /**
+     * For every outable (i.e. facets), this function is
+     * called and handles the data accordingly.
+     */
+    @Override
+    public abstract void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible);
+
+    @Override
+    public void generate() throws IOException {
+        doGenerate(this.context, this.out, this.outName);
+    }
+
+    protected abstract void doGenerate(CallContext context, OutputStream out, String outName) throws IOException;
+
+    protected abstract Series getSeriesOf(XYDataset dataset, int idx);
+
+    /**
+     * Returns the default title of a chart.
+     *
+     * @param context2
+     *
+     * @return the default title of a chart.
+     */
+    protected abstract String getDefaultChartTitle(CallContext context);
+
+    /**
+     * This method is used to create new AxisDataset instances which may differ
+     * in concrete subclasses.
+     *
+     * @param idx
+     *            The index of an axis.
+     */
+    protected abstract AxisDataset createAxisDataset(int idx);
+
+    /**
+     * Combines the ranges of the X axis at index <i>idx</i>.
+     *
+     * @param bounds
+     *            A new Bounds.
+     * @param idx
+     *            The index of the X axis that should be comined with
+     *            <i>range</i>.
+     */
+    protected abstract void combineXBounds(Bounds bounds, int idx);
+
+    /**
+     * Combines the ranges of the Y axis at index <i>idx</i>.
+     *
+     * @param bounds
+     *            A new Bounds.
+     * @param index
+     *            The index of the Y axis that should be comined with.
+     *            <i>range</i>.
+     */
+    protected abstract void combineYBounds(Bounds bounds, int index);
+
+    /**
+     * This method is used to determine the ranges for axes at a given index.
+     *
+     * @param index
+     *            The index of the axes at the plot.
+     *
+     * @return a Range[] with [xrange, yrange];
+     */
+    protected abstract Range[] getRangesForAxis(int index);
+
+    protected abstract Bounds getXBounds(int axis);
+
+    protected abstract void setXBounds(int axis, Bounds bounds);
+
+    protected abstract Bounds getYBounds(int axis);
+
+    protected abstract void setYBounds(int axis, Bounds bounds);
+
+    // /**
+    // * Retuns the call context. May be null if init hasn't been called yet.
+    // *
+    // * @return the CallContext instance
+    // */
+    // protected final CallContext getCallContext() {
+    // return this.context;
+    // }
+    //
+
+    @Override
+    public final void setSettings(final Settings settings) {
+        this.settings = settings;
+    }
+
+    /**
+     * Returns the <i>settings</i> as <i>ChartSettings</i>.
+     *
+     * @return the <i>settings</i> as <i>ChartSettings</i> or null, if
+     *         <i>settings</i> is not an instance of <i>ChartSettings</i>.
+     */
+    protected final ChartSettings getChartSettings() {
+        if (this.settings instanceof ChartSettings) {
+            return (ChartSettings) this.settings;
+        }
+
+        return null;
+    }
+
+    /**
+     * Return instance of <i>ChartSettings</i> with a chart specific section
+     * but with no axes settings.
+     *
+     * @return an instance of <i>ChartSettings</i>.
+     */
+    @Override
+    public final Settings getSettings() {
+        if (this.settings != null)
+            return this.settings;
+
+        final ChartSettings settings = new ChartSettings();
+
+        final ChartSection chartSection = buildChartSection(this.context);
+        final LegendSection legendSection = buildLegendSection();
+        final ExportSection exportSection = buildExportSection();
+
+        settings.setChartSection(chartSection);
+        settings.setLegendSection(legendSection);
+        settings.setExportSection(exportSection);
+
+        final List<AxisSection> axisSections = buildAxisSections();
+        for (final AxisSection axisSection : axisSections)
+            settings.addAxisSection(axisSection);
+
+        return settings;
+    }
+
+    protected abstract ChartSection buildChartSection(CallContext context);
+
+    /**
+     * Creates a new <i>LegendSection</i>.
+     *
+     * @return a new <i>LegendSection</i>.
+     */
+    private LegendSection buildLegendSection() {
+        final LegendSection legendSection = new LegendSection();
+        legendSection.setVisibility(isLegendVisible());
+        legendSection.setFontSize(getLegendFontSize());
+        legendSection.setAggregationThreshold(10);
+        return legendSection;
+    }
+
+    /**
+     * Creates a new <i>ExportSection</i> with default values <b>WIDTH=600</b>
+     * and <b>HEIGHT=400</b>.
+     *
+     * @return a new <i>ExportSection</i>.
+     */
+    private ExportSection buildExportSection() {
+        final ExportSection exportSection = new ExportSection();
+        exportSection.setWidth(DEFAULT_CHART_WIDTH);
+        exportSection.setHeight(DEFAULT_CHART_HEIGHT);
+        exportSection.setMetadata(true);
+        return exportSection;
+    }
+
+    /**
+     * Creates a list of Sections that contains all axes of the chart (including
+     * X and Y axes).
+     *
+     * @return a list of Sections for each axis in this chart.
+     */
+    private List<AxisSection> buildAxisSections() {
+        final List<AxisSection> axisSections = new ArrayList<>();
+
+        axisSections.addAll(buildXAxisSections());
+        axisSections.addAll(buildYAxisSections());
+
+        return axisSections;
+    }
+
+    /**
+     * Creates a new Section for chart's X axis.
+     *
+     * @return a List that contains a Section for the X axis.
+     */
+    protected List<AxisSection> buildXAxisSections() {
+        final List<AxisSection> axisSections = new ArrayList<>();
+
+        final String identifier = "X";
+
+        final AxisSection axisSection = new AxisSection();
+        axisSection.setIdentifier(identifier);
+        axisSection.setLabel(getXAxisLabel());
+        axisSection.setFontSize(14);
+        axisSection.setFixed(false);
+
+        // XXX We are able to find better default ranges that [0,0], but the Y
+        // axes currently have no better ranges set.
+        axisSection.setUpperRange(0d);
+        axisSection.setLowerRange(0d);
+
+        axisSections.add(axisSection);
+
+        return axisSections;
+    }
+
+    /**
+     * Returns the X-Axis label of a chart.
+     *
+     * @return the X-Axis label of a chart.
+     */
+    protected final String getXAxisLabel() {
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings == null) {
+            return getDefaultXAxisLabel(this.context);
+        }
+
+        final AxisSection as = chartSettings.getAxisSection("X");
+        if (as != null) {
+            final String label = as.getLabel();
+
+            if (label != null) {
+                return label;
+            }
+        }
+
+        return getDefaultXAxisLabel(this.context);
+    }
+
+    protected abstract List<AxisSection> buildYAxisSections();
+
+    /**
+     * Returns the default X-Axis label of a chart.
+     *
+     * @param context2
+     *
+     * @return the default X-Axis label of a chart.
+     */
+    protected abstract String getDefaultXAxisLabel(final CallContext context2);
+
+    /** Generate the diagram as an image. */
+    protected final void generateImage(final CallContext context) throws IOException {
+        log.debug("ChartGenerator2.generateImage");
+
+        final JFreeChart chart = generateChart(context);
+
+        final String format = getFormat();
+        int[] size = getSize();
+
+        if (size == null)
+            size = getExportDimension();
+
+        this.context.putContextValue("chart.width", size[0]);
+        this.context.putContextValue("chart.height", size[1]);
+
+        if (format.equals(ChartExportHelper.FORMAT_PNG)) {
+            this.context.putContextValue("chart.image.format", "png");
+
+            ChartExportHelper.exportImage(this.out, chart, this.context);
+        } else if (format.equals(ChartExportHelper.FORMAT_PDF)) {
+            preparePDFContext(this.context);
+
+            ChartExportHelper.exportPDF(this.out, chart, this.context);
+        } else if (format.equals(ChartExportHelper.FORMAT_SVG)) {
+            prepareSVGContext(this.context);
+
+            ChartExportHelper.exportSVG(this.out, chart, this.context);
+        } else if (format.equals(ChartExportHelper.FORMAT_CSV)) {
+            this.context.putContextValue("chart.image.format", "csv");
+
+            ChartExportHelper.exportCSV(this.out, chart, this.context);
+        }
+    }
+
+    /**
+     * Adds a metadata sub-title to the chart if it gets exported
+     */
+    protected final void addMetadataSubtitle(final CallContext context, final JFreeChart chart) {
+        if ((!isExport() || !isExportMetadata()))
+            return;
+
+        final String version = FLYS.VERSION;
+        final String user = CalculationUtils.findArtifactUser(context, getArtifact());
+        final Locale locale = Resources.getLocale(context.getMeta());
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+        final String dateText = df.format(new Date());
+
+        final String text = Resources.getMsg(context.getMeta(), "chart.subtitle.metadata", "default", version, user, dateText);
+
+        chart.addSubtitle(new TextTitle(text));
+    }
+
+    private boolean isExportMetadata() {
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings == null)
+            return true;
+
+        final ExportSection exportSection = chartSettings.getExportSection();
+        if (exportSection == null)
+            return true;
+
+        return exportSection.getMetadata();
+    }
+
+    /**
+     * This method returns the export flag specified in the <i>request</i> document
+     * or <i>false</i> if no export is specified in <i>request</i>.
+     */
+    private boolean isExport() {
+        final Boolean export = (Boolean) XMLUtils.xpath(getRequest(), XPATH_CHART_EXPORT, XPathConstants.BOOLEAN, ArtifactNamespaceContext.INSTANCE);
+
+        return export == null ? false : export;
+    }
+
+    protected final String getRiverName() {
+        return new RiverAccess(getArtifact()).getRiver().getName();
+    }
+
+    protected final String getRiverUnit() {
+        return new RiverAccess(getArtifact()).getRiver().getWstUnit().getName();
+    }
+
+    protected final double[] getRange() {
+        final D4EArtifact flys = getArtifact();
+
+        final RangeAccess rangeAccess = new RangeAccess(flys);
+        return rangeAccess.getKmRange();
+    }
+
+    /**
+     * Returns a boolean object that determines if the chart grid should be
+     * visible or not. This information needs to be provided by <i>settings</i>,
+     * otherwise the default is true.
+     *
+     * @param settings
+     *            A ChartSettings object.
+     *
+     * @return true, if the chart grid should be visible otherwise false.
+     *
+     * @throws NullPointerException
+     *             if <i>settings</i> is null.
+     */
+    private boolean isGridVisible(final ChartSettings settings) {
+        final ChartSection cs = settings.getChartSection();
+        return cs.getDisplayGrid();
+    }
+
+    /**
+     * This method is used to determine, if the chart's legend is visible or
+     * not. If a <i>settings</i> instance is set, this instance determines the
+     * visibility otherwise, this method returns true as default if no
+     * <i>settings</i> is set.
+     *
+     * @return true, if the legend should be visible, otherwise false.
+     */
+    protected final boolean isLegendVisible() {
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings == null)
+            return true;
+
+        final LegendSection ls = chartSettings.getLegendSection();
+        return ls.getVisibility();
+    }
+
+    /**
+     * This method returns the font size for the X axis. If the font size is
+     * specified in ChartSettings (if <i>chartSettings</i> is set), this size is
+     * returned. Otherwise the default font size 12 is returned.
+     *
+     * @return the font size for the x axis.
+     */
+    protected final int getXAxisLabelFontSize() {
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings == null) {
+            return DEFAULT_FONT_SIZE;
+        }
+
+        final AxisSection as = chartSettings.getAxisSection("X");
+        final Integer fontSize = as.getFontSize();
+
+        return fontSize != null ? fontSize : DEFAULT_FONT_SIZE;
+    }
+
+    /**
+     * This method is used to determine the font size of the chart's legend. If
+     * a <i>settings</i> instance is set, this instance determines the font
+     * size, otherwise this method returns 12 as default if no <i>settings</i>
+     * is set or if it doesn't provide a legend font size.
+     *
+     * @return a legend font size.
+     */
+    private int getLegendFontSize() {
+
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings == null)
+            return DEFAULT_FONT_SIZE;
+
+        final LegendSection ls = chartSettings.getLegendSection();
+        if (ls == null)
+            return DEFAULT_FONT_SIZE;
+
+        final Integer fontSize = ls.getFontSize();
+        if (fontSize == null)
+            return DEFAULT_FONT_SIZE;
+
+        return fontSize;
+    }
+
+    /**
+     * Creates a new LegendItem with <i>name</i> and font provided by
+     * <i>createLegendLabelFont()</i>.
+     *
+     * @param theme
+     *            The theme of the chart line.
+     * @param name
+     *            The displayed name of the item.
+     *
+     * @return a new LegendItem instance.
+     */
+    protected final LegendItem createLegendItem(final ThemeDocument theme, final String name) {
+        // OPTIMIZE Pass font, parsed Theme items.
+
+        Color color = theme.parseLineColorField();
+        if (color == null)
+            color = Color.BLACK;
+
+        final LegendItem legendItem = new LegendItem(name, color);
+        legendItem.setLabelFont(createLegendLabelFont());
+        return legendItem;
+    }
+
+    /**
+     * Create new legend entries, dependent on settings.
+     *
+     * @param plot
+     *            The plot for which to modify the legend.
+     */
+    protected final void aggregateLegendEntries(final XYPlot plot) {
+
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings == null)
+            return;
+
+        final Integer threshold = chartSettings.getLegendSection().getAggregationThreshold();
+
+        final int aggrThreshold = threshold != null ? threshold.intValue() : 0;
+
+        LegendProcessor.aggregateLegendEntries(plot, aggrThreshold);
+    }
+
+    /**
+     * Creates Font (Family and size) to use when creating Legend Items. The
+     * font size depends in the return value of <i>getLegendFontSize()</i>.
+     *
+     * @return a new Font instance with <i>DEFAULT_FONT_NAME</i>.
+     */
+    private final Font createLegendLabelFont() {
+        return new Font(DEFAULT_FONT_NAME, Font.PLAIN, getLegendFontSize());
+    }
+
+    /**
+     * Adjust some Stroke/Grid parameters for <i>plot</i>. The chart
+     * <i>Settings</i> are applied in this method.
+     *
+     * @param plot
+     *            The XYPlot which is adapted.
+     */
+    protected void adjustPlot(final XYPlot plot) {
+        final Stroke gridStroke = new BasicStroke(DEFAULT_GRID_LINE_WIDTH, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 3.0f, new float[] { 3.0f }, 0.0f);
+
+        final ChartSettings cs = getChartSettings();
+        final boolean isGridVisible = cs != null ? isGridVisible(cs) : true;
+
+        plot.setDomainGridlineStroke(gridStroke);
+        plot.setDomainGridlinePaint(DEFAULT_GRID_COLOR);
+        plot.setDomainGridlinesVisible(isGridVisible);
+
+        plot.setRangeGridlineStroke(gridStroke);
+        plot.setRangeGridlinePaint(DEFAULT_GRID_COLOR);
+        plot.setRangeGridlinesVisible(isGridVisible);
+
+        plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d));
+    }
+
+    /**
+     * This helper method is used to extract the current locale from instance variable <i>context</i>.
+     *
+     * @return the current locale.
+     */
+    protected final Locale getLocale() {
+        final CallMeta meta = this.context.getMeta();
+        final PreferredLocale[] prefs = meta.getLanguages();
+
+        final int len = prefs != null ? prefs.length : 0;
+
+        final Locale[] locales = new Locale[len];
+
+        for (int i = 0; i < len; i++) {
+            locales[i] = prefs[i].getLocale();
+        }
+
+        return meta.getPreferredLocale(locales);
+    }
+
+    /**
+     * Look up \param key in i18n dictionary.
+     *
+     * @param key
+     *            key for which to find i18nd version.
+     * @param def
+     *            default, returned if lookup failed.
+     * @return value found in i18n dictionary, \param def if no value found.
+     */
+    public final String msg(final String key, final String def) {
+        return Resources.getMsg(this.context.getMeta(), key, def);
+    }
+
+    /**
+     * Look up \param key in i18n dictionary.
+     *
+     * @param key
+     *            key for which to find i18nd version.
+     * @return value found in i18n dictionary, key itself if failed.
+     */
+    public final String msg(final String key) {
+        return Resources.getMsg(this.context.getMeta(), key, key);
+    }
+
+    public final String msg(final String key, final String def, final Object... args) {
+        return Resources.getMsg(this.context.getMeta(), key, def, args);
+    }
+
+    /**
+     * Add datasets stored in instance variable <i>datasets</i> to plot.
+     * <i>datasets</i> actually stores instances of AxisDataset, so each of this
+     * datasets is mapped to a specific axis as well.
+     *
+     * @param plot
+     *            plot to add datasets to.
+     */
+    protected void addDatasets(final XYPlot plot) {
+        log.debug("addDatasets()");
+
+        // AxisDatasets are sorted, but some might be empty.
+        // Thus, generate numbering on the fly.
+        int axisIndex = 0;
+        int datasetIndex = 0;
+
+        for (final Map.Entry<Integer, AxisDataset> entry : this.datasets.entrySet()) {
+            if (!entry.getValue().isEmpty()) {
+                // Add axis and range information.
+                final AxisDataset axisDataset = entry.getValue();
+                final NumberAxis axis = createYAxis(entry.getKey());
+
+                plot.setRangeAxis(axisIndex, axis);
+
+                if (axis.getAutoRangeIncludesZero()) {
+                    axisDataset.setRange(Range.expandToInclude(axisDataset.getRange(), 0d));
+                }
+
+                setYBounds(axisIndex, expandPointRange(axisDataset.getRange()));
+
+                // Add contained datasets, mapping to axis.
+                for (final XYDataset dataset : axisDataset.getDatasets()) {
+                    try {
+                        plot.setDataset(datasetIndex, dataset);
+                        plot.mapDatasetToRangeAxis(datasetIndex, axisIndex);
+
+                        applyThemes(plot, dataset, datasetIndex, axisDataset.isArea(dataset));
+
+                        datasetIndex++;
+                    }
+                    catch (final RuntimeException re) {
+                        log.error(re);
+                    }
+                }
+
+                axisDataset.setPlotAxisIndex(axisIndex);
+                axisIndex++;
+            }
+        }
+    }
+
+    /**
+     * Create Y (range) axis for given index.
+     * Shall be implemented by subclasses.
+     */
+    protected abstract NumberAxis createYAxis(final int index);
+
+    /**
+     * @param idx
+     *            "index" of dataset/series (first dataset to be drawn has
+     *            index 0), correlates with renderer index.
+     * @param isArea
+     *            true if the series describes an area and shall be rendered
+     *            as such.
+     */
+    private void applyThemes(final XYPlot plot, final XYDataset series, final int idx, final boolean isArea) {
+        if (isArea)
+            applyAreaTheme(plot, (StyledAreaSeriesCollection) series, idx);
+        else
+            applyLineTheme(plot, series, idx);
+    }
+
+    /**
+     * Expands a given range if it collapses into one point.
+     *
+     * @param range
+     *            Range to be expanded if upper == lower bound.
+     *
+     * @return Bounds of point plus 5 percent in each direction.
+     */
+    private Bounds expandPointRange(final Range range) {
+        if (range == null) {
+            return null;
+        } else if (range.getLowerBound() == range.getUpperBound()) {
+            final Range expandedRange = ChartHelper.expandRange(range, 5d);
+            return new DoubleBounds(expandedRange.getLowerBound(), expandedRange.getUpperBound());
+        }
+
+        return new DoubleBounds(range.getLowerBound(), range.getUpperBound());
+    }
+
+    /**
+     * Creates a new instance of EnhancedLineAndShapeRenderer.
+     *
+     * @param plot
+     *            The plot which is set for the new renderer.
+     * @param idx
+     *            This value is not used in the current implementation.
+     *
+     * @return a new instance of EnhancedLineAndShapeRenderer.
+     */
+    private XYLineAndShapeRenderer createRenderer(final XYPlot plot, final int idx) {
+        log.debug("Create EnhancedLineAndShapeRenderer for idx: " + idx);
+
+        final EnhancedLineAndShapeRenderer r = new EnhancedLineAndShapeRenderer(true, false);
+
+        r.setPlot(plot);
+
+        return r;
+    }
+
+    /**
+     * This method applies the themes defined in the series itself. Therefore,
+     * <i>StyledXYSeries.applyTheme()</i> is called, which modifies the renderer
+     * for the series.
+     *
+     * @param plot
+     *            The plot.
+     * @param dataset
+     *            The XYDataset which needs to support Series objects.
+     * @param idx
+     *            The index of the renderer / dataset.
+     */
+    private void applyLineTheme(final XYPlot plot, final XYDataset dataset, final int idx) {
+        log.debug("Apply LineTheme for dataset at index: " + idx);
+
+        final LegendItemCollection lic = new LegendItemCollection();
+        final LegendItemCollection anno = plot.getFixedLegendItems();
+
+        final Font legendFont = createLegendLabelFont();
+
+        final XYLineAndShapeRenderer renderer = createRenderer(plot, idx);
+
+        for (int s = 0, num = dataset.getSeriesCount(); s < num; s++) {
+            final Series series = getSeriesOf(dataset, s);
+
+            if (series instanceof StyledSeries) {
+                final Style style = ((StyledSeries) series).getStyle();
+                style.applyTheme(renderer, s);
+            }
+
+            // special case: if there is just one single item, we need to enable
+            // points for this series, otherwise we would not see anything in
+            // the chart area.
+            if (series.getItemCount() == 1) {
+                renderer.setSeriesShapesVisible(s, true);
+            }
+
+            LegendItem legendItem = renderer.getLegendItem(idx, s);
+            if (legendItem.getLabel().endsWith(" ") || legendItem.getLabel().endsWith("interpol")) {
+                legendItem = null;
+            }
+
+            if (legendItem != null) {
+                legendItem.setLabelFont(legendFont);
+                lic.add(legendItem);
+            } else {
+                log.warn("Could not get LegentItem for renderer: " + idx + ", series-idx " + s);
+            }
+        }
+
+        if (anno != null) {
+            lic.addAll(anno);
+        }
+
+        plot.setFixedLegendItems(lic);
+
+        plot.setRenderer(idx, renderer);
+    }
+
+    /**
+     * @param plot
+     *            The plot.
+     * @param area
+     *            A StyledAreaSeriesCollection object.
+     * @param idx
+     *            The index of the dataset.
+     */
+    private final void applyAreaTheme(final XYPlot plot, final StyledAreaSeriesCollection area, final int idx) {
+        final LegendItemCollection lic = new LegendItemCollection();
+        final LegendItemCollection anno = plot.getFixedLegendItems();
+
+        final Font legendFont = createLegendLabelFont();
+
+        log.debug("Registering an 'area'renderer at idx: " + idx);
+
+        final StableXYDifferenceRenderer dRenderer = new StableXYDifferenceRenderer();
+
+        if (area.getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) {
+            dRenderer.setPositivePaint(createTransparentPaint());
+        }
+
+        plot.setRenderer(idx, dRenderer);
+
+        area.applyTheme(dRenderer);
+
+        // i18n
+        dRenderer.setAreaLabelNumberFormat(Formatter.getFormatter(this.context.getMeta(), 2, 4));
+
+        dRenderer.setAreaLabelTemplate(Resources.getMsg(this.context.getMeta(), "area.label.template", "Area=%sm2"));
+
+        final LegendItem legendItem = dRenderer.getLegendItem(idx, 0);
+        if (legendItem != null) {
+            legendItem.setLabelFont(legendFont);
+            lic.add(legendItem);
+        } else {
+            log.warn("Could not get LegentItem for renderer: " + idx + ", series-idx " + 0);
+        }
+
+        if (anno != null) {
+            lic.addAll(anno);
+        }
+
+        plot.setFixedLegendItems(lic);
+    }
+
+    /**
+     * Returns a transparently textured paint.
+     *
+     * @return a transparently textured paint.
+     */
+    private static Paint createTransparentPaint() {
+        // TODO why not use a transparent color?
+        final BufferedImage texture = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
+
+        return new TexturePaint(texture, new Rectangle2D.Double(0d, 0d, 0d, 0d));
+    }
+
+    private void preparePDFContext(final CallContext context) {
+        final int[] dimension = getExportDimension();
+
+        context.putContextValue("chart.width", dimension[0]);
+        context.putContextValue("chart.height", dimension[1]);
+        context.putContextValue("chart.marginLeft", 5f);
+        context.putContextValue("chart.marginRight", 5f);
+        context.putContextValue("chart.marginTop", 5f);
+        context.putContextValue("chart.marginBottom", 5f);
+        context.putContextValue("chart.page.format", ChartExportHelper.DEFAULT_PAGE_SIZE);
+    }
+
+    private void prepareSVGContext(final CallContext context) {
+        final int[] dimension = getExportDimension();
+
+        context.putContextValue("chart.width", dimension[0]);
+        context.putContextValue("chart.height", dimension[1]);
+        context.putContextValue("chart.encoding", ChartExportHelper.DEFAULT_ENCODING);
+    }
+
+    /**
+     * This method retrieves the chart subtitle by calling getChartSubtitle()
+     * and adds it as TextTitle to the chart.
+     * The default implementation of getChartSubtitle() returns the same
+     * as getDefaultChartSubtitle() which must be implemented by derived
+     * classes. If you want to add multiple subtitles to the chart override
+     * this method and add your subtitles manually.
+     *
+     * @param chart
+     *            The JFreeChart chart object.
+     */
+    protected void addSubtitles(final CallContext context, final JFreeChart chart) {
+        final String subtitle = getChartSubtitle(this.context);
+
+        if (subtitle != null && subtitle.length() > 0) {
+            chart.addSubtitle(new TextTitle(subtitle));
+        }
+    }
+
+    protected abstract String getChartSubtitle(CallContext context);
+
+    /**
+     * Adds a new AxisDataset which contains <i>dataset</i> at index <i>idx</i>.
+     *
+     * @param dataset
+     *            An XYDataset.
+     * @param idx
+     *            The axis index.
+     * @param visible
+     *            Determines, if the dataset should be visible or not.
+     */
+    protected final void addAxisDataset(final XYDataset dataset, final int idx, final boolean visible) {
+        if (dataset == null || idx < 0) {
+            return;
+        }
+
+        final AxisDataset axisDataset = getAxisDataset(idx);
+
+        final Bounds[] xyBounds = ChartHelper.getBounds(dataset);
+
+        if (xyBounds == null) {
+            log.warn("Skip XYDataset for Axis (invalid ranges): " + idx);
+            return;
+        }
+
+        if (visible) {
+            if (log.isDebugEnabled()) {
+                log.debug("Add new AxisDataset at index: " + idx);
+                log.debug("X extent: " + xyBounds[0]);
+                log.debug("Y extent: " + xyBounds[1]);
+            }
+
+            axisDataset.addDataset(dataset);
+        }
+
+        combineXBounds(xyBounds[0], 0);
+        combineYBounds(xyBounds[1], idx);
+    }
+
+    /**
+     * This method grants access to the AxisDatasets stored in <i>datasets</i>.
+     * If no AxisDataset exists for index <i>idx</i>, a new AxisDataset is
+     * created using <i>createAxisDataset()</i>.
+     *
+     * @param idx
+     *            The index of the desired AxisDataset.
+     *
+     * @return an existing or new AxisDataset.
+     */
+    protected final AxisDataset getAxisDataset(final int idx) {
+        AxisDataset axisDataset = this.datasets.get(idx);
+
+        if (axisDataset == null) {
+            axisDataset = createAxisDataset(idx);
+            this.datasets.put(idx, axisDataset);
+        }
+
+        return axisDataset;
+    }
+
+    /**
+     * Returns the size of a chart export as array which has been specified by
+     * the incoming request document.
+     *
+     * @return the size of a chart as [width, height] or null if no width or
+     *         height are given in the request document.
+     */
+    protected final int[] getSize() {
+        final int[] size = new int[2];
+
+        final Element sizeEl = (Element) XMLUtils.xpath(this.request, XPATH_CHART_SIZE, XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE);
+
+        if (sizeEl != null) {
+            final String uri = ArtifactNamespaceContext.NAMESPACE_URI;
+
+            final String w = sizeEl.getAttributeNS(uri, "width");
+            final String h = sizeEl.getAttributeNS(uri, "height");
+
+            if (w.length() > 0 && h.length() > 0) {
+                try {
+                    size[0] = Integer.parseInt(w);
+                    size[1] = Integer.parseInt(h);
+                }
+                catch (final NumberFormatException nfe) {
+                    log.warn("Wrong values for chart width/height.");
+                }
+            }
+        }
+
+        return size[0] > 0 && size[1] > 0 ? size : null;
+    }
+
+    /**
+     * This method returns the format specified in the <i>request</i> document
+     * or <i>DEFAULT_CHART_FORMAT</i> if no format is specified in
+     * <i>request</i>.
+     *
+     * @return the format used to export this chart.
+     */
+    private String getFormat() {
+        final String format = (String) XMLUtils.xpath(this.request, XPATH_CHART_FORMAT, XPathConstants.STRING, ArtifactNamespaceContext.INSTANCE);
+
+        return format == null || format.length() == 0 ? DEFAULT_CHART_FORMAT : format;
+    }
+
+    /**
+     * Returns the X-Axis range as String array from request document.
+     * If the (x|y)range elements are not found in request document, return
+     * null (i.e. not zoomed).
+     *
+     * @return a String array with [lower, upper], null if not in document.
+     */
+    protected final String[] getDomainAxisRangeFromRequest() {
+        final Element xrange = (Element) XMLUtils.xpath(this.request, XPATH_CHART_X_RANGE, XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE);
+
+        if (xrange == null) {
+            return null;
+        }
+
+        final String uri = ArtifactNamespaceContext.NAMESPACE_URI;
+
+        final String lower = xrange.getAttributeNS(uri, "from");
+        final String upper = xrange.getAttributeNS(uri, "to");
+
+        return new String[] { lower, upper };
+    }
+
+    /**
+     * Returns null if the (x|y)range-element was not found in
+     * request document.
+     * This usally means that the axis are not manually zoomed, i.e. showing
+     * full data extent.
+     */
+    protected final String[] getValueAxisRangeFromRequest() {
+        final Element yrange = (Element) XMLUtils.xpath(this.request, XPATH_CHART_Y_RANGE, XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE);
+
+        if (yrange == null) {
+            return null;
+        }
+
+        final String uri = ArtifactNamespaceContext.NAMESPACE_URI;
+
+        final String lower = yrange.getAttributeNS(uri, "from");
+        final String upper = yrange.getAttributeNS(uri, "to");
+
+        return new String[] { lower, upper };
+    }
+
+    /**
+     * Returns the default size of a chart export as array.
+     *
+     * @return the default size of a chart as [width, height].
+     */
+    protected final int[] getDefaultSize() {
+        return new int[] { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT };
+    }
+
+    /**
+     * This method returns the export dimension specified in ChartSettings as
+     * int array [width,height].
+     *
+     * @return an int array with [width,height].
+     */
+    private int[] getExportDimension() {
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings == null)
+            return new int[] { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT };
+
+        final ExportSection export = chartSettings.getExportSection();
+        final Integer width = export.getWidth();
+        final Integer height = export.getHeight();
+
+        if (width != null && height != null) {
+            return new int[] { width, height };
+        }
+
+        return new int[] { 600, 400 };
+    }
+
+    /**
+     * Returns the chart title provided by <i>settings</i>.
+     *
+     * @param settings
+     *            A ChartSettings object.
+     *
+     * @return the title provided by <i>settings</i> or null if no
+     *         <i>ChartSection</i> is provided by <i>settings</i>.
+     *
+     * @throws NullPointerException
+     *             if <i>settings</i> is null.
+     */
+    private String getChartTitle(final ChartSettings settings) {
+        final ChartSection cs = settings.getChartSection();
+        return cs != null ? cs.getTitle() : null;
+    }
+
+    /**
+     * Returns the chart subtitle provided by <i>settings</i>.
+     *
+     * @param settings
+     *            A ChartSettings object.
+     *
+     * @return the subtitle provided by <i>settings</i> or null if no
+     *         <i>ChartSection</i> is provided by <i>settings</i>.
+     *
+     * @throws NullPointerException
+     *             if <i>settings</i> is null.
+     */
+    protected final String getChartSubtitle(final ChartSettings settings) {
+        final ChartSection cs = settings.getChartSection();
+        return cs != null ? cs.getSubtitle() : null;
+    }
+
+    /**
+     * Returns the title of a chart. The return value depends on the existence
+     * of ChartSettings: if there are ChartSettings set, this method returns the
+     * chart title provided by those settings. Otherwise, this method returns
+     * getDefaultChartTitle().
+     *
+     * @return the title of a chart.
+     */
+    protected String getChartTitle(final CallContext context) {
+        final ChartSettings chartSettings = getChartSettings();
+
+        if (chartSettings != null) {
+            return getChartTitle(chartSettings);
+        }
+
+        return getDefaultChartTitle(context);
+    }
+
+    /**
+     * This method always returns null. Override it in subclasses that require
+     * subtitles.
+     *
+     * @return null.
+     */
+    protected String getDefaultChartSubtitle(final CallContext context) {
+        // Override this method in subclasses
+        return null;
+    }
+
+    /** Where to place the logo. */
+    protected final String logoHPlace() {
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings != null) {
+            final ChartSection cs = chartSettings.getChartSection();
+            final String place = cs.getLogoHPlacement();
+
+            return place;
+        }
+        return "center";
+    }
+
+    /** Where to place the logo. */
+    protected final String logoVPlace() {
+        final ChartSettings chartSettings = getChartSettings();
+        if (chartSettings != null) {
+            final ChartSection cs = chartSettings.getChartSection();
+            final String place = cs.getLogoVPlacement();
+
+            return place;
+        }
+        return "top";
+    }
+
+    /** Return the logo id from settings. */
+    private String showLogo(final ChartSettings chartSettings) {
+        if (chartSettings != null) {
+            final ChartSection cs = chartSettings.getChartSection();
+            final String logo = cs.getDisplayLogo();
+
+            return logo;
+        }
+        return "none";
+    }
+
+    /**
+     * This method is used to determine if a logo should be added to the plot.
+     *
+     * @return logo name (null if none).
+     */
+    protected final String showLogo() {
+        final ChartSettings chartSettings = getChartSettings();
+        return showLogo(chartSettings);
+    }
+
+    /**
+     * This method is used to determine if the resulting chart should display
+     * grid lines or not. <b>Note: this method always returns true!</b>
+     *
+     * @return true, if the chart should display grid lines, otherwise false.
+     */
+    protected final boolean isGridVisible() {
+        return true;
+    }
+
+    protected final void addAnnotationsToRenderer(final XYPlot plot) {
+
+        final AnnotationRenderer annotationRenderer = new AnnotationRenderer(getChartSettings(), this.datasets, DEFAULT_FONT_NAME);
+        annotationRenderer.addAnnotationsToRenderer(plot, this.annotations);
+
+        doAddFurtherAnnotations(plot, this.annotations);
+    }
+
+    /**
+     * Allow further annotation processing, override to implement.
+     *
+     * Does nothing by default.
+     */
+    protected void doAddFurtherAnnotations(final XYPlot plot, final List<RiverAnnotation> annotations) {
+
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,30 +11,22 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
-
 import java.text.NumberFormat;
 
-import org.w3c.dom.Document;
-
 import org.apache.log4j.Logger;
-
-import au.com.bytecode.opencsv.CSVWriter;
-
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Settings;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
-
-import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
-import org.dive4elements.artifactdatabase.state.Settings;
-
 import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
-
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.collections.D4EArtifactCollection;
-
 import org.dive4elements.river.themes.ThemeDocument;
 import org.dive4elements.river.utils.Formatter;
+import org.w3c.dom.Document;
 
+import au.com.bytecode.opencsv.CSVWriter;
 
 /**
  * Abstract exporter that implements some basic methods for exporting data of
@@ -44,7 +36,7 @@
  */
 public abstract class AbstractExporter implements OutGenerator {
 
-    /** The log used in this exporter.*/
+    /** The log used in this exporter. */
     private static Logger log = Logger.getLogger(AbstractExporter.class);
 
     /* XXX: Why does AbstractExporter do not implement FacetTypes? */
@@ -82,7 +74,7 @@
     /** The selected facet. */
     protected String facet;
 
-    /** The collection.*/
+    /** The collection. */
     protected D4EArtifactCollection collection;
 
     /** The master artifact. */
@@ -94,29 +86,38 @@
 
     private NumberFormat qFormat;
 
+    private NumberFormat meanBedHeightFormat;
+
+    private NumberFormat tkhFormat;
+
+    private NumberFormat flowDepthFormat;
+
+    private NumberFormat w2Format;
 
     /**
      * Concrete subclasses need to use this method to write their special data
      * objects into the CSV document.
      *
-     * @param writer The CSVWriter.
+     * @param writer
+     *            The CSVWriter.
      */
     protected abstract void writeCSVData(CSVWriter writer) throws IOException;
 
-
     /**
      * Write lines of informative content to CSV file.
      * Usually this will be done above the column headers from within
      * the implementation of writeCSVData in concret subclasses.
      *
-     * @param writer The CSVWriter
-     * @param infolines Array of Strings with informative content.
-     * Each will be written to a separate line prefixed with START_META_CHAR.
+     * @param writer
+     *            The CSVWriter
+     * @param infolines
+     *            Array of Strings with informative content.
+     *            Each will be written to a separate line prefixed with START_META_CHAR.
      */
-    protected void  writeCSVInfo(CSVWriter writer, String[] infolines) {
-        String[] metaline = new String[1];
+    protected void writeCSVInfo(final CSVWriter writer, final String[] infolines) {
+        final String[] metaline = new String[1];
 
-        for (String infoline: infolines) {
+        for (final String infoline : infolines) {
             metaline[0] = START_META_CHAR + " " + infoline;
             writer.writeNext(metaline);
         }
@@ -129,74 +130,66 @@
      */
     protected abstract void writePDF(OutputStream out);
 
-
     /**
      * This method enables concrete subclasses to collected its own special
      * data.
      *
-     * @param data The artifact that stores the data that has to be
-     * exported.
+     * @param data
+     *            The artifact that stores the data that has to be
+     *            exported.
      */
     protected abstract void addData(Object data);
 
-    public void setup(Object config) {
+    @Override
+    public void setup(final Object config) {
         log.debug("AbstractExporter.setup");
     }
 
-
     @Override
-    public void init(
-        String       outName,
-        Document     request,
-        OutputStream out,
-        CallContext  context
-    ) {
+    public void init(final String outName, final Document request, final OutputStream out, final CallContext context) {
         log.debug("AbstractExporter.init");
 
         this.outName = outName;
         this.request = request;
-        this.out     = out;
+        this.out = out;
         this.context = context;
     }
 
-
     @Override
-    public void setMasterArtifact(Artifact master) {
+    public void setMasterArtifact(final Artifact master) {
         this.master = master;
     }
 
-    /** Get the callcontext that this exporter has been initialized
-     * with. */
+    /**
+     * Get the callcontext that this exporter has been initialized
+     * with.
+     */
     public CallContext getCallContext() {
         return this.context;
     }
 
-
     @Override
-    public void setCollection(D4EArtifactCollection collection) {
+    public void setCollection(final D4EArtifactCollection collection) {
         this.collection = collection;
     }
 
-
     /**
      * This doOut() just collects the data of multiple artifacts. Therefore, it
      * makes use of the addData() method which enables concrete subclasses to
      * store its data on its own. The real output creation takes place in the
      * concrete generate() methods.
      *
-     * @param artifactFacet The artifact and facet.
-     * The facet to add - NOTE: the facet needs to fit to the first
-     * facet inserted into this exporter. Otherwise this artifact/facet is
-     * skipped.
-     * @param attr The attr document.
+     * @param artifactFacet
+     *            The artifact and facet.
+     *            The facet to add - NOTE: the facet needs to fit to the first
+     *            facet inserted into this exporter. Otherwise this artifact/facet is
+     *            skipped.
+     * @param attr
+     *            The attr document.
      */
     @Override
-    public void doOut(
-        ArtifactAndFacet artifactFacet,
-        ThemeDocument    attr,
-        boolean          visible
-    ) {
-        String name = artifactFacet.getFacetName();
+    public void doOut(final ArtifactAndFacet artifactFacet, final ThemeDocument attr, final boolean visible) {
+        final String name = artifactFacet.getFacetName();
 
         log.debug("AbstractExporter.doOut: " + name);
 
@@ -205,193 +198,209 @@
             return;
         }
 
-        addData(artifactFacet.getData(context));
+        addData(artifactFacet.getData(this.context));
     }
 
-
     /**
      * Generates an export based on a specified facet.
      */
     @Override
-    public void generate()
-    throws IOException
-    {
+    public void generate() throws IOException {
         log.debug("AbstractExporter.generate");
 
-        if (facet == null) {
+        if (this.facet == null) {
             throw new IOException("invalid (null) facet for exporter");
         }
 
-        if (facet.equals(FACET_CSV)) {
+        if (this.facet.equals(FACET_CSV)) {
             generateCSV();
-        }
-        else if (facet.equals(FACET_PDF)) {
+        } else if (this.facet.equals(FACET_PDF)) {
             generatePDF();
-        }
-        else {
-            throw new IOException(
-                "invalid facet for exporter: '" + facet + "'");
+        } else {
+            throw new IOException("invalid facet for exporter: '" + this.facet + "'");
         }
     }
 
-
     /**
      * Determines if the desired facet is valid for this exporter. If no facet
      * is currently set, <i>facet</i> is set.
      *
-     * @param facet The desired facet.
+     * @param facet
+     *            The desired facet.
      *
      * @return true, if <i>facet</i> is valid, otherwise false.
      */
-    protected boolean isFacetValid(String facet) {
-        log.debug("AbstractExporter.isFacetValid : "
-            + facet + " (" + getFacet() + ")" );
+    protected boolean isFacetValid(final String facet) {
+        log.debug("AbstractExporter.isFacetValid : " + facet + " (" + getFacet() + ")");
 
-        String thisFacet = getFacet();
+        final String thisFacet = getFacet();
 
         if (thisFacet == null || thisFacet.length() == 0) {
             return false;
-        }
-        else if (facet == null || facet.length() == 0) {
+        } else if (facet == null || facet.length() == 0) {
             return false;
-        }
-        else {
+        } else {
             return thisFacet.equals(facet);
         }
     }
 
-
     /**
      * Returns the name of the desired facet.
      *
      * @return the name of the desired facet.
      */
     protected String getFacet() {
-        if (facet == null) {
-            facet = getFacetFromRequest();
+        if (this.facet == null) {
+            this.facet = getFacetFromRequest();
         }
 
-        return facet;
+        return this.facet;
     }
 
-
     /**
      * Extracts the name of the requested facet from request document.
      *
      * @return the name of the requested facet.
      */
     protected String getFacetFromRequest() {
-        return XMLUtils.xpathString(
-            request, XPATH_FACET, ArtifactNamespaceContext.INSTANCE);
-    }
-
-    protected String msg(String key) {
-        return Resources.getMsg(context.getMeta(), key, key);
+        return XMLUtils.xpathString(this.request, XPATH_FACET, ArtifactNamespaceContext.INSTANCE);
     }
 
-    protected String msg(String key, String def) {
-        return Resources.getMsg(context.getMeta(), key, def);
+    protected String msg(final String key) {
+        return Resources.getMsg(this.context.getMeta(), key, key);
     }
 
-    protected String msg(String key, Object[] args) {
-        return Resources.getMsg(context.getMeta(), key, key, args);
+    protected String msg(final String key, final String def) {
+        return Resources.getMsg(this.context.getMeta(), key, def);
     }
 
-    protected String msg(String key, String def, Object[] args) {
-        return Resources.getMsg(context.getMeta(), key, def, args);
+    protected String msg(final String key, final Object[] args) {
+        return Resources.getMsg(this.context.getMeta(), key, key, args);
     }
 
+    protected String msg(final String key, final String def, final Object[] args) {
+        return Resources.getMsg(this.context.getMeta(), key, def, args);
+    }
+
+    protected String msgVarg(final String key, final Object... args) {
+        return Resources.getMsg(this.context.getMeta(), key, key, args);
+    }
+
+    /**
+     * Formats header with unit: msg [unit]
+     */
+    // TODO: REMOVE, because it has moved to ExportContextCSV
+    protected final String msgUnit(final String key, final String unit) {
+        final String msg = msg(key);
+        return String.format("%s [%s]", msg, unit);
+    }
 
     /**
      * This method starts CSV creation. It makes use of writeCSVData() which has
      * to be implemented by concrete subclasses.
      */
-    protected void generateCSV()
-    throws    IOException
-    {
+    protected void generateCSV() throws IOException {
         log.info("AbstractExporter.generateCSV");
 
-        char quote = '"';
-        char escape = '\\';
+        final char quote = '"';
+        final char escape = '\\';
 
-        CSVWriter writer = new CSVWriter(
-            new OutputStreamWriter(
-                out,
-                DEFAULT_CSV_CHARSET),
-            DEFAULT_CSV_SEPARATOR, quote, escape, "\r\n");
+        // Write BOM so excel is happy
+        final byte[] BOM = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
+        this.out.write(BOM);
+
+        final CSVWriter writer = new CSVWriter(new OutputStreamWriter(this.out, DEFAULT_CSV_CHARSET), DEFAULT_CSV_SEPARATOR, quote, escape, "\r\n");
 
         writeCSVData(writer);
 
         writer.close();
     }
 
-
     /**
      * This method starts PDF creation.
      */
-    protected void generatePDF()
-    throws    IOException
-    {
+    protected void generatePDF() throws IOException {
         log.info("AbstractExporter.generatePDF");
         writePDF(this.out);
     }
 
-
     /**
      * Returns an instance of <i>EmptySettings</i> currently!
      *
      * @return an instance of <i>EmptySettings</i>.
      */
+    @Override
     public Settings getSettings() {
         return new EmptySettings();
     }
 
-
     /**
      * This method is not implemented. Override it in subclasses if those need a
      * <i>Settings</i> object.
      */
-    public void setSettings(Settings settings) {
+    @Override
+    public void setSettings(final Settings settings) {
         // do nothing
     }
 
-
     /**
      * Returns the number formatter for kilometer values.
      *
      * @return the number formatter for kilometer values.
      */
     protected NumberFormat getKmFormatter() {
-        if (kmFormat == null) {
-            kmFormat = Formatter.getWaterlevelKM(context);
+        if (this.kmFormat == null) {
+            this.kmFormat = Formatter.getWaterlevelKM(this.context);
         }
-        return kmFormat;
+        return this.kmFormat;
     }
 
-
     /**
      * Returns the number formatter for W values.
      *
      * @return the number formatter for W values.
      */
     protected NumberFormat getWFormatter() {
-        if (wFormat == null) {
-            wFormat = Formatter.getWaterlevelW(context);
+        if (this.wFormat == null) {
+            this.wFormat = Formatter.getWaterlevelW(this.context);
         }
-        return wFormat;
+        return this.wFormat;
     }
 
-
     /**
      * Returns the number formatter for Q values.
      *
      * @return the number formatter for Q values.
      */
     protected NumberFormat getQFormatter() {
-        if (qFormat == null) {
-            qFormat = Formatter.getWaterlevelQ(context);
+        if (this.qFormat == null) {
+            this.qFormat = Formatter.getWaterlevelQ(this.context);
         }
-        return qFormat;
+        return this.qFormat;
+    }
+
+    protected final NumberFormat getMeanBedHeighFormatter() {
+        if (this.meanBedHeightFormat == null)
+            this.meanBedHeightFormat = Formatter.getMeanBedHeight(this.context);
+        return this.meanBedHeightFormat;
+    }
+
+    protected final NumberFormat getTkhFormatter() {
+        if (this.tkhFormat == null)
+            this.tkhFormat = Formatter.getTkh(this.context);
+        return this.tkhFormat;
+    }
+
+    protected final NumberFormat getFlowDepthFormatter() {
+        if (this.flowDepthFormat == null)
+            this.flowDepthFormat = Formatter.getFlowDepth(this.context);
+        return this.flowDepthFormat;
+    }
+
+    protected final NumberFormat getW2Formatter() {
+        if (this.w2Format == null)
+            this.w2Format = Formatter.getFlowDepth(this.context);
+        return this.w2Format;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/AnnotationRenderer.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,352 @@
+/** 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.exports;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.jfree.AxisDataset;
+import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation;
+import org.dive4elements.river.jfree.RiverAnnotation;
+import org.dive4elements.river.jfree.StickyAxisAnnotation;
+import org.dive4elements.river.themes.LineStyle;
+import org.dive4elements.river.themes.TextStyle;
+import org.dive4elements.river.themes.ThemeDocument;
+import org.jfree.chart.LegendItem;
+import org.jfree.chart.LegendItemCollection;
+import org.jfree.chart.annotations.XYLineAnnotation;
+import org.jfree.chart.annotations.XYTextAnnotation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYItemRenderer;
+import org.jfree.ui.TextAnchor;
+
+/**
+ * @author Gernot Belger
+ */
+public final class AnnotationRenderer {
+
+    private static final Logger log = Logger.getLogger(AnnotationRenderer.class);
+
+    private static float ANNOTATIONS_AXIS_OFFSET = 0.02f;
+
+    private final ChartSettings settings;
+
+    private final Map<Integer, AxisDataset> datasets;
+
+    private final String fontName;
+
+    public AnnotationRenderer(final ChartSettings settings, final Map<Integer, AxisDataset> datasets, final String fontName) {
+        this.settings = settings;
+        this.datasets = datasets;
+        this.fontName = fontName;
+    }
+
+    /**
+     * Add annotations (Sticky, Text and hyk zones) to a plot.
+     *
+     * @param annotations
+     *            Annotations to add
+     * @param plot
+     *            XYPlot to add annotations to.
+     * @param settings
+     *            ChartSettings object for settings.
+     * @param datasets
+     *            Map of axis index and datasets
+     */
+    public final void addAnnotationsToRenderer(final XYPlot plot, final List<RiverAnnotation> annotations) {
+        if (annotations == null || annotations.isEmpty()) {
+            log.debug("addAnnotationsToRenderer: no annotations.");
+            return;
+        }
+
+        // OPTMIMIZE: Pre-calculate positions
+        final ChartArea area = new ChartArea(plot.getDomainAxis(0), plot.getRangeAxis());
+
+        // Walk over all Annotation sets.
+        for (final RiverAnnotation fa : annotations) {
+
+            // Access text styling, if any.
+            final ThemeDocument theme = fa.getTheme();
+            TextStyle textStyle = null;
+            LineStyle lineStyle = null;
+
+            // Get Theming information and add legend item.
+            if (theme != null) {
+                textStyle = theme.parseComplexTextStyle();
+                lineStyle = theme.parseComplexLineStyle();
+                if (fa.getLabel() != null) {
+                    // Legend handling, maybe misplaced?
+                    final LegendItemCollection lic = new LegendItemCollection();
+                    LegendItemCollection old = plot.getFixedLegendItems();
+
+                    Color color = theme.parseLineColorField();
+                    if (color == null) {
+                        color = Color.BLACK;
+                    }
+
+                    Color textColor = theme.parseTextColor();
+                    if (textColor == null) {
+                        textColor = Color.BLACK;
+                    }
+
+                    final LegendItem newItem = new LegendItem(fa.getLabel(), color);
+
+                    final LegendSection ls = this.settings != null ? this.settings.getLegendSection() : null;
+
+                    final Integer size = ls != null ? ls.getFontSize() : null;
+
+                    newItem.setLabelFont(new Font(this.fontName, Font.PLAIN, size));
+
+                    newItem.setLabelPaint(textColor);
+
+                    lic.add(newItem);
+                    // (Re-)Add prior legend entries.
+                    if (old != null) {
+                        old.addAll(lic);
+                    } else {
+                        old = lic;
+                    }
+                    plot.setFixedLegendItems(old);
+                }
+            }
+
+            // The 'Sticky' Annotations (at axis, with line and text).
+            for (final StickyAxisAnnotation sta : fa.getAxisTextAnnotations()) {
+                addStickyAnnotation(sta, plot, area, lineStyle, textStyle, theme, this.datasets.get(new Integer(sta.getAxisSymbol())));
+            }
+
+            // Other Text Annotations (e.g. labels of (manual) points).
+            for (final XYTextAnnotation ta : fa.getTextAnnotations()) {
+                // Style the text.
+                if (textStyle != null) {
+                    textStyle.apply(ta);
+                }
+                ta.setY(area.above(0.05d, ta.getY()));
+                plot.getRenderer().addAnnotation(ta, org.jfree.ui.Layer.FOREGROUND);
+            }
+        }
+    }
+
+    /**
+     * Add a text and a line annotation.
+     *
+     * @param area
+     *            convenience to determine positions in plot.
+     * @param theme
+     *            (optional) theme document
+     */
+    private void addStickyAnnotation(final StickyAxisAnnotation annotation, final XYPlot plot, final ChartArea area, final LineStyle lineStyle,
+            final TextStyle textStyle, final ThemeDocument theme, final AxisDataset dataset) {
+        // OPTIMIZE pre-calculate area-related values
+        final float TEXT_OFF = 0.03f;
+
+        XYLineAnnotation lineAnnotation = null;
+        XYTextAnnotation textAnnotation = null;
+
+        final int axisIndex = annotation.getAxisSymbol();
+        XYItemRenderer renderer = null;
+        if (dataset != null && dataset.getDatasets().length > 0) {
+            renderer = plot.getRendererForDataset(dataset.getDatasets()[0]);
+        } else {
+            renderer = plot.getRenderer();
+        }
+
+        if (annotation.atX()) {
+            textAnnotation = new CollisionFreeXYTextAnnotation(annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF));
+            // OPTIMIZE externalize the calculation involving PI.
+            // textAnnotation.setRotationAngle(270f*Math.PI/180f);
+            lineAnnotation = createGroundStickAnnotation(area, annotation.getPos(), lineStyle);
+            textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
+            textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
+        } else {
+            // Stick to the "right" (opposed to left) Y-Axis.
+            if (axisIndex != 0 && plot.getRangeAxis(axisIndex) != null) {
+                // OPTIMIZE: Pass a different area to this function,
+                // do the adding to renderer outside (let this
+                // function return the annotations).
+                // Note that this path is travelled rarely.
+                textAnnotation = new CollisionFreeXYTextAnnotation(annotation.getText(), area.ofRight(TEXT_OFF), annotation.getPos());
+                textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT);
+                textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT);
+                lineAnnotation = createRightStickAnnotation(area, annotation.getPos(), lineStyle);
+
+                // hit-lines for duration curve
+                final ChartArea area2 = new ChartArea(plot.getDomainAxis(), plot.getRangeAxis(axisIndex));
+                if (!Float.isNaN(annotation.getHitPoint()) && theme != null) {
+                    // New line annotation to hit curve.
+                    if (theme.parseShowVerticalLine()) {
+                        final XYLineAnnotation hitLineAnnotation = createStickyLineAnnotation(StickyAxisAnnotation.SimpleAxis.X_AXIS, annotation.getHitPoint(),
+                                annotation.getPos(),
+                                // annotation.getHitPoint(),
+                                area2, lineStyle);
+                        renderer.addAnnotation(hitLineAnnotation, org.jfree.ui.Layer.BACKGROUND);
+                    }
+                    if (theme.parseShowHorizontalLine()) {
+                        final XYLineAnnotation lineBackAnnotation = createStickyLineAnnotation(StickyAxisAnnotation.SimpleAxis.Y_AXIS2, annotation.getPos(),
+                                annotation.getHitPoint(), area2, lineStyle);
+                        renderer.addAnnotation(lineBackAnnotation, org.jfree.ui.Layer.BACKGROUND);
+                    }
+                }
+            } else { // Stick to the left y-axis.
+                textAnnotation = new CollisionFreeXYTextAnnotation(annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos());
+                textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
+                textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
+                lineAnnotation = createLeftStickAnnotation(area, annotation.getPos(), lineStyle);
+                if (!Float.isNaN(annotation.getHitPoint()) && theme != null) {
+                    // New line annotation to hit curve.
+                    if (theme.parseShowHorizontalLine()) {
+                        final XYLineAnnotation hitLineAnnotation = createStickyLineAnnotation(StickyAxisAnnotation.SimpleAxis.Y_AXIS, annotation.getPos(),
+                                annotation.getHitPoint(), area, lineStyle);
+                        renderer.addAnnotation(hitLineAnnotation, org.jfree.ui.Layer.BACKGROUND);
+                    }
+                    if (theme.parseShowVerticalLine()) {
+                        final XYLineAnnotation lineBackAnnotation = createStickyLineAnnotation(StickyAxisAnnotation.SimpleAxis.X_AXIS, annotation.getHitPoint(),
+                                annotation.getPos(), area, lineStyle);
+                        renderer.addAnnotation(lineBackAnnotation, org.jfree.ui.Layer.BACKGROUND);
+                    }
+                }
+            }
+        }
+
+        // Style the text.
+        if (textStyle != null) {
+            textStyle.apply(textAnnotation);
+        }
+
+        // Add the Annotations to renderer.
+        renderer.addAnnotation(textAnnotation, org.jfree.ui.Layer.FOREGROUND);
+        renderer.addAnnotation(lineAnnotation, org.jfree.ui.Layer.FOREGROUND);
+    }
+
+    public final void addYAnnotationsToRenderer(final XYPlot plot, final SortedMap<Integer, RiverAnnotation> yAnnotations) {
+        final List<RiverAnnotation> annotations = new ArrayList<>();
+
+        for (final Map.Entry<Integer, RiverAnnotation> entry : yAnnotations.entrySet()) {
+            final int axis = entry.getKey();
+            final AxisDataset dataset = this.datasets.get(new Integer(axis));
+
+            if (dataset == null || dataset.getRange() == null) {
+                log.warn("No dataset available and active for axis " + axis);
+            } else {
+                final RiverAnnotation ya = entry.getValue();
+                for (final StickyAxisAnnotation sta : ya.getAxisTextAnnotations()) {
+                    sta.setAxisSymbol(axis);
+                }
+                annotations.add(ya);
+            }
+        }
+
+        addAnnotationsToRenderer(plot, annotations);
+    }
+
+    /**
+     * Create annotation that sticks to "ground" (X) axis.
+     *
+     * @param area
+     *            helper to calculate coordinates
+     * @param pos
+     *            one-dimensional position (distance from axis)
+     * @param lineStyle
+     *            the line style to use for the line.
+     */
+    private XYLineAnnotation createGroundStickAnnotation(final ChartArea area, final float pos, final LineStyle lineStyle) {
+        if (lineStyle != null)
+            return new XYLineAnnotation(pos, area.atGround(), pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET), new BasicStroke(lineStyle.getWidth()),
+                    lineStyle.getColor());
+
+        return new XYLineAnnotation(pos, area.atGround(), pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET));
+    }
+
+    /**
+     * Create annotation that sticks to the second Y axis ("right").
+     *
+     * @param area
+     *            helper to calculate coordinates
+     * @param pos
+     *            one-dimensional position (distance from axis)
+     * @param lineStyle
+     *            the line style to use for the line.
+     */
+    private XYLineAnnotation createRightStickAnnotation(final ChartArea area, final float pos, final LineStyle lineStyle) {
+        if (lineStyle != null)
+            return new XYLineAnnotation(area.atRight(), pos, area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos, new BasicStroke(lineStyle.getWidth()),
+                    lineStyle.getColor());
+
+        return new XYLineAnnotation(area.atRight(), pos, area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos);
+    }
+
+    /**
+     * Create annotation that sticks to the first Y axis ("left").
+     *
+     * @param area
+     *            helper to calculate coordinates
+     * @param pos
+     *            one-dimensional position (distance from axis)
+     * @param lineStyle
+     *            the line style to use for the line.
+     */
+    private XYLineAnnotation createLeftStickAnnotation(final ChartArea area, final float pos, final LineStyle lineStyle) {
+        if (lineStyle != null)
+            return new XYLineAnnotation(area.atLeft(), pos, area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos, new BasicStroke(lineStyle.getWidth()),
+                    lineStyle.getColor());
+
+        return new XYLineAnnotation(area.atLeft(), pos, area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos);
+    }
+
+    /**
+     * Create a line from a axis to a given point.
+     *
+     * @param axis
+     *            The "simple" axis.
+     * @param fromD1
+     *            from-location in first dimension.
+     * @param toD2
+     *            to-location in second dimension.
+     * @param area
+     *            helper to calculate offsets.
+     * @param lineStyle
+     *            optional line style.
+     */
+    public static XYLineAnnotation createStickyLineAnnotation(final StickyAxisAnnotation.SimpleAxis axis, final float fromD1, final float toD2,
+            final ChartArea area, final LineStyle lineStyle) {
+        double anchorX1 = 0d, anchorX2 = 0d, anchorY1 = 0d, anchorY2 = 0d;
+        switch (axis) {
+        case X_AXIS:
+            anchorX1 = fromD1;
+            anchorX2 = fromD1;
+            anchorY1 = area.atGround();
+            anchorY2 = toD2;
+            break;
+        case Y_AXIS:
+            anchorX1 = area.atLeft();
+            anchorX2 = toD2;
+            anchorY1 = fromD1;
+            anchorY2 = fromD1;
+            break;
+        case Y_AXIS2:
+            anchorX1 = area.atRight();
+            anchorX2 = toD2;
+            anchorY1 = fromD1;
+            anchorY2 = fromD1;
+            break;
+        }
+
+        if (lineStyle != null)
+            return new XYLineAnnotation(anchorX1, anchorY1, anchorX2, anchorY2, new BasicStroke(lineStyle.getWidth()), lineStyle.getColor());
+
+        return new XYLineAnnotation(anchorX1, anchorY1, anchorX2, anchorY2);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/AxisSection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/AxisSection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -85,8 +85,8 @@
     }
 
 
-    public Boolean isFixed() {
-        return getBooleanValue(FIXATION_ATTR);
+    public boolean isFixed() {
+        return getBooleanValue(FIXATION_ATTR, false);
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartExportFontMapper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,52 @@
+/** 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.exports;
+
+import java.awt.Font;
+import java.io.IOException;
+
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.pdf.FontMapper;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class ChartExportFontMapper implements FontMapper {
+
+    @Override
+    public Font pdfToAwt(final BaseFont font, final int size) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public BaseFont awtToPdf(final Font font) {
+        try {
+
+            if (font.isItalic()) {
+                if (font.isBold())
+                    return BaseFont.createFont("fonts/Roboto/Roboto-BoldItalic.ttf", BaseFont.IDENTITY_H, false);
+                else
+                    return BaseFont.createFont("fonts/Roboto/Roboto-Italic.ttf", BaseFont.IDENTITY_H, false);
+            } else {
+                if (font.isBold())
+                    return BaseFont.createFont("fonts/Roboto/Roboto-Bold.ttf", BaseFont.IDENTITY_H, false);
+                else
+                    return BaseFont.createFont("fonts/Roboto/Roboto-Regular.ttf", BaseFont.IDENTITY_H, false);
+            }
+        }
+        catch (DocumentException | IOException e) {
+            e.printStackTrace();
+            throw new ExceptionConverter(e);
+        }
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartExportHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,24 +10,31 @@
 
 import com.lowagie.text.Document;
 import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
 import com.lowagie.text.PageSize;
 import com.lowagie.text.Rectangle;
-
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.pdf.DefaultFontMapper;
+import com.lowagie.text.pdf.DefaultFontMapper.BaseFontParameters;
+import com.lowagie.text.pdf.FontMapper;
 import com.lowagie.text.pdf.PdfContentByte;
 import com.lowagie.text.pdf.PdfTemplate;
 import com.lowagie.text.pdf.PdfWriter;
 
+import java.awt.Font;
 import java.awt.Graphics2D;
 import java.awt.Transparency;
 
 import java.awt.geom.Rectangle2D;
-
+import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
-
+import java.text.DateFormat;
 import java.text.NumberFormat;
+import java.util.Date;
+import java.util.Locale;
 import java.util.Map;
 
 import org.jfree.chart.ChartRenderingInfo;
@@ -44,11 +51,13 @@
 import org.jfree.chart.JFreeChart;
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.data.xy.XYDataset;
-
+import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 
 import org.dive4elements.artifacts.common.utils.XMLUtils;
-
+import org.dive4elements.river.FLYS;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
 import org.dive4elements.river.jfree.XYMetaSeriesCollection;
 import org.dive4elements.river.utils.Formatter;
 
@@ -262,7 +271,10 @@
                 PdfContentByte content  = writer.getDirectContent();
 
                 PdfTemplate template = content.createTemplate(width, height);
-                Graphics2D  graphics = template.createGraphics(width, height);
+
+                final FontMapper mapper = new ChartExportFontMapper();
+                
+                final Graphics2D  graphics = template.createGraphics(width, height );
 
                 double[] origin = getCenteredAnchor(
                     marginLeft, marginRight, marginBottom, marginTop,
@@ -273,10 +285,11 @@
                     origin[0], origin[1], size[0], size[1]);
 
                 ChartRenderingInfo info = new ChartRenderingInfo();
+                chart.draw(graphics, area, info);
 
-                chart.draw(graphics, area, info);
                 graphics.dispose();
                 content.addTemplate(template, 0f, 0f);
+
             }
             finally {
                 document.close();
@@ -301,40 +314,43 @@
         CallContext context)
     {
         log.debug("export chart as CSV");
-        CSVWriter writer = null;
+        
         try {
-            writer = new CSVWriter(
+           
+            // Write BOM so excel is happy
+            final byte[] BOM = new byte[] {(byte)0xEF, (byte)0xBB, (byte)0xBF};
+            out.write(BOM);
+            
+            final CSVWriter writer = new CSVWriter(
                 new OutputStreamWriter(
                     out,
                     DEFAULT_ENCODING),
                 DEFAULT_CSV_SEPARATOR, '"', '\\', "\r\n");
+    
+            NumberFormat format = Formatter.getCSVFormatter(context);
+    
+            XYPlot plot = chart.getXYPlot();
+            int count = plot.getDatasetCount();
+            for (int i = 0; i < count; i++) {
+                XYDataset data = plot.getDataset(i);
+                int scount = data.getSeriesCount();
+                for (int j = 0; j < scount; j++) {
+                    Comparable seriesKey = data.getSeriesKey(j);
+                    log.debug("series key: " + seriesKey.toString());
+                    Map<String, String> metaData = null;
+                    if (data instanceof XYMetaSeriesCollection) {
+                        metaData = ((XYMetaSeriesCollection) data).getMetaData();
+                    }
+                    writeCSVHeader(writer, seriesKey.toString(), metaData);
+                    writeCSVData(writer, data, format);
+                }
+            }
+            writer.close();
         }
         catch(UnsupportedEncodingException uee) {
             log.warn("Wrong encoding for CSV export.");
             return;
         }
-
-        NumberFormat format = Formatter.getCSVFormatter(context);
-
-        XYPlot plot = chart.getXYPlot();
-        int count = plot.getDatasetCount();
-        for (int i = 0; i < count; i++) {
-            XYDataset data = plot.getDataset(i);
-            int scount = data.getSeriesCount();
-            for (int j = 0; j < scount; j++) {
-                Comparable seriesKey = data.getSeriesKey(j);
-                log.debug("series key: " + seriesKey.toString());
-                Map<String, String> metaData = null;
-                if (data instanceof XYMetaSeriesCollection) {
-                    metaData = ((XYMetaSeriesCollection) data).getMetaData();
-                }
-                writeCSVHeader(writer, seriesKey.toString(), metaData);
-                writeCSVData(writer, data, format);
-            }
-        }
-        try {
-            writer.close();
-        }
         catch(IOException ioe) {
             log.error("Writing CSV export failed!");
         }
@@ -445,7 +461,7 @@
      * parameters. The first value is the x point, the second value is the y
      * point.
      */
-    public static double[] getCenteredAnchor(
+    private static double[] getCenteredAnchor(
         double mLeft,      double mRight,      double mBottom, double mTop,
         double width,      double height,
         double chartWidth, double chartHeight
@@ -480,5 +496,4 @@
 
         return origin;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartExtender.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,40 @@
+/** 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.exports;
+
+import org.jfree.chart.plot.XYPlot;
+
+/**
+ * Implementors of this class can be used to tweak some very application specific behaviour within the charts.<br/>
+ * Implementations should not have a state, because they are instantiated only once.
+ *
+ * @author Gernot Belger
+ */
+public interface ChartExtender {
+
+    /**
+     * Called before {@link DiagramGenerator#autoZoom(org.jfree.chart.plot.XYPlot)} is called, allows to tweak auto zoom
+     * behavior.
+     */
+    void beforeAutoZoom(DiagramGenerator generator);
+
+    /**
+     * Called after {@link DiagramGenerator#autoZoom(org.jfree.chart.plot.XYPlot)} was called, allows to tweak auto zoom
+     * behavior.
+     */
+    void afterAutoZoom(DiagramGenerator generator);
+
+    /**
+     * Called after the complete chart is generated.
+     *
+     * @param plot
+     */
+    void afterGenerateChart(DiagramGenerator generator, XYPlot plot);
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,66 +8,18 @@
 
 package org.dive4elements.river.exports;
 
-import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
-import org.dive4elements.artifactdatabase.state.Settings;
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.ArtifactNamespaceContext;
-import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.artifacts.CallMeta;
-import org.dive4elements.artifacts.PreferredLocale;
-import org.dive4elements.artifacts.common.utils.XMLUtils;
-
-import org.dive4elements.river.artifacts.access.RiverAccess;
-import org.dive4elements.river.artifacts.access.RangeAccess;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.resources.Resources;
-import org.dive4elements.river.collections.D4EArtifactCollection;
-import org.dive4elements.river.jfree.Bounds;
-import org.dive4elements.river.jfree.DoubleBounds;
-import org.dive4elements.river.jfree.EnhancedLineAndShapeRenderer;
-import org.dive4elements.river.jfree.RiverAnnotation;
-import org.dive4elements.river.jfree.StableXYDifferenceRenderer;
-import org.dive4elements.river.jfree.Style;
-import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
-import org.dive4elements.river.jfree.StyledSeries;
-import org.dive4elements.river.jfree.AxisDataset;
-import org.dive4elements.river.themes.ThemeDocument;
-
-import java.awt.BasicStroke;
-import java.awt.Color;
 import java.awt.Font;
-import java.awt.Paint;
-import java.awt.Stroke;
-import java.awt.TexturePaint;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import javax.xml.xpath.XPathConstants;
 
-import org.apache.log4j.Logger;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.LegendItem;
-import org.jfree.chart.LegendItemCollection;
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.jfree.RiverAnnotation;
+import org.dive4elements.river.themes.ThemeDocument;
 import org.jfree.chart.axis.NumberAxis;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
-import org.jfree.chart.title.TextTitle;
 import org.jfree.data.Range;
-import org.jfree.data.general.Series;
-import org.jfree.data.xy.XYDataset;
-import org.jfree.ui.RectangleInsets;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import org.dive4elements.river.utils.Formatter;
 
 /**
  * The base class for chart creation. It should provide some basic things that
@@ -80,58 +32,7 @@
  *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public abstract class ChartGenerator implements OutGenerator {
-
-    private static Logger log = Logger.getLogger(ChartGenerator.class);
-
-    public static final int    DEFAULT_CHART_WIDTH     = 600;
-    public static final int    DEFAULT_CHART_HEIGHT    = 400;
-    public static final String DEFAULT_CHART_FORMAT    = "png";
-    public static final Color  DEFAULT_GRID_COLOR      = Color.GRAY;
-    public static final float  DEFAULT_GRID_LINE_WIDTH = 0.3f;
-    public static final int    DEFAULT_FONT_SIZE       = 12;
-    public static final String DEFAULT_FONT_NAME       = "Tahoma";
-
-    protected static float ANNOTATIONS_AXIS_OFFSET = 0.02f;
-
-    public static final String XPATH_CHART_SIZE =
-        "/art:action/art:attributes/art:size";
-
-    public static final String XPATH_CHART_FORMAT =
-        "/art:action/art:attributes/art:format/@art:value";
-
-    public static final String XPATH_CHART_X_RANGE =
-        "/art:action/art:attributes/art:xrange";
-
-    public static final String XPATH_CHART_Y_RANGE =
-        "/art:action/art:attributes/art:yrange";
-
-
-    /** The document of the incoming out() request.*/
-    protected Document request;
-
-    /** The output stream where the data should be written to.*/
-    protected OutputStream out;
-
-    /** The CallContext object.*/
-    protected CallContext context;
-
-    protected D4EArtifactCollection collection;
-
-    /** Artifact that is used to decorate the chart with meta information.*/
-    protected Artifact master;
-
-    /** The settings that should be used during output creation.*/
-    protected Settings settings;
-
-    /** Map of datasets ("index"). */
-    protected SortedMap<Integer, AxisDataset> datasets;
-
-    /** List of annotations to insert in plot. */
-    protected List<RiverAnnotation> annotations =
-        new ArrayList<RiverAnnotation>();
-
-    protected String outName;
+public abstract class ChartGenerator extends AbstractChartGenerator {
 
     /**
      * A mini interface that allows to walk over the YAXIS enums defined in
@@ -145,142 +46,8 @@
     } // end of YAxisWalker interface
 
 
-    /**
-     * Default constructor that initializes internal data structures.
-     */
-    public ChartGenerator() {
-        datasets = new TreeMap<Integer, AxisDataset>();
-    }
-
-    @Override
-    public void setup(Object config) {
-        log.debug("ChartGenerator.setup");
-    }
-
-    /**
-     * Adds annotations to list. The given annotation will be visible.
-     */
-    public void addAnnotations(RiverAnnotation annotation) {
-        annotations.add(annotation);
-    }
-
-
-    /**
-     * This method needs to be implemented by concrete subclasses to create new
-     * instances of JFreeChart.
-     *
-     * @return a new instance of a JFreeChart.
-     */
-    public abstract JFreeChart generateChart();
-
-
-    /** For every outable (i.e. facets), this function is
-     * called and handles the data accordingly. */
-    @Override
-    public abstract void doOut(
-        ArtifactAndFacet bundle,
-        ThemeDocument    attr,
-        boolean          visible);
-
-
     protected abstract YAxisWalker getYAxisWalker();
 
-
-    protected abstract Series getSeriesOf(XYDataset dataset, int idx);
-
-    /**
-     * Returns the default title of a chart.
-     *
-     * @return the default title of a chart.
-     */
-    protected abstract String getDefaultChartTitle();
-
-
-    /**
-     * Returns the default X-Axis label of a chart.
-     *
-     * @return the default X-Axis label of a chart.
-     */
-    protected abstract String getDefaultXAxisLabel();
-
-
-    /**
-     * This method is called to retrieve the default label for an Y axis at
-     * position <i>pos</i>.
-     *
-     * @param pos The position of an Y axis.
-     *
-     * @return the default Y axis label at position <i>pos</i>.
-     */
-    protected abstract String getDefaultYAxisLabel(int pos);
-
-
-    /**
-     * This method is used to create new AxisDataset instances which may differ
-     * in concrete subclasses.
-     *
-     * @param idx The index of an axis.
-     */
-    protected abstract AxisDataset createAxisDataset(int idx);
-
-
-    /**
-     * Combines the ranges of the X axis at index <i>idx</i>.
-     *
-     * @param bounds A new Bounds.
-     * @param idx The index of the X axis that should be comined with
-     * <i>range</i>.
-     */
-    protected abstract void combineXBounds(Bounds bounds, int idx);
-
-
-    /**
-     * Combines the ranges of the Y axis at index <i>idx</i>.
-     *
-     * @param bounds A new Bounds.
-     * @param index The index of the Y axis that should be comined with.
-     * <i>range</i>.
-     */
-    protected abstract void combineYBounds(Bounds bounds, int index);
-
-
-    /**
-     * This method is used to determine the ranges for axes at a given index.
-     *
-     * @param index The index of the axes at the plot.
-     *
-     * @return a Range[] with [xrange, yrange];
-     */
-    public abstract Range[] getRangesForAxis(int index);
-
-    public abstract Bounds getXBounds(int axis);
-
-    protected abstract void setXBounds(int axis, Bounds bounds);
-
-    public abstract Bounds getYBounds(int axis);
-
-    protected abstract void setYBounds(int axis, Bounds bounds);
-
-
-    /**
-     * This method retrieves the chart subtitle by calling getChartSubtitle()
-     * and adds it as TextTitle to the chart.
-     * The default implementation of getChartSubtitle() returns the same
-     * as getDefaultChartSubtitle() which must be implemented by derived
-     * classes. If you want to add multiple subtitles to the chart override
-     * this method and add your subtitles manually.
-     *
-     * @param chart The JFreeChart chart object.
-     */
-    protected void addSubtitles(JFreeChart chart) {
-        String subtitle = getChartSubtitle();
-
-        if (subtitle != null && subtitle.length() > 0) {
-            chart.addSubtitle(new TextTitle(subtitle));
-        }
-    }
-
-
     /**
      * Register annotations like MainValues for later plotting
      *
@@ -313,148 +80,21 @@
         }
     }
 
-
-    /**
-     * Generate chart.
-     */
-    @Override
-    public void generate()
-    throws IOException
-    {
-        log.debug("ChartGenerator.generate");
-
-        JFreeChart chart = generateChart();
-
-        String format = getFormat();
-        int[]  size   = getSize();
-
-        if (size == null) {
-            size = getExportDimension();
-        }
-
-        context.putContextValue("chart.width",  size[0]);
-        context.putContextValue("chart.height", size[1]);
-
-        if (format.equals(ChartExportHelper.FORMAT_PNG)) {
-            context.putContextValue("chart.image.format", "png");
-
-            ChartExportHelper.exportImage(
-                out,
-                chart,
-                context);
-        }
-        else if (format.equals(ChartExportHelper.FORMAT_PDF)) {
-            preparePDFContext(context);
-
-            ChartExportHelper.exportPDF(
-                out,
-                chart,
-                context);
-        }
-        else if (format.equals(ChartExportHelper.FORMAT_SVG)) {
-            prepareSVGContext(context);
-
-            ChartExportHelper.exportSVG(
-                out,
-                chart,
-                context);
-        }
-        else if (format.equals(ChartExportHelper.FORMAT_CSV)) {
-            context.putContextValue("chart.image.format", "csv");
-
-            ChartExportHelper.exportCSV(
-                out,
-                chart,
-                context);
-        }
-    }
-
-
     @Override
-    public void init(
-        String outName,
-        Document request,
-        OutputStream out,
-        CallContext context
-    ) {
-        log.debug("ChartGenerator.init");
-
-        this.outName = outName;
-        this.request = request;
-        this.out     = out;
-        this.context = context;
-    }
-
-
-    /** Sets the master artifact. */
-    @Override
-    public void setMasterArtifact(Artifact master) {
-        this.master = master;
-    }
-
-
-    /**
-     * Gets the master artifact.
-     * @return the master artifact.
-     */
-    public Artifact getMaster() {
-        return master;
-    }
-
-
-    /** Sets the collection. */
-    @Override
-    public void setCollection(D4EArtifactCollection collection) {
-        this.collection = collection;
+    protected void doGenerate(CallContext context, OutputStream out, String outName) throws IOException {
+        generateImage(context);
     }
 
-
-    @Override
-    public void setSettings(Settings settings) {
-        this.settings = settings;
-    }
-
-
-    /**
-     * Returns instance of <i>ChartSettings</i> with a chart specific section
-     * but with no axes settings.
-     *
-     * @return an instance of <i>ChartSettings</i>.
-     */
-    @Override
-    public Settings getSettings() {
-        if (this.settings != null) {
-            return this.settings;
-        }
-
-        ChartSettings settings = new ChartSettings();
-
-        ChartSection  chartSection  = buildChartSection();
-        LegendSection legendSection = buildLegendSection();
-        ExportSection exportSection = buildExportSection();
-
-        settings.setChartSection(chartSection);
-        settings.setLegendSection(legendSection);
-        settings.setExportSection(exportSection);
-
-        List<AxisSection> axisSections = buildAxisSections();
-        for (AxisSection axisSection: axisSections) {
-            settings.addAxisSection(axisSection);
-        }
-
-        return settings;
-    }
-
-
     /**
      * Creates a new <i>ChartSection</i>.
      *
      * @return a new <i>ChartSection</i>.
      */
-    protected ChartSection buildChartSection() {
+    @Override
+    protected ChartSection buildChartSection(final CallContext context) {
         ChartSection chartSection = new ChartSection();
-        chartSection.setTitle(getChartTitle());
-        chartSection.setSubtitle(getChartSubtitle());
+        chartSection.setTitle(getChartTitle(context));
+        chartSection.setSubtitle(getChartSubtitle(context));
         chartSection.setDisplayGrid(isGridVisible());
         chartSection.setDisplayLogo(showLogo());
         chartSection.setLogoVPlacement(logoVPlace());
@@ -462,78 +102,6 @@
         return chartSection;
     }
 
-
-    /**
-     * Creates a new <i>LegendSection</i>.
-     *
-     * @return a new <i>LegendSection</i>.
-     */
-    protected LegendSection buildLegendSection() {
-        LegendSection legendSection = new LegendSection();
-        legendSection.setVisibility(isLegendVisible());
-        legendSection.setFontSize(getLegendFontSize());
-        legendSection.setAggregationThreshold(10);
-        return legendSection;
-    }
-
-
-    /**
-     * Creates a new <i>ExportSection</i> with default values <b>WIDTH=600</b>
-     * and <b>HEIGHT=400</b>.
-     *
-     * @return a new <i>ExportSection</i>.
-     */
-    protected ExportSection buildExportSection() {
-        ExportSection exportSection = new ExportSection();
-        exportSection.setWidth(600);
-        exportSection.setHeight(400);
-        return exportSection;
-    }
-
-
-    /**
-     * Create list of Sections that contains all axes of the chart (including
-     * X and Y axes).
-     *
-     * @return a list of Sections for each axis in this chart.
-     */
-    protected List<AxisSection> buildAxisSections() {
-        List<AxisSection> axisSections = new ArrayList<AxisSection>();
-
-        axisSections.addAll(buildXAxisSections());
-        axisSections.addAll(buildYAxisSections());
-
-        return axisSections;
-    }
-
-
-    /**
-     * Creates a new Section for chart's X axis.
-     *
-     * @return a List that contains a Section for the X axis.
-     */
-    protected List<AxisSection> buildXAxisSections() {
-        List<AxisSection> axisSections = new ArrayList<AxisSection>();
-
-        String identifier = "X";
-
-        AxisSection axisSection = new AxisSection();
-        axisSection.setIdentifier(identifier);
-        axisSection.setLabel(getXAxisLabel());
-        axisSection.setFontSize(14);
-        axisSection.setFixed(false);
-
-        // XXX We are able to find better default ranges that [0,0], but the Y
-        // axes currently have no better ranges set.
-        axisSection.setUpperRange(0d);
-        axisSection.setLowerRange(0d);
-
-        axisSections.add(axisSection);
-
-        return axisSections;
-    }
-
-
     /**
      * Creates a list of Section for the chart's Y axes. This method makes use
      * of <i>getYAxisWalker</i> to be able to access all Y axes defined in
@@ -541,8 +109,9 @@
      *
      * @return a list of Y axis sections.
      */
-    protected List<AxisSection> buildYAxisSections() {
-        List<AxisSection> axisSections = new ArrayList<AxisSection>();
+    @Override
+    protected final List<AxisSection> buildYAxisSections() {
+        List<AxisSection> axisSections = new ArrayList<>();
 
         YAxisWalker walker = getYAxisWalker();
         for (int i = 0, n = walker.length(); i < n; i++) {
@@ -565,127 +134,6 @@
         return axisSections;
     }
 
-
-    /**
-     * Returns the <i>settings</i> as <i>ChartSettings</i>.
-     *
-     * @return the <i>settings</i> as <i>ChartSettings</i> or null, if
-     * <i>settings</i> is not an instance of <i>ChartSettings</i>.
-     */
-    public ChartSettings getChartSettings() {
-        if (settings instanceof ChartSettings) {
-            return (ChartSettings) settings;
-        }
-
-        return null;
-    }
-
-
-    /**
-     * Returns the chart title provided by <i>settings</i>.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return the title provided by <i>settings</i> or null if no
-     * <i>ChartSection</i> is provided by <i>settings</i>.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public String getChartTitle(ChartSettings settings) {
-        ChartSection cs = settings.getChartSection();
-        return cs != null ? cs.getTitle() : null;
-    }
-
-
-    /**
-     * Returns the chart subtitle provided by <i>settings</i>.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return the subtitle provided by <i>settings</i> or null if no
-     * <i>ChartSection</i> is provided by <i>settings</i>.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public String getChartSubtitle(ChartSettings settings) {
-        ChartSection cs = settings.getChartSection();
-        return cs != null ? cs.getSubtitle() : null;
-    }
-
-
-    /**
-     * Returns a boolean object that determines if the chart grid should be
-     * visible or not. This information needs to be provided by <i>settings</i>,
-     * otherweise the default is true.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return true, if the chart grid should be visible otherwise false.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public boolean isGridVisible(ChartSettings settings) {
-        ChartSection     cs = settings.getChartSection();
-        Boolean displayGrid = cs.getDisplayGrid();
-
-        return displayGrid != null ? displayGrid : true;
-    }
-
-
-    /**
-     * Returns a boolean object that determines if the chart legend should be
-     * visible or not. This information needs to be provided by <i>settings</i>,
-     * otherwise the default is true.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return true, if the chart legend should be visible otherwise false.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public boolean isLegendVisible(ChartSettings settings) {
-        LegendSection      ls = settings.getLegendSection();
-        Boolean displayLegend = ls.getVisibility();
-
-        return displayLegend != null ? displayLegend : true;
-    }
-
-
-    /**
-     * Returns the legend font size specified in <i>settings</i> or null if no
-     * <i>LegendSection</i> is provided by <i>settings</i>.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return the legend font size or null.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public Integer getLegendFontSize(ChartSettings settings) {
-        LegendSection ls = settings.getLegendSection();
-        return ls != null ? ls.getFontSize() : null;
-    }
-
-
-    /**
-     * Returns the title of a chart. The return value depends on the existence
-     * of ChartSettings: if there are ChartSettings set, this method returns the
-     * chart title provided by those settings. Otherwise, this method returns
-     * getDefaultChartTitle().
-     *
-     * @return the title of a chart.
-     */
-    protected String getChartTitle() {
-        ChartSettings chartSettings = getChartSettings();
-
-        if (chartSettings != null) {
-            return getChartTitle(chartSettings);
-        }
-
-        return getDefaultChartTitle();
-    }
-
-
     /**
      * Returns the subtitle of a chart. The return value depends on the
      * existence of ChartSettings: if there are ChartSettings set, this method
@@ -694,171 +142,16 @@
      *
      * @return the subtitle of a chart.
      */
-    protected String getChartSubtitle() {
+    @Override
+    protected String getChartSubtitle(final CallContext context) {
         ChartSettings chartSettings = getChartSettings();
 
-        if (chartSettings != null) {
+        if (chartSettings != null) 
             return getChartSubtitle(chartSettings);
-        }
-
-        return getDefaultChartSubtitle();
-    }
-
-
-    /**
-     * This method always returns null. Override it in subclasses that require
-     * subtitles.
-     *
-     * @return null.
-     */
-    protected String getDefaultChartSubtitle() {
-        // Override this method in subclasses
-        return null;
-    }
-
-
-    /**
-     * This method is used to determine, if the chart's legend is visible or
-     * not. If a <i>settings</i> instance is set, this instance determines the
-     * visibility otherwise, this method returns true as default if no
-     * <i>settings</i> is set.
-     *
-     * @return true, if the legend should be visible, otherwise false.
-     */
-    protected boolean isLegendVisible() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            return isLegendVisible(chartSettings);
-        }
-
-        return true;
-    }
-
-
-    /** Where to place the logo. */
-    protected String logoHPlace() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            ChartSection cs    = chartSettings.getChartSection();
-            String       place = cs.getLogoHPlacement();
-
-            return place;
-        }
-        return "center";
-    }
-
-
-    /** Where to place the logo. */
-    protected String logoVPlace() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            ChartSection cs    = chartSettings.getChartSection();
-            String       place = cs.getLogoVPlacement();
-
-            return place;
-        }
-        return "top";
-    }
-
-
-    /** Return the logo id from settings. */
-    protected String showLogo(ChartSettings chartSettings) {
-        if (chartSettings != null) {
-            ChartSection cs   = chartSettings.getChartSection();
-            String       logo = cs.getDisplayLogo();
-
-            return logo;
-        }
-        return "none";
-    }
-
 
-    /**
-     * This method is used to determine if a logo should be added to the plot.
-     *
-     * @return logo name (null if none).
-     */
-    protected String showLogo() {
-        ChartSettings chartSettings = getChartSettings();
-        return showLogo(chartSettings);
-    }
-
-
-    /**
-     * This method is used to determine the font size of the chart's legend. If
-     * a <i>settings</i> instance is set, this instance determines the font
-     * size, otherwise this method returns 12 as default if no <i>settings</i>
-     * is set or if it doesn't provide a legend font size.
-     *
-     * @return a legend font size.
-     */
-    protected int getLegendFontSize() {
-        Integer fontSize = null;
-
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            fontSize = getLegendFontSize(chartSettings);
-        }
-
-        return fontSize != null ? fontSize : DEFAULT_FONT_SIZE;
-    }
-
-
-    /**
-     * This method is used to determine if the resulting chart should display
-     * grid lines or not. <b>Note: this method always returns true!</b>
-     *
-     * @return true, if the chart should display grid lines, otherwise false.
-     */
-    protected boolean isGridVisible() {
-        return true;
+        return getDefaultChartSubtitle(context);
     }
 
-
-    /**
-     * Returns the X-Axis label of a chart.
-     *
-     * @return the X-Axis label of a chart.
-     */
-    protected String getXAxisLabel() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings == null) {
-            return getDefaultXAxisLabel();
-        }
-
-        AxisSection as = chartSettings.getAxisSection("X");
-        if (as != null) {
-            String label = as.getLabel();
-
-            if (label != null) {
-                return label;
-            }
-        }
-
-        return getDefaultXAxisLabel();
-    }
-
-
-    /**
-     * This method returns the font size for the X axis. If the font size is
-     * specified in ChartSettings (if <i>chartSettings</i> is set), this size is
-     * returned. Otherwise the default font size 12 is returned.
-     *
-     * @return the font size for the x axis.
-     */
-    protected int getXAxisLabelFontSize() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings == null) {
-            return DEFAULT_FONT_SIZE;
-        }
-
-        AxisSection   as = chartSettings.getAxisSection("X");
-        Integer fontSize = as.getFontSize();
-
-        return fontSize != null ? fontSize : DEFAULT_FONT_SIZE;
-    }
-
-
     /**
      * This method returns the font size for an Y axis. If the font size is
      * specified in ChartSettings (if <i>chartSettings</i> is set), this size is
@@ -883,31 +176,6 @@
         return fontSize != null ? fontSize : DEFAULT_FONT_SIZE;
     }
 
-
-    /**
-     * This method returns the export dimension specified in ChartSettings as
-     * int array [width,height].
-     *
-     * @return an int array with [width,height].
-     */
-    protected int[] getExportDimension() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings == null) {
-            return new int[] { 600, 400 };
-        }
-
-        ExportSection export = chartSettings.getExportSection();
-        Integer width  = export.getWidth();
-        Integer height = export.getHeight();
-
-        if (width != null && height != null) {
-            return new int[] { width, height };
-        }
-
-        return new int[] { 600, 400 };
-    }
-
-
     /**
      * Returns the Y-Axis label of a chart at position <i>pos</i>.
      *
@@ -931,7 +199,17 @@
 
         return getDefaultYAxisLabel(pos);
     }
-
+    
+    /**
+     * This method is called to retrieve the default label for an Y axis at
+     * position <i>pos</i>.
+     *
+     * @param pos
+     *            The position of an Y axis.
+     *
+     * @return the default Y axis label at position <i>pos</i>.
+     */
+    protected abstract String getDefaultYAxisLabel(int pos);
 
     /**
      * This method searches for a specific axis in the <i>settings</i> if
@@ -956,9 +234,7 @@
             return null;
         }
 
-        Boolean fixed = as.isFixed();
-
-        if (fixed != null && fixed) {
+        if (as.isFixed()) {
 
             /* Only time series charts have time ranges so prefer those. */
             if (axisId.equals("X")) {
@@ -986,505 +262,6 @@
         return null;
     }
 
-
-    /**
-     * Adds a new AxisDataset which contains <i>dataset</i> at index <i>idx</i>.
-     *
-     * @param dataset An XYDataset.
-     * @param idx The axis index.
-     * @param visible Determines, if the dataset should be visible or not.
-     */
-    public void addAxisDataset(XYDataset dataset, int idx, boolean visible) {
-        if (dataset == null || idx < 0) {
-            return;
-        }
-
-        AxisDataset axisDataset = getAxisDataset(idx);
-
-        Bounds[] xyBounds = ChartHelper.getBounds(dataset);
-
-        if (xyBounds == null) {
-            log.warn("Skip XYDataset for Axis (invalid ranges): " + idx);
-            return;
-        }
-
-        if (visible) {
-            if (log.isDebugEnabled()) {
-                log.debug("Add new AxisDataset at index: " + idx);
-                log.debug("X extent: " + xyBounds[0]);
-                log.debug("Y extent: " + xyBounds[1]);
-            }
-
-            axisDataset.addDataset(dataset);
-        }
-
-        combineXBounds(xyBounds[0], 0);
-        combineYBounds(xyBounds[1], idx);
-    }
-
-
-    /**
-     * This method grants access to the AxisDatasets stored in <i>datasets</i>.
-     * If no AxisDataset exists for index <i>idx</i>, a new AxisDataset is
-     * created using <i>createAxisDataset()</i>.
-     *
-     * @param idx The index of the desired AxisDataset.
-     *
-     * @return an existing or new AxisDataset.
-     */
-    public AxisDataset getAxisDataset(int idx) {
-        AxisDataset axisDataset = datasets.get(idx);
-
-        if (axisDataset == null) {
-            axisDataset = createAxisDataset(idx);
-            datasets.put(idx, axisDataset);
-        }
-
-        return axisDataset;
-    }
-
-
-    /**
-     * Adjust some Stroke/Grid parameters for <i>plot</i>. The chart
-     * <i>Settings</i> are applied in this method.
-     *
-     * @param plot The XYPlot which is adapted.
-     */
-    protected void adjustPlot(XYPlot plot) {
-        Stroke gridStroke = new BasicStroke(
-            DEFAULT_GRID_LINE_WIDTH,
-            BasicStroke.CAP_BUTT,
-            BasicStroke.JOIN_MITER,
-            3.0f,
-            new float[] { 3.0f },
-            0.0f);
-
-        ChartSettings      cs = getChartSettings();
-        boolean isGridVisible = cs != null ? isGridVisible(cs) : true;
-
-        plot.setDomainGridlineStroke(gridStroke);
-        plot.setDomainGridlinePaint(DEFAULT_GRID_COLOR);
-        plot.setDomainGridlinesVisible(isGridVisible);
-
-        plot.setRangeGridlineStroke(gridStroke);
-        plot.setRangeGridlinePaint(DEFAULT_GRID_COLOR);
-        plot.setRangeGridlinesVisible(isGridVisible);
-
-        plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d));
-    }
-
-
-    /**
-     * This helper mehtod is used to extract the current locale from instance
-     * vairable <i>context</i>.
-     *
-     * @return the current locale.
-     */
-    protected Locale getLocale() {
-        CallMeta           meta = context.getMeta();
-        PreferredLocale[] prefs = meta.getLanguages();
-
-        int len = prefs != null ? prefs.length : 0;
-
-        Locale[] locales = new Locale[len];
-
-        for (int i = 0; i < len; i++) {
-            locales[i] = prefs[i].getLocale();
-        }
-
-        return meta.getPreferredLocale(locales);
-    }
-
-
-    /**
-     * Look up \param key in i18n dictionary.
-     * @param key key for which to find i18nd version.
-     * @param def default, returned if lookup failed.
-     * @return value found in i18n dictionary, \param def if no value found.
-     */
-    protected String msg(String key, String def) {
-        return Resources.getMsg(context.getMeta(), key, def);
-    }
-
-    /**
-     * Look up \param key in i18n dictionary.
-     * @param key key for which to find i18nd version.
-     * @return value found in i18n dictionary, key itself if failed.
-     */
-    protected String msg(String key) {
-        return Resources.getMsg(context.getMeta(), key, key);
-    }
-
-    protected String msg(String key, Object[] args) {
-        return Resources.getMsg(context.getMeta(), key, key, args);
-    }
-
-    protected String msg(String key, String def, Object[] args) {
-        return Resources.getMsg(context.getMeta(), key, def, args);
-    }
-
-
-    protected String getRiverName() {
-        return new RiverAccess((D4EArtifact)master).getRiver().getName();
-    }
-
-    protected String getRiverUnit() {
-        return new RiverAccess((D4EArtifact)master).getRiver()
-            .getWstUnit().getName();
-    }
-
-    protected double[] getRange() {
-        D4EArtifact flys = (D4EArtifact) master;
-
-        RangeAccess rangeAccess = new RangeAccess(flys);
-        return rangeAccess.getKmRange();
-    }
-
-
-    /**
-     * Returns the size of a chart export as array which has been specified by
-     * the incoming request document.
-     *
-     * @return the size of a chart as [width, height] or null if no width or
-     * height are given in the request document.
-     */
-    protected int[] getSize() {
-        int[] size = new int[2];
-
-        Element sizeEl = (Element)XMLUtils.xpath(
-            request,
-            XPATH_CHART_SIZE,
-            XPathConstants.NODE,
-            ArtifactNamespaceContext.INSTANCE);
-
-        if (sizeEl != null) {
-            String uri = ArtifactNamespaceContext.NAMESPACE_URI;
-
-            String w = sizeEl.getAttributeNS(uri, "width");
-            String h = sizeEl.getAttributeNS(uri, "height");
-
-            if (w.length() > 0 && h.length() > 0) {
-                try {
-                    size[0] = Integer.parseInt(w);
-                    size[1] = Integer.parseInt(h);
-                }
-                catch (NumberFormatException nfe) {
-                    log.warn("Wrong values for chart width/height.");
-                }
-            }
-        }
-
-        return size[0] > 0 && size[1] > 0 ? size : null;
-    }
-
-
-    /**
-     * This method returns the format specified in the <i>request</i> document
-     * or <i>DEFAULT_CHART_FORMAT</i> if no format is specified in
-     * <i>request</i>.
-     *
-     * @return the format used to export this chart.
-     */
-    protected String getFormat() {
-        String format = (String) XMLUtils.xpath(
-            request,
-            XPATH_CHART_FORMAT,
-            XPathConstants.STRING,
-            ArtifactNamespaceContext.INSTANCE);
-
-        return format == null || format.length() == 0
-            ? DEFAULT_CHART_FORMAT
-            : format;
-    }
-
-
-    /**
-     * Returns the X-Axis range as String array from request document.
-     * If the (x|y)range elements are not found in request document, return
-     * null (i.e. not zoomed).
-     *
-     * @return a String array with [lower, upper], null if not in document.
-     */
-    protected String[] getDomainAxisRangeFromRequest() {
-        Element xrange = (Element)XMLUtils.xpath(
-            request,
-            XPATH_CHART_X_RANGE,
-            XPathConstants.NODE,
-            ArtifactNamespaceContext.INSTANCE);
-
-        if (xrange == null) {
-            return null;
-        }
-
-        String uri = ArtifactNamespaceContext.NAMESPACE_URI;
-
-        String lower = xrange.getAttributeNS(uri, "from");
-        String upper = xrange.getAttributeNS(uri, "to");
-
-        return new String[] { lower, upper };
-    }
-
-
-    /** Returns null if the (x|y)range-element was not found in
-     * request document.
-     * This usally means that the axis are not manually zoomed, i.e. showing
-     * full data extent. */
-    protected String[] getValueAxisRangeFromRequest() {
-        Element yrange = (Element)XMLUtils.xpath(
-            request,
-            XPATH_CHART_Y_RANGE,
-            XPathConstants.NODE,
-            ArtifactNamespaceContext.INSTANCE);
-
-        if (yrange == null) {
-            return null;
-        }
-
-
-        String uri = ArtifactNamespaceContext.NAMESPACE_URI;
-
-        String lower = yrange.getAttributeNS(uri, "from");
-        String upper = yrange.getAttributeNS(uri, "to");
-
-        return new String[] { lower, upper };
-    }
-
-
-    /**
-     * Returns the default size of a chart export as array.
-     *
-     * @return the default size of a chart as [width, height].
-     */
-    protected int[] getDefaultSize() {
-        return new int[] { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT };
-    }
-
-
-    /**
-     * Add datasets stored in instance variable <i>datasets</i> to plot.
-     * <i>datasets</i> actually stores instances of AxisDataset, so each of this
-     * datasets is mapped to a specific axis as well.
-     *
-     * @param plot plot to add datasets to.
-     */
-    protected void addDatasets(XYPlot plot) {
-        log.debug("addDatasets()");
-
-        // AxisDatasets are sorted, but some might be empty.
-        // Thus, generate numbering on the fly.
-        int axisIndex    = 0;
-        int datasetIndex = 0;
-
-        for (Map.Entry<Integer, AxisDataset> entry: datasets.entrySet()) {
-            if (!entry.getValue().isEmpty()) {
-                // Add axis and range information.
-                AxisDataset axisDataset = entry.getValue();
-                NumberAxis  axis        = createYAxis(entry.getKey());
-
-                plot.setRangeAxis(axisIndex, axis);
-
-                if (axis.getAutoRangeIncludesZero()) {
-                    axisDataset.setRange(
-                        Range.expandToInclude(axisDataset.getRange(), 0d));
-                }
-
-                setYBounds(
-                    axisIndex, expandPointRange(axisDataset.getRange()));
-
-                // Add contained datasets, mapping to axis.
-                for (XYDataset dataset: axisDataset.getDatasets()) {
-                    plot.setDataset(datasetIndex, dataset);
-                    plot.mapDatasetToRangeAxis(datasetIndex, axisIndex);
-
-                    applyThemes(plot, dataset,
-                        datasetIndex,
-                        axisDataset.isArea(dataset));
-
-                    datasetIndex++;
-                }
-
-                axisDataset.setPlotAxisIndex(axisIndex);
-                axisIndex++;
-            }
-        }
-    }
-
-
-    /**
-     * @param idx "index" of dataset/series (first dataset to be drawn has
-     *            index 0), correlates with renderer index.
-     * @param isArea true if the series describes an area and shall be rendered
-     *                as such.
-     */
-    protected void applyThemes(
-        XYPlot    plot,
-        XYDataset series,
-        int       idx,
-        boolean   isArea
-    ) {
-        if (isArea) {
-            applyAreaTheme(plot, (StyledAreaSeriesCollection) series, idx);
-        }
-        else {
-            applyLineTheme(plot, series, idx);
-        }
-    }
-
-
-    /**
-     * This method applies the themes defined in the series itself. Therefore,
-     * <i>StyledXYSeries.applyTheme()</i> is called, which modifies the renderer
-     * for the series.
-     *
-     * @param plot The plot.
-     * @param dataset The XYDataset which needs to support Series objects.
-     * @param idx The index of the renderer / dataset.
-     */
-    protected void applyLineTheme(XYPlot plot, XYDataset dataset, int idx) {
-        log.debug("Apply LineTheme for dataset at index: " + idx);
-
-        LegendItemCollection lic  = new LegendItemCollection();
-        LegendItemCollection anno = plot.getFixedLegendItems();
-
-        Font legendFont = createLegendLabelFont();
-
-        XYLineAndShapeRenderer renderer = createRenderer(plot, idx);
-
-        for (int s = 0, num = dataset.getSeriesCount(); s < num; s++) {
-            Series series = getSeriesOf(dataset, s);
-
-            if (series instanceof StyledSeries) {
-                Style style = ((StyledSeries) series).getStyle();
-                style.applyTheme(renderer, s);
-            }
-
-            // special case: if there is just one single item, we need to enable
-            // points for this series, otherwise we would not see anything in
-            // the chart area.
-            if (series.getItemCount() == 1) {
-                renderer.setSeriesShapesVisible(s, true);
-            }
-
-            LegendItem legendItem = renderer.getLegendItem(idx, s);
-            if (legendItem.getLabel().endsWith(" ") ||
-                legendItem.getLabel().endsWith("interpol")) {
-                legendItem = null;
-            }
-
-            if (legendItem != null) {
-                legendItem.setLabelFont(legendFont);
-                lic.add(legendItem);
-            }
-            else {
-                log.warn("Could not get LegentItem for renderer: "
-                    + idx + ", series-idx " + s);
-            }
-        }
-
-        if (anno != null) {
-            lic.addAll(anno);
-        }
-
-        plot.setFixedLegendItems(lic);
-
-        plot.setRenderer(idx, renderer);
-    }
-
-
-    /**
-     * @param plot The plot.
-     * @param area A StyledAreaSeriesCollection object.
-     * @param idx The index of the dataset.
-     */
-    protected void applyAreaTheme(
-        XYPlot                     plot,
-        StyledAreaSeriesCollection area,
-        int                        idx
-    ) {
-        LegendItemCollection lic  = new LegendItemCollection();
-        LegendItemCollection anno = plot.getFixedLegendItems();
-
-        Font legendFont = createLegendLabelFont();
-
-        log.debug("Registering an 'area'renderer at idx: " + idx);
-
-        StableXYDifferenceRenderer dRenderer =
-            new StableXYDifferenceRenderer();
-
-        if (area.getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) {
-            dRenderer.setPositivePaint(createTransparentPaint());
-        }
-
-        plot.setRenderer(idx, dRenderer);
-
-        area.applyTheme(dRenderer);
-
-        // i18n
-        dRenderer.setAreaLabelNumberFormat(
-            Formatter.getFormatter(context.getMeta(), 2, 4));
-
-        dRenderer.setAreaLabelTemplate(Resources.getMsg(
-            context.getMeta(), "area.label.template", "Area=%sm2"));
-
-        LegendItem legendItem = dRenderer.getLegendItem(idx, 0);
-        if (legendItem != null) {
-            legendItem.setLabelFont(legendFont);
-            lic.add(legendItem);
-        }
-        else {
-            log.warn("Could not get LegentItem for renderer: "
-                + idx + ", series-idx " + 0);
-        }
-
-        if (anno != null) {
-            lic.addAll(anno);
-        }
-
-        plot.setFixedLegendItems(lic);
-    }
-
-
-    /**
-     * Expands a given range if it collapses into one point.
-     *
-     * @param range Range to be expanded if upper == lower bound.
-     *
-     * @return Bounds of point plus 5 percent in each direction.
-     */
-    private Bounds expandPointRange(Range range) {
-        if (range == null) {
-            return null;
-        }
-        else if (range.getLowerBound() == range.getUpperBound()) {
-            Range expandedRange = ChartHelper.expandRange(range, 5d);
-            return new DoubleBounds(
-                expandedRange.getLowerBound(), expandedRange.getUpperBound());
-        }
-
-        return new DoubleBounds(range.getLowerBound(), range.getUpperBound());
-    }
-
-
-    /**
-     * Creates a new instance of EnhancedLineAndShapeRenderer.
-     *
-     * @param plot The plot which is set for the new renderer.
-     * @param idx This value is not used in the current implementation.
-     *
-     * @return a new instance of EnhancedLineAndShapeRenderer.
-     */
-    protected XYLineAndShapeRenderer createRenderer(XYPlot plot, int idx) {
-        log.debug("Create EnhancedLineAndShapeRenderer for idx: " + idx);
-
-        EnhancedLineAndShapeRenderer r =
-            new EnhancedLineAndShapeRenderer(true, false);
-
-        r.setPlot(plot);
-
-        return r;
-    }
-
-
     /**
      * Creates a new instance of <i>IdentifiableNumberAxis</i>.
      *
@@ -1493,17 +270,17 @@
      *
      * @return an instance of IdentifiableNumberAxis.
      */
-    protected NumberAxis createNumberAxis(int idx, String label) {
+    protected final NumberAxis createNumberAxis(int idx, String label) {
         YAxisWalker walker = getYAxisWalker();
 
         return new IdentifiableNumberAxis(walker.getId(idx), label);
     }
 
-
     /**
      * Create Y (range) axis for given index.
      * Shall be overriden by subclasses.
      */
+    @Override
     protected NumberAxis createYAxis(int index) {
         YAxisWalker walker = getYAxisWalker();
 
@@ -1520,115 +297,11 @@
         axis.setLabelFont(labelFont);
         axis.setTickLabelFont(labelFont);
 
+        // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+        axis.setLowerMargin(0);
+        axis.setUpperMargin(0);
+        
         return axis;
     }
-
-
-    /**
-     * Creates a new LegendItem with <i>name</i> and font provided by
-     * <i>createLegendLabelFont()</i>.
-     *
-     * @param theme The theme of the chart line.
-     * @param name The displayed name of the item.
-     *
-     * @return a new LegendItem instance.
-     */
-    public LegendItem createLegendItem(ThemeDocument theme, String name) {
-        // OPTIMIZE Pass font, parsed Theme items.
-
-        Color color = theme.parseLineColorField();
-        if (color == null) {
-            color = Color.BLACK;
-        }
-
-        LegendItem legendItem  = new LegendItem(name, color);
-
-        legendItem.setLabelFont(createLegendLabelFont());
-        return legendItem;
-    }
-
-
-    /**
-     * Creates Font (Family and size) to use when creating Legend Items. The
-     * font size depends in the return value of <i>getLegendFontSize()</i>.
-     *
-     * @return a new Font instance with <i>DEFAULT_FONT_NAME</i>.
-     */
-    protected Font createLegendLabelFont() {
-        return new Font(
-            DEFAULT_FONT_NAME,
-            Font.PLAIN,
-            getLegendFontSize()
-        );
-    }
-
-
-    /**
-     * Create new legend entries, dependent on settings.
-     * @param plot The plot for which to modify the legend.
-     */
-    public void aggregateLegendEntries(XYPlot plot) {
-        int AGGR_THRESHOLD = 0;
-
-        if (getChartSettings() == null) {
-            return;
-        }
-        Integer threshold = getChartSettings().getLegendSection()
-            .getAggregationThreshold();
-
-        AGGR_THRESHOLD = (threshold != null) ? threshold.intValue() : 0;
-
-        LegendProcessor.aggregateLegendEntries(plot, AGGR_THRESHOLD);
-    }
-
-
-    /**
-     * Returns a transparently textured paint.
-     *
-     * @return a transparently textured paint.
-     */
-    protected static Paint createTransparentPaint() {
-        // TODO why not use a transparent color?
-        BufferedImage texture = new BufferedImage(
-            1, 1, BufferedImage.TYPE_4BYTE_ABGR);
-
-        return new TexturePaint(
-            texture, new Rectangle2D.Double(0d, 0d, 0d, 0d));
-    }
-
-
-    protected void preparePDFContext(CallContext context) {
-        int[] dimension = getExportDimension();
-
-        context.putContextValue("chart.width", dimension[0]);
-        context.putContextValue("chart.height", dimension[1]);
-        context.putContextValue("chart.marginLeft",   5f);
-        context.putContextValue("chart.marginRight",  5f);
-        context.putContextValue("chart.marginTop",    5f);
-        context.putContextValue("chart.marginBottom", 5f);
-        context.putContextValue(
-            "chart.page.format",
-            ChartExportHelper.DEFAULT_PAGE_SIZE);
-    }
-
-
-    protected void prepareSVGContext(CallContext context) {
-        int[] dimension = getExportDimension();
-
-        context.putContextValue("chart.width", dimension[0]);
-        context.putContextValue("chart.height", dimension[1]);
-        context.putContextValue(
-            "chart.encoding",
-            ChartExportHelper.DEFAULT_ENCODING);
-    }
-
-    /**
-     * Retuns the call context. May be null if init hasn't been called yet.
-     *
-     * @return the CallContext instance
-     */
-    public CallContext getCallContext() {
-        return context;
-    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,282 +8,69 @@
 
 package org.dive4elements.river.exports;
 
-import java.awt.BasicStroke;
-import java.awt.Color;
+import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM;
+
 import java.awt.Font;
 import java.awt.Graphics2D;
-import java.awt.Paint;
-import java.awt.Stroke;
-import java.awt.TexturePaint;
 import java.awt.Transparency;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.text.NumberFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
-import javax.xml.xpath.XPathConstants;
-
-import org.apache.log4j.Logger;
-import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
-import org.dive4elements.artifactdatabase.state.Settings;
-import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.artifacts.ArtifactNamespaceContext;
 import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.artifacts.CallMeta;
-import org.dive4elements.artifacts.PreferredLocale;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.access.RangeAccess;
-import org.dive4elements.river.artifacts.resources.Resources;
-import org.dive4elements.river.collections.D4EArtifactCollection;
 import org.dive4elements.river.java2d.NOPGraphics2D;
-import org.dive4elements.river.jfree.AxisDataset;
-import org.dive4elements.river.jfree.Bounds;
-import org.dive4elements.river.jfree.DoubleBounds;
-import org.dive4elements.river.jfree.EnhancedLineAndShapeRenderer;
 import org.dive4elements.river.jfree.RiverAnnotation;
-import org.dive4elements.river.jfree.StableXYDifferenceRenderer;
-import org.dive4elements.river.jfree.Style;
-import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
-import org.dive4elements.river.jfree.StyledSeries;
-import org.dive4elements.river.model.River;
-import org.dive4elements.river.themes.ThemeDocument;
 import org.dive4elements.river.utils.Formatter;
-import org.dive4elements.river.utils.RiverUtils;
 import org.jfree.chart.ChartRenderingInfo;
 import org.jfree.chart.JFreeChart;
-import org.jfree.chart.LegendItem;
-import org.jfree.chart.LegendItemCollection;
 import org.jfree.chart.axis.NumberAxis;
 import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
-import org.jfree.chart.title.TextTitle;
 import org.jfree.data.Range;
-import org.jfree.data.general.Series;
-import org.jfree.data.xy.XYDataset;
-import org.jfree.ui.RectangleInsets;
 import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM;
 
 /**
  * Implementation of the OutGenerator interface for charts.
  * It should provide some basic things that equal in all chart types.
  *
  */
-public abstract class ChartGenerator2 implements OutGenerator {
-
-    private static Logger log = Logger.getLogger(ChartGenerator2.class);
-
-    public static final boolean USE_NOP_GRAPHICS =
-        Boolean.getBoolean("info.rendering.nop.graphics");
-
-
-    public static final int    DEFAULT_CHART_WIDTH     = 600;
-    public static final int    DEFAULT_CHART_HEIGHT    = 400;
-    public static final String DEFAULT_CHART_FORMAT    = "png";
-    public static final Color  DEFAULT_GRID_COLOR      = Color.GRAY;
-    public static final float  DEFAULT_GRID_LINE_WIDTH = 0.3f;
-    public static final int    DEFAULT_FONT_SIZE       = 12;
-    public static final String DEFAULT_FONT_NAME       = "Tahoma";
-
-
-    public static final String XPATH_CHART_SIZE =
-        "/art:action/art:attributes/art:size";
-
-    public static final String XPATH_CHART_FORMAT =
-        "/art:action/art:attributes/art:format/@art:value";
+public abstract class ChartGenerator2 extends AbstractChartGenerator {
 
-    public static final String XPATH_CHART_X_RANGE =
-        "/art:action/art:attributes/art:xrange";
-
-    public static final String XPATH_CHART_Y_RANGE =
-        "/art:action/art:attributes/art:yrange";
-
-    /** The document of the incoming out() request.*/
-    protected Document request;
-
-    /** The output stream where the data should be written to.*/
-    protected OutputStream out;
-
-    /** The CallContext object.*/
-    protected CallContext context;
-
-    protected D4EArtifactCollection collection;
-
-    /** Artifact that is used to decorate the chart with meta information.*/
-    protected Artifact master;
-
-    /** The settings that should be used during output creation.*/
-    protected Settings settings;
-
-    /** Map of datasets ("index"). */
-    protected SortedMap<Integer, AxisDataset> datasets;
+    private static final boolean USE_NOP_GRAPHICS = Boolean.getBoolean("info.rendering.nop.graphics");
 
     /** Map of annotations to add at specific Y-axis. */
-    protected SortedMap<Integer, RiverAnnotation> yAnnotations;
-
-    /** List of annotations to insert in plot. */
-    protected List<RiverAnnotation> annotations =
-        new ArrayList<RiverAnnotation>();
-
-    protected abstract List<AxisSection> buildYAxisSections();
-
-    protected String outName;
+    protected SortedMap<Integer, RiverAnnotation> yAnnotations = new TreeMap<>();
 
-    /**
-     * Default constructor that initializes internal data structures.
-     */
-    public ChartGenerator2() {
-        datasets = new TreeMap<Integer, AxisDataset>();
-        yAnnotations = new TreeMap<Integer, RiverAnnotation>();
-    }
-
-    /**
-     * Adds annotations to list. The given annotation will be visible.
-     */
-    public void addAnnotations(RiverAnnotation annotation) {
-        annotations.add(annotation);
-    }
+    private Map<String, IdentifiableNumberAxis> axisNameToAxis = new HashMap<>();
 
     public void addYAnnotation(RiverAnnotation annotation, int axisIndex) {
         yAnnotations.put(axisIndex, annotation);
     }
 
-    /**
-     * This method needs to be implemented by concrete subclasses to create new
-     * instances of JFreeChart.
-     *
-     * @return a new instance of a JFreeChart.
-     */
-    public abstract JFreeChart generateChart();
-
-
-    /** For every outable (i.e. facets), this function is
-     * called and handles the data accordingly. */
     @Override
-    public abstract void doOut(
-        ArtifactAndFacet bundle,
-        ThemeDocument    attr,
-        boolean          visible);
-
-
-
-    protected abstract Series getSeriesOf(XYDataset dataset, int idx);
-
-    /**
-     * Returns the default title of a chart.
-     *
-     * @return the default title of a chart.
-     */
-    protected abstract String getDefaultChartTitle();
-
-    protected abstract String getDefaultYAxisLabel(String axisName);
-
-
-    /**
-     * Returns the default X-Axis label of a chart.
-     *
-     * @return the default X-Axis label of a chart.
-     */
-    protected abstract String getDefaultXAxisLabel();
-
-    /**
-     * This method is used to create new AxisDataset instances which may differ
-     * in concrete subclasses.
-     *
-     * @param idx The index of an axis.
-     */
-    protected abstract AxisDataset createAxisDataset(int idx);
-
+    protected void doGenerate(final CallContext context, final OutputStream out, final String outName) throws IOException {
+        log.debug("ChartGenerator2.generate");
 
-    /**
-     * Combines the ranges of the X axis at index <i>idx</i>.
-     *
-     * @param bounds A new Bounds.
-     * @param idx The index of the X axis that should be comined with
-     * <i>range</i>.
-     */
-    protected abstract void combineXBounds(Bounds bounds, int idx);
-
-
-    /**
-     * Combines the ranges of the Y axis at index <i>idx</i>.
-     *
-     * @param bounds A new Bounds.
-     * @param index The index of the Y axis that should be comined with.
-     * <i>range</i>.
-     */
-    protected abstract void combineYBounds(Bounds bounds, int index);
-
-
-    /**
-     * This method is used to determine the ranges for axes at a given index.
-     *
-     * @param index The index of the axes at the plot.
-     *
-     * @return a Range[] with [xrange, yrange];
-     */
-    public abstract Range[] getRangesForAxis(int index);
-
-    public abstract Bounds getXBounds(int axis);
-
-    protected abstract void setXBounds(int axis, Bounds bounds);
-
-    public abstract Bounds getYBounds(int axis);
-
-    protected abstract void setYBounds(int axis, Bounds bounds);
-
-
-    /**
-     * This method retrieves the chart subtitle by calling getChartSubtitle()
-     * and adds it as TextTitle to the chart.
-     * The default implementation of getChartSubtitle() returns the same
-     * as getDefaultChartSubtitle() which must be implemented by derived
-     * classes. If you want to add multiple subtitles to the chart override
-     * this method and add your subtitles manually.
-     *
-     * @param chart The JFreeChart chart object.
-     */
-    protected void addSubtitles(JFreeChart chart) {
-        String subtitle = getChartSubtitle();
-
-        if (subtitle != null && subtitle.length() > 0) {
-            chart.addSubtitle(new TextTitle(subtitle));
-        }
+        if (outName.indexOf("chartinfo") > 0)
+            generateInfo(context, out);
+        else 
+            generateImage(context);
     }
 
-    /**
-     * Generate chart.
+    /** 
+     * Generate only meta infos 
      */
-    @Override
-    public void generate() throws IOException {
-
-        log.debug("ChartGenerator2.generate");
-
-        if (outName.indexOf("chartinfo") > 0) {
-            generateInfo();
-        }
-        else {
-            generateImage();
-        }
-    }
-
-
-    /** Generate only meta infos */
-    private void generateInfo() throws IOException {
+    private void generateInfo(final CallContext context, final OutputStream out) {
 
         log.debug("ChartInfoGenerator2.generateInfo");
 
-        JFreeChart chart = generateChart();
+        JFreeChart chart = generateChart(context);
 
         int[] size = getSize();
         if (size == null) {
@@ -328,142 +115,16 @@
         XMLUtils.toStream(doc, out);
     }
 
-    /** Generate the diagram as an image. */
-    private void generateImage() throws IOException {
-        log.debug("ChartGenerator2.generateImage");
-
-        JFreeChart chart = generateChart();
-
-        String format = getFormat();
-        int[]  size   = getSize();
-
-        if (size == null) {
-            size = getExportDimension();
-        }
-
-        context.putContextValue("chart.width",  size[0]);
-        context.putContextValue("chart.height", size[1]);
-
-        if (format.equals(ChartExportHelper.FORMAT_PNG)) {
-            context.putContextValue("chart.image.format", "png");
-
-            ChartExportHelper.exportImage(
-                out,
-                chart,
-                context);
-        }
-        else if (format.equals(ChartExportHelper.FORMAT_PDF)) {
-            preparePDFContext(context);
-
-            ChartExportHelper.exportPDF(
-                out,
-                chart,
-                context);
-        }
-        else if (format.equals(ChartExportHelper.FORMAT_SVG)) {
-            prepareSVGContext(context);
-
-            ChartExportHelper.exportSVG(
-                out,
-                chart,
-                context);
-        }
-        else if (format.equals(ChartExportHelper.FORMAT_CSV)) {
-            context.putContextValue("chart.image.format", "csv");
-
-            ChartExportHelper.exportCSV(
-                out,
-                chart,
-                context);
-        }
-    }
-
-
-    @Override
-    public void init(
-        String outName,
-        Document request,
-        OutputStream out,
-        CallContext context
-    ) {
-        log.debug("ChartGenerator2.init");
-
-        this.outName = outName;
-        this.request = request;
-        this.out     = out;
-        this.context = context;
-    }
-
-
-    /** Sets the master artifact. */
-    @Override
-    public void setMasterArtifact(Artifact master) {
-        this.master = master;
-    }
-
-
-    /**
-     * Gets the master artifact.
-     * @return the master artifact.
-     */
-    public Artifact getMaster() {
-        return master;
-    }
-
-
-    /** Sets the collection. */
-    @Override
-    public void setCollection(D4EArtifactCollection collection) {
-        this.collection = collection;
-    }
-
-
-    @Override
-    public void setSettings(Settings settings) {
-        this.settings = settings;
-    }
-
-
-    /**
-     * Return instance of <i>ChartSettings</i> with a chart specific section
-     * but with no axes settings.
-     *
-     * @return an instance of <i>ChartSettings</i>.
-     */
-    @Override
-    public Settings getSettings() {
-        if (this.settings != null) {
-            return this.settings;
-        }
-
-        ChartSettings settings = new ChartSettings();
-
-        ChartSection  chartSection  = buildChartSection();
-        LegendSection legendSection = buildLegendSection();
-        ExportSection exportSection = buildExportSection();
-
-        settings.setChartSection(chartSection);
-        settings.setLegendSection(legendSection);
-        settings.setExportSection(exportSection);
-
-        List<AxisSection> axisSections = buildAxisSections();
-        for (AxisSection axisSection: axisSections) {
-            settings.addAxisSection(axisSection);
-        }
-
-        return settings;
-    }
-
-
     /**
      * Creates a new <i>ChartSection</i>.
      *
      * @return a new <i>ChartSection</i>.
      */
-    protected ChartSection buildChartSection() {
+    @Override
+    protected ChartSection buildChartSection(final CallContext context) {
         ChartSection chartSection = new ChartSection();
-        chartSection.setTitle(getChartTitle());
-        chartSection.setSubtitle(getChartSubtitlePure());
+        chartSection.setTitle(getChartTitle(context));
+        chartSection.setSubtitle(getChartSubtitlePure(context));
         chartSection.setDisplayGrid(isGridVisible());
         chartSection.setDisplayLogo(showLogo());
         chartSection.setLogoVPlacement(logoVPlace());
@@ -471,198 +132,7 @@
         return chartSection;
     }
 
-
-    /**
-     * Creates a new <i>LegendSection</i>.
-     *
-     * @return a new <i>LegendSection</i>.
-     */
-    protected LegendSection buildLegendSection() {
-        LegendSection legendSection = new LegendSection();
-        legendSection.setVisibility(isLegendVisible());
-        legendSection.setFontSize(getLegendFontSize());
-        legendSection.setAggregationThreshold(10);
-        return legendSection;
-    }
-
-
-    /**
-     * Creates a new <i>ExportSection</i> with default values <b>WIDTH=600</b>
-     * and <b>HEIGHT=400</b>.
-     *
-     * @return a new <i>ExportSection</i>.
-     */
-    protected ExportSection buildExportSection() {
-        ExportSection exportSection = new ExportSection();
-        exportSection.setWidth(600);
-        exportSection.setHeight(400);
-        return exportSection;
-    }
-
-
-    /**
-     * Creates a list of Sections that contains all axes of the chart (including
-     * X and Y axes).
-     *
-     * @return a list of Sections for each axis in this chart.
-     */
-    protected List<AxisSection> buildAxisSections() {
-        List<AxisSection> axisSections = new ArrayList<AxisSection>();
-
-        axisSections.addAll(buildXAxisSections());
-        axisSections.addAll(buildYAxisSections());
-
-        return axisSections;
-    }
-
-
-    /**
-     * Creates a new Section for chart's X axis.
-     *
-     * @return a List that contains a Section for the X axis.
-     */
-    protected List<AxisSection> buildXAxisSections() {
-        List<AxisSection> axisSections = new ArrayList<AxisSection>();
-
-        String identifier = "X";
-
-        AxisSection axisSection = new AxisSection();
-        axisSection.setIdentifier(identifier);
-        axisSection.setLabel(getXAxisLabel());
-        axisSection.setFontSize(14);
-        axisSection.setFixed(false);
-
-        // XXX We are able to find better default ranges that [0,0], but the Y
-        // axes currently have no better ranges set.
-        axisSection.setUpperRange(0d);
-        axisSection.setLowerRange(0d);
-
-        axisSections.add(axisSection);
-
-        return axisSections;
-    }
-
-
-    /**
-     * Returns the <i>settings</i> as <i>ChartSettings</i>.
-     *
-     * @return the <i>settings</i> as <i>ChartSettings</i> or null, if
-     * <i>settings</i> is not an instance of <i>ChartSettings</i>.
-     */
-    public ChartSettings getChartSettings() {
-        if (settings instanceof ChartSettings) {
-            return (ChartSettings) settings;
-        }
-
-        return null;
-    }
-
-
-    /**
-     * Returns the chart title provided by <i>settings</i>.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return the title provided by <i>settings</i> or null if no
-     * <i>ChartSection</i> is provided by <i>settings</i>.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public String getChartTitle(ChartSettings settings) {
-        ChartSection cs = settings.getChartSection();
-        return cs != null ? cs.getTitle() : null;
-    }
-
-
-    /**
-     * Returns the chart subtitle provided by <i>settings</i>.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return the subtitle provided by <i>settings</i> or null if no
-     * <i>ChartSection</i> is provided by <i>settings</i>.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public String getChartSubtitle(ChartSettings settings) {
-        ChartSection cs = settings.getChartSection();
-        return cs != null ? cs.getSubtitle() : null;
-    }
-
-
-    /**
-     * Returns a boolean object that determines if the chart grid should be
-     * visible or not. This information needs to be provided by <i>settings</i>,
-     * otherweise the default is true.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return true, if the chart grid should be visible otherwise false.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public boolean isGridVisible(ChartSettings settings) {
-        ChartSection     cs = settings.getChartSection();
-        Boolean displayGrid = cs.getDisplayGrid();
-
-        return displayGrid != null ? displayGrid : true;
-    }
-
-
-    /**
-     * Returns a boolean object that determines if the chart legend should be
-     * visible or not. This information needs to be provided by <i>settings</i>,
-     * otherwise the default is true.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return true, if the chart legend should be visible otherwise false.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public boolean isLegendVisible(ChartSettings settings) {
-        LegendSection      ls = settings.getLegendSection();
-        Boolean displayLegend = ls.getVisibility();
-
-        return displayLegend != null ? displayLegend : true;
-    }
-
-
-    /**
-     * Returns the legend font size specified in <i>settings</i> or null if no
-     * <i>LegendSection</i> is provided by <i>settings</i>.
-     *
-     * @param settings A ChartSettings object.
-     *
-     * @return the legend font size or null.
-     *
-     * @throws NullPointerException if <i>settings</i> is null.
-     */
-    public Integer getLegendFontSize(ChartSettings settings) {
-        LegendSection ls = settings.getLegendSection();
-        return ls != null ? ls.getFontSize() : null;
-    }
-
-
-    /**
-     * Returns the title of a chart. The return value depends on the existence
-     * of ChartSettings: if there are ChartSettings set, this method returns the
-     * chart title provided by those settings. Otherwise, this method returns
-     * getDefaultChartTitle().
-     *
-     * @return the title of a chart.
-     */
-    protected String getChartTitle() {
-        ChartSettings chartSettings = getChartSettings();
-
-        if (chartSettings != null) {
-            return getChartTitle(chartSettings);
-        }
-
-        return getDefaultChartTitle();
-    }
-
-    protected String interpolateVariables(String s) {
+    protected String interpolateVariables(final CallContext context, String s) {
         log.debug("Interpolate variables in string '" + s + "'");
         Object radius = context.getContextValue("radius");
         if (radius instanceof Double) {
@@ -687,17 +157,18 @@
      * existence of ChartSettings: if there are ChartSettings set, this method
      * returns the chart title provided by those settings. Otherwise, this
      * method returns getDefaultChartSubtitle().
+     * @param context 
      *
      * @return the subtitle of a chart.
      */
-    protected String getChartSubtitlePure() {
+    protected String getChartSubtitlePure(CallContext context) {
         ChartSettings chartSettings = getChartSettings();
 
         String subTitle = chartSettings != null
             ? getChartSubtitle(chartSettings)
-            : getDefaultChartSubtitle();
+            : getDefaultChartSubtitle(context);
 
-        String defSubTitle = getDefaultChartSubtitle();
+        String defSubTitle = getDefaultChartSubtitle(context);
 
         if (subTitle == null) {
             subTitle = defSubTitle != null ? defSubTitle : "";
@@ -706,162 +177,9 @@
         return subTitle;
     }
 
-    protected String getChartSubtitle() {
-        return interpolateVariables(getChartSubtitlePure());
-    }
-
-
-    /**
-     * This method always returns null. Override it in subclasses that require
-     * subtitles.
-     *
-     * @return null.
-     */
-    protected String getDefaultChartSubtitle() {
-        // Override this method in subclasses
-        return null;
-    }
-
-
-    /**
-     * This method is used to determine, if the chart's legend is visible or
-     * not. If a <i>settings</i> instance is set, this instance determines the
-     * visibility otherwise, this method returns true as default if no
-     * <i>settings</i> is set.
-     *
-     * @return true, if the legend should be visible, otherwise false.
-     */
-    protected boolean isLegendVisible() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            return isLegendVisible(chartSettings);
-        }
-
-        return true;
-    }
-
-
-    /** Where to place the logo. */
-    protected String logoHPlace() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            ChartSection cs    = chartSettings.getChartSection();
-            String       place = cs.getLogoHPlacement();
-
-            return place;
-        }
-        return "center";
-    }
-
-
-    /** Where to place the logo. */
-    protected String logoVPlace() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            ChartSection cs    = chartSettings.getChartSection();
-            String       place = cs.getLogoVPlacement();
-
-            return place;
-        }
-        return "top";
-    }
-
-
-    /** Return the logo id from settings. */
-    protected String showLogo(ChartSettings chartSettings) {
-        if (chartSettings != null) {
-            ChartSection cs   = chartSettings.getChartSection();
-            String       logo = cs.getDisplayLogo();
-
-            return logo;
-        }
-        return "none";
-    }
-
-
-    /**
-     * This method is used to determine if a logo should be added to the plot.
-     *
-     * @return logo name (null if none).
-     */
-    protected String showLogo() {
-        ChartSettings chartSettings = getChartSettings();
-        return showLogo(chartSettings);
-    }
-
-
-    /**
-     * This method is used to determine the font size of the chart's legend. If
-     * a <i>settings</i> instance is set, this instance determines the font
-     * size, otherwise this method returns 12 as default if no <i>settings</i>
-     * is set or if it doesn't provide a legend font size.
-     *
-     * @return a legend font size.
-     */
-    protected int getLegendFontSize() {
-        Integer fontSize = null;
-
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings != null) {
-            fontSize = getLegendFontSize(chartSettings);
-        }
-
-        return fontSize != null ? fontSize : DEFAULT_FONT_SIZE;
-    }
-
-
-    /**
-     * This method is used to determine if the resulting chart should display
-     * grid lines or not. <b>Note: this method always returns true!</b>
-     *
-     * @return true, if the chart should display grid lines, otherwise false.
-     */
-    protected boolean isGridVisible() {
-        return true;
-    }
-
-
-    /**
-     * Returns the X-Axis label of a chart.
-     *
-     * @return the X-Axis label of a chart.
-     */
-    protected String getXAxisLabel() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings == null) {
-            return getDefaultXAxisLabel();
-        }
-
-        AxisSection as = chartSettings.getAxisSection("X");
-        if (as != null) {
-            String label = as.getLabel();
-
-            if (label != null) {
-                return label;
-            }
-        }
-
-        return getDefaultXAxisLabel();
-    }
-
-
-    /**
-     * This method returns the font size for the X axis. If the font size is
-     * specified in ChartSettings (if <i>chartSettings</i> is set), this size is
-     * returned. Otherwise the default font size 12 is returned.
-     *
-     * @return the font size for the x axis.
-     */
-    protected int getXAxisLabelFontSize() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings == null) {
-            return DEFAULT_FONT_SIZE;
-        }
-
-        AxisSection   as = chartSettings.getAxisSection("X");
-        Integer fontSize = as.getFontSize();
-
-        return fontSize != null ? fontSize : DEFAULT_FONT_SIZE;
+    @Override
+    protected String getChartSubtitle(CallContext context) {
+        return interpolateVariables(context, getChartSubtitlePure(context));
     }
 
     /**
@@ -891,29 +209,6 @@
         return fontSize != null ? fontSize : DEFAULT_FONT_SIZE;
     }
 
-    /**
-     * This method returns the export dimension specified in ChartSettings as
-     * int array [width,height].
-     *
-     * @return an int array with [width,height].
-     */
-    protected int[] getExportDimension() {
-        ChartSettings chartSettings = getChartSettings();
-        if (chartSettings == null) {
-            return new int[] { 600, 400 };
-        }
-
-        ExportSection export = chartSettings.getExportSection();
-        Integer width  = export.getWidth();
-        Integer height = export.getHeight();
-
-        if (width != null && height != null) {
-            return new int[] { width, height };
-        }
-
-        return new int[] { 600, 400 };
-    }
-
     protected abstract String getYAxisLabel(String axisName);
 
     /**
@@ -939,9 +234,7 @@
             return null;
         }
 
-        Boolean  fixed = as.isFixed();
-
-        if (fixed != null && fixed) {
+        if (as.isFixed()) {
             Double upper = as.getUpperRange();
             Double lower = as.getLowerRange();
 
@@ -955,504 +248,6 @@
         return null;
     }
 
-
-    /**
-     * Adds a new AxisDataset which contains <i>dataset</i> at index <i>idx</i>.
-     *
-     * @param dataset An XYDataset.
-     * @param idx The axis index.
-     * @param visible Determines, if the dataset should be visible or not.
-     */
-    public void addAxisDataset(XYDataset dataset, int idx, boolean visible) {
-        if (dataset == null || idx < 0) {
-            return;
-        }
-
-        AxisDataset axisDataset = getAxisDataset(idx);
-
-        Bounds[] xyBounds = ChartHelper.getBounds(dataset);
-
-        if (xyBounds == null) {
-            log.warn("Skip XYDataset for Axis (invalid ranges): " + idx);
-            return;
-        }
-
-        if (visible) {
-            if (log.isDebugEnabled()) {
-                log.debug("Add new AxisDataset at index: " + idx);
-                log.debug("X extent: " + xyBounds[0]);
-                log.debug("Y extent: " + xyBounds[1]);
-            }
-
-            axisDataset.addDataset(dataset);
-        }
-
-        combineXBounds(xyBounds[0], 0);
-        combineYBounds(xyBounds[1], idx);
-    }
-
-
-    /**
-     * This method grants access to the AxisDatasets stored in <i>datasets</i>.
-     * If no AxisDataset exists for index <i>idx</i>, a new AxisDataset is
-     * created using <i>createAxisDataset()</i>.
-     *
-     * @param idx The index of the desired AxisDataset.
-     *
-     * @return an existing or new AxisDataset.
-     */
-    public AxisDataset getAxisDataset(int idx) {
-        AxisDataset axisDataset = datasets.get(idx);
-
-        if (axisDataset == null) {
-            axisDataset = createAxisDataset(idx);
-            datasets.put(idx, axisDataset);
-        }
-
-        return axisDataset;
-    }
-
-
-    /**
-     * Adjust some Stroke/Grid parameters for <i>plot</i>. The chart
-     * <i>Settings</i> are applied in this method.
-     *
-     * @param plot The XYPlot which is adapted.
-     */
-    protected void adjustPlot(XYPlot plot) {
-        Stroke gridStroke = new BasicStroke(
-            DEFAULT_GRID_LINE_WIDTH,
-            BasicStroke.CAP_BUTT,
-            BasicStroke.JOIN_MITER,
-            3.0f,
-            new float[] { 3.0f },
-            0.0f);
-
-        ChartSettings      cs = getChartSettings();
-        boolean isGridVisible = cs != null ? isGridVisible(cs) : true;
-
-        plot.setDomainGridlineStroke(gridStroke);
-        plot.setDomainGridlinePaint(DEFAULT_GRID_COLOR);
-        plot.setDomainGridlinesVisible(isGridVisible);
-
-        plot.setRangeGridlineStroke(gridStroke);
-        plot.setRangeGridlinePaint(DEFAULT_GRID_COLOR);
-        plot.setRangeGridlinesVisible(isGridVisible);
-
-        plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d));
-    }
-
-
-    /**
-     * This helper mehtod is used to extract the current locale from instance
-     * vairable <i>context</i>.
-     *
-     * @return the current locale.
-     */
-    protected Locale getLocale() {
-        CallMeta           meta = context.getMeta();
-        PreferredLocale[] prefs = meta.getLanguages();
-
-        int len = prefs != null ? prefs.length : 0;
-
-        Locale[] locales = new Locale[len];
-
-        for (int i = 0; i < len; i++) {
-            locales[i] = prefs[i].getLocale();
-        }
-
-        return meta.getPreferredLocale(locales);
-    }
-
-
-    /**
-     * Look up \param key in i18n dictionary.
-     * @param key key for which to find i18nd version.
-     * @param def default, returned if lookup failed.
-     * @return value found in i18n dictionary, \param def if no value found.
-     */
-    public String msg(String key, String def) {
-        return Resources.getMsg(context.getMeta(), key, def);
-    }
-
-    /**
-     * Look up \param key in i18n dictionary.
-     * @param key key for which to find i18nd version.
-     * @return value found in i18n dictionary, key itself if failed.
-     */
-    public String msg(String key) {
-        return Resources.getMsg(context.getMeta(), key, key);
-    }
-
-    public String msg(String key, String def, Object[] args) {
-        return Resources.getMsg(context.getMeta(), key, def, args);
-    }
-
-
-    protected String getRiverName() {
-        D4EArtifact flys = (D4EArtifact) master;
-
-        River river = RiverUtils.getRiver(flys);
-        return (river != null) ? river.getName() : "";
-    }
-
-
-    protected double[] getRange() {
-        D4EArtifact flys = (D4EArtifact) master;
-
-        RangeAccess rangeAccess = new RangeAccess(flys);
-        return rangeAccess.getKmRange();
-    }
-
-
-    /**
-     * Returns the size of a chart export as array which has been specified by
-     * the incoming request document.
-     *
-     * @return the size of a chart as [width, height] or null if no width or
-     * height are given in the request document.
-     */
-    protected int[] getSize() {
-        int[] size = new int[2];
-
-        Element sizeEl = (Element)XMLUtils.xpath(
-            request,
-            XPATH_CHART_SIZE,
-            XPathConstants.NODE,
-            ArtifactNamespaceContext.INSTANCE);
-
-        if (sizeEl != null) {
-            String uri = ArtifactNamespaceContext.NAMESPACE_URI;
-
-            String w = sizeEl.getAttributeNS(uri, "width");
-            String h = sizeEl.getAttributeNS(uri, "height");
-
-            if (w.length() > 0 && h.length() > 0) {
-                try {
-                    size[0] = Integer.parseInt(w);
-                    size[1] = Integer.parseInt(h);
-                }
-                catch (NumberFormatException nfe) {
-                    log.warn("Wrong values for chart width/height.");
-                }
-            }
-        }
-
-        return size[0] > 0 && size[1] > 0 ? size : null;
-    }
-
-
-    /**
-     * This method returns the format specified in the <i>request</i> document
-     * or <i>DEFAULT_CHART_FORMAT</i> if no format is specified in
-     * <i>request</i>.
-     *
-     * @return the format used to export this chart.
-     */
-    protected String getFormat() {
-        String format = (String) XMLUtils.xpath(
-            request,
-            XPATH_CHART_FORMAT,
-            XPathConstants.STRING,
-            ArtifactNamespaceContext.INSTANCE);
-
-        return format == null || format.length() == 0
-            ? DEFAULT_CHART_FORMAT
-            : format;
-    }
-
-
-    /**
-     * Returns the X-Axis range as String array from request document.
-     * If the (x|y)range elements are not found in request document, return
-     * null (i.e. not zoomed).
-     *
-     * @return a String array with [lower, upper], null if not in document.
-     */
-    protected String[] getDomainAxisRangeFromRequest() {
-        Element xrange = (Element)XMLUtils.xpath(
-            request,
-            XPATH_CHART_X_RANGE,
-            XPathConstants.NODE,
-            ArtifactNamespaceContext.INSTANCE);
-
-        if (xrange == null) {
-            return null;
-        }
-
-        String uri = ArtifactNamespaceContext.NAMESPACE_URI;
-
-        String lower = xrange.getAttributeNS(uri, "from");
-        String upper = xrange.getAttributeNS(uri, "to");
-
-        return new String[] { lower, upper };
-    }
-
-
-    /** Returns null if the (x|y)range-element was not found in
-     *request document.
-     * This usally means that the axis are not manually zoomed, i.e. showing
-     * full data extent. */
-    protected String[] getValueAxisRangeFromRequest() {
-        Element yrange = (Element)XMLUtils.xpath(
-            request,
-            XPATH_CHART_Y_RANGE,
-            XPathConstants.NODE,
-            ArtifactNamespaceContext.INSTANCE);
-
-        if (yrange == null) {
-            return null;
-        }
-
-
-        String uri = ArtifactNamespaceContext.NAMESPACE_URI;
-
-        String lower = yrange.getAttributeNS(uri, "from");
-        String upper = yrange.getAttributeNS(uri, "to");
-
-        return new String[] { lower, upper };
-    }
-
-
-    /**
-     * Returns the default size of a chart export as array.
-     *
-     * @return the default size of a chart as [width, height].
-     */
-    protected int[] getDefaultSize() {
-        return new int[] { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT };
-    }
-
-
-    /**
-     * Add datasets stored in instance variable <i>datasets</i> to plot.
-     * <i>datasets</i> actually stores instances of AxisDataset, so each of this
-     * datasets is mapped to a specific axis as well.
-     *
-     * @param plot plot to add datasets to.
-     */
-    protected void addDatasets(XYPlot plot) {
-        log.debug("addDatasets()");
-
-        // AxisDatasets are sorted, but some might be empty.
-        // Thus, generate numbering on the fly.
-        int axisIndex    = 0;
-        int datasetIndex = 0;
-
-        for (Map.Entry<Integer, AxisDataset> entry: datasets.entrySet()) {
-            if (!entry.getValue().isEmpty()) {
-                // Add axis and range information.
-                AxisDataset axisDataset = entry.getValue();
-                NumberAxis  axis        = createYAxis(entry.getKey());
-
-                plot.setRangeAxis(axisIndex, axis);
-
-                if (axis.getAutoRangeIncludesZero()) {
-                    axisDataset.setRange(
-                        Range.expandToInclude(axisDataset.getRange(), 0d));
-                }
-
-                setYBounds(axisIndex, expandPointRange(axisDataset.getRange()));
-
-                // Add contained datasets, mapping to axis.
-                for (XYDataset dataset: axisDataset.getDatasets()) {
-                    try {
-                        plot.setDataset(datasetIndex, dataset);
-                        plot.mapDatasetToRangeAxis(datasetIndex, axisIndex);
-
-                        applyThemes(plot, dataset,
-                            datasetIndex,
-                            axisDataset.isArea(dataset));
-
-                        datasetIndex++;
-                    }
-                    catch (RuntimeException re) {
-                        log.error(re);
-                    }
-                }
-
-                axisDataset.setPlotAxisIndex(axisIndex);
-                axisIndex++;
-            }
-        }
-    }
-
-
-    /**
-     * @param idx "index" of dataset/series (first dataset to be drawn has
-     *            index 0), correlates with renderer index.
-     * @param isArea true if the series describes an area and shall be rendered
-     *                as such.
-     */
-    protected void applyThemes(
-        XYPlot    plot,
-        XYDataset series,
-        int       idx,
-        boolean   isArea
-    ) {
-        if (isArea) {
-            applyAreaTheme(plot, (StyledAreaSeriesCollection) series, idx);
-        }
-        else {
-            applyLineTheme(plot, series, idx);
-        }
-    }
-
-
-    /**
-     * This method applies the themes defined in the series itself. Therefore,
-     * <i>StyledXYSeries.applyTheme()</i> is called, which modifies the renderer
-     * for the series.
-     *
-     * @param plot The plot.
-     * @param dataset The XYDataset which needs to support Series objects.
-     * @param idx The index of the renderer / dataset.
-     */
-    protected void applyLineTheme(XYPlot plot, XYDataset dataset, int idx) {
-        log.debug("Apply LineTheme for dataset at index: " + idx);
-
-        LegendItemCollection lic  = new LegendItemCollection();
-        LegendItemCollection anno = plot.getFixedLegendItems();
-
-        Font legendFont = createLegendLabelFont();
-
-        XYLineAndShapeRenderer renderer = createRenderer(plot, idx);
-
-        for (int s = 0, num = dataset.getSeriesCount(); s < num; s++) {
-            Series series = getSeriesOf(dataset, s);
-
-            if (series instanceof StyledSeries) {
-                Style style = ((StyledSeries) series).getStyle();
-                style.applyTheme(renderer, s);
-            }
-
-            // special case: if there is just one single item, we need to enable
-            // points for this series, otherwise we would not see anything in
-            // the chart area.
-            if (series.getItemCount() == 1) {
-                renderer.setSeriesShapesVisible(s, true);
-            }
-
-            LegendItem legendItem = renderer.getLegendItem(idx, s);
-            if (legendItem.getLabel().endsWith(" ") ||
-                legendItem.getLabel().endsWith("interpol")) {
-                legendItem = null;
-            }
-
-            if (legendItem != null) {
-                legendItem.setLabelFont(legendFont);
-                lic.add(legendItem);
-            }
-            else {
-                log.warn("Could not get LegentItem for renderer: "
-                    + idx + ", series-idx " + s);
-            }
-        }
-
-        if (anno != null) {
-            lic.addAll(anno);
-        }
-
-        plot.setFixedLegendItems(lic);
-
-        plot.setRenderer(idx, renderer);
-    }
-
-
-    /**
-     * @param plot The plot.
-     * @param area A StyledAreaSeriesCollection object.
-     * @param idx The index of the dataset.
-     */
-    protected void applyAreaTheme(
-        XYPlot                     plot,
-        StyledAreaSeriesCollection area,
-        int                        idx
-    ) {
-        LegendItemCollection lic  = new LegendItemCollection();
-        LegendItemCollection anno = plot.getFixedLegendItems();
-
-        Font legendFont = createLegendLabelFont();
-
-        log.debug("Registering an 'area'renderer at idx: " + idx);
-
-        StableXYDifferenceRenderer dRenderer =
-            new StableXYDifferenceRenderer();
-
-        if (area.getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) {
-            dRenderer.setPositivePaint(createTransparentPaint());
-        }
-
-        plot.setRenderer(idx, dRenderer);
-
-        area.applyTheme(dRenderer);
-
-        // i18n
-        dRenderer.setAreaLabelNumberFormat(
-            Formatter.getFormatter(context.getMeta(), 2, 4));
-
-        dRenderer.setAreaLabelTemplate(Resources.getMsg(
-            context.getMeta(), "area.label.template", "Area=%sm2"));
-
-        LegendItem legendItem = dRenderer.getLegendItem(idx, 0);
-        if (legendItem != null) {
-            legendItem.setLabelFont(legendFont);
-            lic.add(legendItem);
-        }
-        else {
-            log.warn("Could not get LegentItem for renderer: "
-                + idx + ", series-idx " + 0);
-        }
-
-        if (anno != null) {
-            lic.addAll(anno);
-        }
-
-        plot.setFixedLegendItems(lic);
-    }
-
-
-    /**
-     * Expands a given range if it collapses into one point.
-     *
-     * @param range Range to be expanded if upper == lower bound.
-     *
-     * @return Bounds of point plus 5 percent in each direction.
-     */
-    private Bounds expandPointRange(Range range) {
-        if (range == null) {
-            return null;
-        }
-        else if (range.getLowerBound() == range.getUpperBound()) {
-            Range expandedRange = ChartHelper.expandRange(range, 5d);
-            return new DoubleBounds(
-                expandedRange.getLowerBound(), expandedRange.getUpperBound());
-        }
-
-        return new DoubleBounds(range.getLowerBound(), range.getUpperBound());
-    }
-
-
-    /**
-     * Creates a new instance of EnhancedLineAndShapeRenderer.
-     *
-     * @param plot The plot which is set for the new renderer.
-     * @param idx This value is not used in the current implementation.
-     *
-     * @return a new instance of EnhancedLineAndShapeRenderer.
-     */
-    protected XYLineAndShapeRenderer createRenderer(XYPlot plot, int idx) {
-        log.debug("Create EnhancedLineAndShapeRenderer for idx: " + idx);
-
-        EnhancedLineAndShapeRenderer r =
-            new EnhancedLineAndShapeRenderer(true, false);
-
-        r.setPlot(plot);
-
-        return r;
-    }
-
-
     /**
      * Creates a new instance of <i>IdentifiableNumberAxis</i>.
      *
@@ -1461,15 +256,15 @@
      *
      * @return an instance of IdentifiableNumberAxis.
      */
-    protected NumberAxis createNumberAxis(int idx, String label) {
+    protected final NumberAxis createNumberAxis(int idx, String label) {
         return new IdentifiableNumberAxis(axisIndexToName(idx), label);
     }
 
-
     /**
      * Create Y (range) axis for given index.
      * Shall be overriden by subclasses.
      */
+    @Override
     protected NumberAxis createYAxis(int index) {
 
         Font labelFont = new Font(
@@ -1479,121 +274,32 @@
 
         String axisName = axisIndexToName(index);
 
-        IdentifiableNumberAxis axis = new IdentifiableNumberAxis(
-            axisName, getYAxisLabel(axisName));
+        IdentifiableNumberAxis axis = new IdentifiableNumberAxis(axisName, getYAxisLabel(axisName));
 
         axis.setAutoRangeIncludesZero(false);
         axis.setLabelFont(labelFont);
         axis.setTickLabelFont(labelFont);
+        // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+        axis.setLowerMargin(0);
+        axis.setUpperMargin(0);
 
+        /* remember axis for lookup */
+        axisNameToAxis.put( axisName, axis );
+        
         return axis;
     }
 
-
-    /**
-     * Creates a new LegendItem with <i>name</i> and font provided by
-     * <i>createLegendLabelFont()</i>.
-     *
-     * @param theme The theme of the chart line.
-     * @param name The displayed name of the item.
-     *
-     * @return a new LegendItem instance.
-     */
-    public LegendItem createLegendItem(ThemeDocument theme, String name) {
-        // OPTIMIZE Pass font, parsed Theme items.
-
-        Color color = theme.parseLineColorField();
-        if (color == null) {
-            color = Color.BLACK;
-        }
-
-        LegendItem legendItem  = new LegendItem(name, color);
-
-        legendItem.setLabelFont(createLegendLabelFont());
-        return legendItem;
-    }
-
-
-    /**
-     * Creates Font (Family and size) to use when creating Legend Items. The
-     * font size depends in the return value of <i>getLegendFontSize()</i>.
-     *
-     * @return a new Font instance with <i>DEFAULT_FONT_NAME</i>.
-     */
-    protected Font createLegendLabelFont() {
-        return new Font(
-            DEFAULT_FONT_NAME,
-            Font.PLAIN,
-            getLegendFontSize()
-        );
+    public final IdentifiableNumberAxis getAxis(final String axisName) {
+        return axisNameToAxis.get(axisName);
     }
-
-
-    /**
-     * Create new legend entries, dependent on settings.
-     * @param plot The plot for which to modify the legend.
-     */
-    public void aggregateLegendEntries(XYPlot plot) {
-        int AGGR_THRESHOLD = 0;
-
-        if (getChartSettings() == null) {
-            return;
-        }
-        Integer threshold = getChartSettings().getLegendSection()
-            .getAggregationThreshold();
-
-        AGGR_THRESHOLD = (threshold != null) ? threshold.intValue() : 0;
-
-        LegendProcessor.aggregateLegendEntries(plot, AGGR_THRESHOLD);
-    }
-
-
-    /**
-     * Returns a transparently textured paint.
-     *
-     * @return a transparently textured paint.
-     */
-    protected static Paint createTransparentPaint() {
-        // TODO why not use a transparent color?
-        BufferedImage texture = new BufferedImage(
-            1, 1, BufferedImage.TYPE_4BYTE_ABGR);
-
-        return new TexturePaint(
-            texture, new Rectangle2D.Double(0d, 0d, 0d, 0d));
+    
+    /** Returns the number of registered y-axes */
+    public final int getNumYAxes() {
+        return axisNameToAxis.size();
     }
-
-
-    protected void preparePDFContext(CallContext context) {
-        int[] dimension = getExportDimension();
-
-        context.putContextValue("chart.width", dimension[0]);
-        context.putContextValue("chart.height", dimension[1]);
-        context.putContextValue("chart.marginLeft",   5f);
-        context.putContextValue("chart.marginRight",  5f);
-        context.putContextValue("chart.marginTop",    5f);
-        context.putContextValue("chart.marginBottom", 5f);
-        context.putContextValue(
-            "chart.page.format",
-            ChartExportHelper.DEFAULT_PAGE_SIZE);
+    
+    protected final void addYAnnotationsToRenderer(final XYPlot plot) {
+        final AnnotationRenderer annotationRenderer = new AnnotationRenderer(getChartSettings(), getDatasets(), DEFAULT_FONT_NAME);
+        annotationRenderer.addYAnnotationsToRenderer(plot, this.yAnnotations);
     }
-
-
-    protected void prepareSVGContext(CallContext context) {
-        int[] dimension = getExportDimension();
-
-        context.putContextValue("chart.width", dimension[0]);
-        context.putContextValue("chart.height", dimension[1]);
-        context.putContextValue(
-            "chart.encoding",
-            ChartExportHelper.DEFAULT_ENCODING);
-    }
-
-    /**
-     * Retuns the call context. May be null if init hasn't been called yet.
-     *
-     * @return the CallContext instance
-     */
-    public CallContext getCallContext() {
-        return context;
-    }
-}
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartInfoGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartInfoGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -69,6 +69,7 @@
         this.generator = generator;
     }
 
+    @Override
     public void setup(Object config) {
         log.debug("ChartInfoGenerator.setup");
     }
@@ -81,6 +82,7 @@
      * @param out
      * @param context
      */
+    @Override
     public void init(
         String outName,
         Document request,
@@ -98,21 +100,21 @@
      *
      * @param master The master artifact
      */
+    @Override
     public void setMasterArtifact(Artifact master) {
         generator.setMasterArtifact(master);
     }
 
-
     /**
      * Dispatches the operation to the instantiated generator.
      *
      * @param collection The collection.
      */
+    @Override
     public void setCollection(D4EArtifactCollection collection) {
         generator.setCollection(collection);
     }
-
-
+    
     /**
      * Dispatches the operation to the instantiated generator.
      */
@@ -137,7 +139,7 @@
     {
         log.debug("ChartInfoGenerator.generate");
 
-        JFreeChart chart = generator.generateChart();
+        JFreeChart chart = generator.generateChart(generator.getContext());
 
         int[] size = generator.getSize();
         if (size == null) {
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartSection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartSection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -93,8 +93,8 @@
     }
 
 
-    public Boolean getDisplayGrid() {
-        return getBooleanValue(DISPLAYGRID_ATTR);
+    public boolean getDisplayGrid() {
+        return getBooleanValue(DISPLAYGRID_ATTR, true);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartSettings.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartSettings.java	Fri Jul 13 11:56:22 2018 +0200
@@ -314,6 +314,7 @@
 
         String width  = XMLUtils.xpathString(export, "export/width", null);
         String height = XMLUtils.xpathString(export, "export/height", null);
+        String metadata = XMLUtils.xpathString(export, "export/chart_settings_export_metadata", null);
 
         if (log.isDebugEnabled()) {
             log.debug("Found export width : '" + width + "'");
@@ -322,6 +323,7 @@
 
         section.setWidth(Integer.valueOf(width.length() > 0 ? width : "-1"));
         section.setHeight(Integer.valueOf(height.length() > 0 ? height : "-1"));
+        section.setMetadata(metadata == null ? false : Boolean.valueOf(metadata));
 
         target.setExportSection(section);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -16,13 +16,8 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-import org.jfree.chart.LegendItemCollection;
-import org.jfree.chart.annotations.XYBoxAnnotation;
-import org.jfree.chart.annotations.XYTextAnnotation;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.data.xy.XYSeries;
-
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.DataProvider;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.geom.Lines;
@@ -35,8 +30,13 @@
 import org.dive4elements.river.model.FastCrossSectionLine;
 import org.dive4elements.river.themes.TextStyle;
 import org.dive4elements.river.themes.ThemeDocument;
+import org.dive4elements.river.utils.Formatter;
 import org.dive4elements.river.utils.RiverUtils;
-import org.dive4elements.river.utils.Formatter;
+import org.jfree.chart.LegendItemCollection;
+import org.jfree.chart.annotations.XYBoxAnnotation;
+import org.jfree.chart.annotations.XYTextAnnotation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.data.xy.XYSeries;
 
 
 /**
@@ -93,7 +93,7 @@
      * Get localized chart title.
      */
     @Override
-    public String getDefaultChartTitle() {
+    public String getDefaultChartTitle(final CallContext context) {
         Object[] i18n_msg_args = new Object[] {
                 getRiverName()
         };
@@ -103,19 +103,19 @@
 
     /** Always return default subtitle. */
     @Override
-    protected String getChartSubtitle() {
+    protected String getChartSubtitle(CallContext context) {
         // XXX NOTE: overriding this method disables ChartSettings subtitle!
         // The default implementation of this method in ChartGenerator returns
         // the subtitle changed via the chart settings dialog. This method
         // always returns the subtitle containing river and km, NEVER the
         // ChartSettings subtitle!
-        return getDefaultChartSubtitle();
+        return getDefaultChartSubtitle(context);
     }
 
-
+    
     /** Get Charts default subtitle. */
     @Override
-    protected String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(final CallContext context) {
         List<DataProvider> providers =
             context.getDataProvider(
                 CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA);
@@ -164,8 +164,7 @@
     }
 
     @Override
-    protected void addAnnotationsToRenderer(XYPlot plot) {
-        super.addAnnotationsToRenderer(plot);
+    protected void doAddFurtherAnnotations(XYPlot plot, List<RiverAnnotation> annotations) {
 
         // Paints for the boxes/lines.
         Stroke basicStroke = new BasicStroke(1.0f);
@@ -179,7 +178,7 @@
                 plot.getDomainAxis(0),
                 plot.getRangeAxis());
 
-        for(RiverAnnotation fa : this.annotations) {
+        for(RiverAnnotation fa : annotations) {
 
             // Access text styling, if any.
             ThemeDocument theme = fa.getTheme();
@@ -245,14 +244,14 @@
     }
 
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
     }
 
 
     @Override
     protected String getDefaultYAxisLabel(int pos) {
-        D4EArtifact flys = (D4EArtifact) master;
+        D4EArtifact flys = getArtifact();
 
         String unit = RiverUtils.getRiver(flys).getWstUnit().getName();
 
@@ -279,6 +278,8 @@
             log.error("No facet name for doOut(). No output generated!");
             return;
         }
+        
+        CallContext context = getContext();
 
         if (name.equals(CROSS_SECTION)) {
             doCrossSectionOut(
@@ -351,11 +352,13 @@
         // DO NOT SORT DATA! This destroys the gaps indicated by NaNs.
         StyledXYSeries series = new StyledXYSeries(seriesName, false, theme);
 
+        CallContext context = getContext();
+        
         if (!theme.parseShowLineLabel()) {
             series.setLabel("");
         }
         if (theme.parseShowWidth()) {
-            NumberFormat nf = Formatter.getMeterFormat(this.context);
+            NumberFormat nf = Formatter.getMeterFormat(context);
             String labelAdd = "b=" + nf.format(lines.width) + "m";
             if (series.getLabel().length() == 0) {
                 series.setLabel(labelAdd);
@@ -366,8 +369,8 @@
         }
         if (theme.parseShowLevel() && lines.points.length > 1
                 && lines.points[1].length > 0) {
-            NumberFormat nf = Formatter.getMeterFormat(this.context);
-            D4EArtifact flys = (D4EArtifact) master;
+            NumberFormat nf = Formatter.getMeterFormat(context);
+            D4EArtifact flys = getArtifact();
 
             String unit = RiverUtils.getRiver(flys).getWstUnit().getName();
 
@@ -380,7 +383,7 @@
             }
         }
         if (theme.parseShowMiddleHeight() && lines.width != 0) {
-            NumberFormat nf = Formatter.getMeterFormat(this.context);
+            NumberFormat nf = Formatter.getMeterFormat(context);
             String labelAdd = "T=" + nf.format(lines.area / lines.width) + "m";
             // : " + lines.area + "/" + lines.width);
             if (series.getLabel().length() == 0) {
@@ -450,9 +453,9 @@
      * @return a new <i>ChartSection</i>.
      */
     @Override
-    protected ChartSection buildChartSection() {
+    protected ChartSection buildChartSection(final CallContext context) {
         ChartSection chartSection = new ChartSection();
-        chartSection.setTitle(getChartTitle());
+        chartSection.setTitle(getChartTitle(context));
         chartSection.setDisplayGrid(isGridVisible());
         chartSection.setDisplayLogo(showLogo());
         chartSection.setLogoVPlacement(logoVPlace());
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DiagramAttributes.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DiagramAttributes.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,6 +9,8 @@
 package org.dive4elements.river.exports;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 import org.w3c.dom.Element;
@@ -82,6 +84,10 @@
         public List<Processor> getProcessors() {
             return processors;
         }
+        
+        public Collection<ChartExtender> getExtenders() {
+            return DiagramAttributes.this.getExtenders();
+        }
 
         public Title getTitle() {
             return DiagramAttributes.this.getTitle();
@@ -109,16 +115,15 @@
     } // class Instance
 
     public static class AxisAttributes {
-        private String  name;
-        private boolean isLeftAlign; // TODO: Remove!
-        private boolean forceAlign;  // TODO: Remove!
-        private boolean includeZero; // TODO: Use Evaluator
+        private final String  name;
+        private final boolean isLeftAlign; // TODO: Remove!
+        private final boolean forceAlign;  // TODO: Remove!
+        private final boolean includeZero; // TODO: Use Evaluator
 
-        private Evaluator isInverted;
-        private Evaluator isLog;
-
-        public AxisAttributes() {
-        }
+        private final Evaluator isInverted;
+        private final Evaluator isLog;
+        private final double lowerMargin;
+        private final double upperMargin;
 
         public AxisAttributes(
             String    name,
@@ -126,7 +131,9 @@
             boolean   forceAlign,
             boolean   includeZero,
             Evaluator isInverted,
-            Evaluator isLog
+            Evaluator isLog,
+            double lowerMargin,
+            double upperMargin
         ) {
             this.name        = name;
             this.isLeftAlign = isLeftAlign;
@@ -134,6 +141,8 @@
             this.includeZero = includeZero;
             this.isInverted  = isInverted;
             this.isLog       = isLog;
+            this.lowerMargin = lowerMargin;
+            this.upperMargin = upperMargin;
         }
 
         public String getName() {
@@ -159,15 +168,20 @@
         public Evaluator isLog() {
             return isLog;
         }
+        
+        public double getLowerMargin() {
+            return this.lowerMargin;
+        }
+        
+        public double getUpperMargin() {
+            return this.upperMargin;
+        }
     } // class AxisAttributes
 
     public class DomainAxisAttributes extends AxisAttributes {
 
         private Title title;
 
-        public DomainAxisAttributes() {
-        }
-
         public DomainAxisAttributes(
             String    name,
             boolean   isLeftAlign,
@@ -178,7 +192,7 @@
             Title     title
         ) {
             super(name, isLeftAlign, forceAlign, includeZero, isInverted,
-                    isLog);
+                    isLog, 0.0, 0.0);
             this.title = title;
         }
 
@@ -337,6 +351,7 @@
 
     private List<AxisAttributes> axesAttrs;
     private List<AxisProcessor>  axesProcessors;
+    private List<ChartExtender> extenders = new ArrayList<>();
 
     private Title title;
     private Title subtitle;
@@ -355,6 +370,7 @@
         parseTitle(config);
         parseSubtitle(config);
         parseDomainAxis(config);
+        parseExtenders(config);
         return this;
     }
 
@@ -375,6 +391,9 @@
             String isInverted = axisElement.getAttribute("inverted");
             String isLog = axisElement.getAttribute("logarithmic");
 
+            final double lowerMargin = parseDouble( axisElement.getAttribute("lowerMargin"), 0.0 );
+            final double upperMargin = parseDouble( axisElement.getAttribute("upperMargin"), 0.0 );
+            
             if (name.isEmpty()) {
                 continue;
             }
@@ -394,7 +413,22 @@
             axesAttrs.add(new AxisAttributes(
                 name, isleftAlign, forceAlign,
                 includeZero.equals("true"),
-                isInvertedE, isLogE));
+                isInvertedE, isLogE,
+                lowerMargin,upperMargin));
+        }
+    }
+    
+    private static double parseDouble( final String text, final double defaultValue ) {
+        if( text == null || text.isEmpty() )
+            return defaultValue;
+        
+        try {
+            return Double.parseDouble(text);
+        }
+        catch (final NumberFormatException e) {
+            e.printStackTrace();
+            log.error(String.format("Invalid double attribute: ", text), e);
+            return defaultValue;
         }
     }
 
@@ -433,6 +467,10 @@
     public List<AxisProcessor> getAxesProcessors() {
         return axesProcessors;
     }
+    
+    public Collection<ChartExtender> getExtenders() {
+        return Collections.unmodifiableCollection(extenders);
+    }
 
     public Title getTitle() {
         return title;
@@ -467,6 +505,33 @@
             }
         }
     }
+    
+    private void parseExtenders(final Element config) {
+        final NodeList processorNodes = config.getElementsByTagName("chartextender");
+
+        for (int i = 0, N = processorNodes.getLength(); i < N; ++i) {
+            final Element extenderElement = (Element)processorNodes.item(i);
+            final String className = extenderElement.getAttribute("class").trim();
+            if (className.isEmpty() ) {
+                log.error("chartextender missing 'class' attribute");
+                continue;
+            }
+
+            try {
+                final Class<?> protoclass = Class.forName(className);
+                if( !ChartExtender.class.isAssignableFrom(protoclass) ) {
+                    log.error(String.format( "Chart extender must implement interface ChartExtender: %s", className) );
+                    continue;
+                }
+                
+                final ChartExtender extender = (ChartExtender) protoclass.newInstance();
+                extenders.add(extender);
+            }
+            catch (ClassNotFoundException | InstantiationException | IllegalAccessException cnfe) {
+                log.error(String.format( "Failed to load or create chartextender class: %s", className ), cnfe);
+            }
+        }
+    }
 
     private void parseTitle(Element config) {
         title = extractTitle(config, "title");
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,72 +10,52 @@
 
 import java.awt.Color;
 import java.awt.Font;
-
 import java.text.NumberFormat;
-
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-
-import java.io.OutputStream;
 
 import javax.swing.ImageIcon;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
-
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifactdatabase.state.Facet;
-
 import org.dive4elements.artifacts.CallContext;
-
 import org.dive4elements.river.artifacts.D4EArtifact;
-
+import org.dive4elements.river.exports.DiagramAttributes.AxisAttributes;
 import org.dive4elements.river.exports.process.Processor;
-
-import org.dive4elements.river.jfree.RiverAnnotation;
-import org.dive4elements.river.jfree.AnnotationHelper;
 import org.dive4elements.river.jfree.AxisDataset;
 import org.dive4elements.river.jfree.Bounds;
 import org.dive4elements.river.jfree.DoubleBounds;
+import org.dive4elements.river.jfree.RiverAnnotation;
 import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
 import org.dive4elements.river.jfree.XYMetaSeriesCollection;
-
 import org.dive4elements.river.themes.ThemeDocument;
-
 import org.jfree.chart.ChartFactory;
 import org.jfree.chart.JFreeChart;
 import org.jfree.chart.LegendItem;
-
 import org.jfree.chart.annotations.XYAnnotation;
 import org.jfree.chart.annotations.XYImageAnnotation;
-
 import org.jfree.chart.axis.LogarithmicAxis;
 import org.jfree.chart.axis.NumberAxis;
 import org.jfree.chart.axis.ValueAxis;
-
 import org.jfree.chart.plot.Marker;
 import org.jfree.chart.plot.PlotOrientation;
 import org.jfree.chart.plot.XYPlot;
-
 import org.jfree.data.Range;
-
 import org.jfree.data.general.Series;
-
 import org.jfree.data.xy.XYDataset;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
 
-import org.w3c.dom.Document;
-
-import org.apache.commons.lang.StringUtils;
-
 
 /**
  * The main diagram creation class.
@@ -101,9 +81,9 @@
     /** The log that is used in this generator. */
     private static Logger log = Logger.getLogger(DiagramGenerator.class);
 
-    protected List<Marker> domainMarkers = new ArrayList<Marker>();
+    protected List<Marker> domainMarkers = new ArrayList<>();
 
-    protected List<Marker> valueMarkers = new ArrayList<Marker>();
+    protected List<Marker> valueMarkers = new ArrayList<>();
 
     /** The max X range to include all X values of all series for each axis. */
     protected Map<Integer, Bounds> xBounds;
@@ -143,17 +123,7 @@
         diagramAttributes = da.new Instance();
     }
 
-    @Override
-    public void init(
-        String       outName,
-        Document     request,
-        OutputStream out,
-        CallContext  context
-    ) {
-        super.init(outName, request, out, context);
-    }
-
-    private void setInvertedFromConfig() {
+    private void setInvertedFromConfig(CallContext context) {
         DiagramAttributes.DomainAxisAttributes dx =
             diagramAttributes.getDomainAxis();
 
@@ -174,13 +144,13 @@
      * Generate the chart anew (including localized axis and all).
      */
     @Override
-    public JFreeChart generateChart() {
+    protected JFreeChart generateChart(CallContext context) {
         log.debug("DiagramGenerator.generateChart");
 
         postProcess();
 
         JFreeChart chart = ChartFactory.createXYLineChart(
-            getChartTitle(),
+            getChartTitle(context),
             "",
             "",
             null,
@@ -190,12 +160,13 @@
             false);
 
         XYPlot plot = (XYPlot) chart.getPlot();
-        ValueAxis axis = createXAxis(getXAxisLabel());
+        ValueAxis axis = createXAxis(context, getXAxisLabel());
         plot.setDomainAxis(axis);
 
         chart.setBackgroundPaint(Color.WHITE);
         plot.setBackgroundPaint(Color.WHITE);
-        addSubtitles(chart);
+        addSubtitles(context, chart);
+        addMetadataSubtitle(context, chart);
         adjustPlot(plot);
 
         //debugAxis(plot);
@@ -213,7 +184,7 @@
 
         localizeAxes(plot);
 
-        setInvertedFromConfig();
+        setInvertedFromConfig(context);
 
         adjustAxes(plot);
         if (!(axis instanceof LogarithmicAxis)) {
@@ -228,23 +199,23 @@
         //debugAxis(plot);
 
         // These have to go after the autozoom.
-        AnnotationHelper.addAnnotationsToRenderer(annotations, plot,
-                getChartSettings(), datasets);
-        AnnotationHelper.addYAnnotationsToRenderer(yAnnotations, plot,
-                getChartSettings(), datasets);
+        addAnnotationsToRenderer(plot);
+        addYAnnotationsToRenderer(plot);
 
         // Add a logo (maybe).
         addLogo(plot);
 
         aggregateLegendEntries(plot);
 
+        /* allow extenders to do some work */
+        final Collection<ChartExtender> extenders = this.diagramAttributes.getExtenders();
+        for (final ChartExtender extender : extenders) {
+            extender.afterGenerateChart(this, plot);
+        }
+        
         return chart;
     }
 
-    public String getOutName() {
-        return outName;
-    }
-
     /**
      * Return left most data points x value (on first axis).
      */
@@ -385,14 +356,25 @@
     }
 
 
-    protected NumberAxis createXAxis(String label) {
+    protected NumberAxis createXAxis(final CallContext context, String label) {
         boolean logarithmic = (Boolean)diagramAttributes.getDomainAxis().
             isLog().evaluate((D4EArtifact)getMaster(), context);
 
         if (logarithmic) {
-            return new LogarithmicAxis(label);
+            final LogarithmicAxis axis = new LogarithmicAxis(label);
+            // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+            axis.setLowerMargin(0);
+            axis.setUpperMargin(0);
+            return axis;
         }
-        return new NumberAxis(label);
+        final NumberAxis axis = new NumberAxis(label);
+        // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+        axis.setLowerMargin(0);
+        axis.setUpperMargin(0);
+        // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+        axis.setLowerMargin(0);
+        axis.setUpperMargin(0);
+        return axis;
     }
 
 
@@ -491,13 +473,31 @@
 
         AxisDataset axisDataset = (AxisDataset) getAxisDataset(index);
 
+        Bounds[] xyBounds = ChartHelper.getBounds(area);
+
+        if (xyBounds == null) {
+            log.warn("Skip XYDataset for Axis (invalid ranges): " + index);
+            return;
+        }
+        
+
         if (visible) {
+            if (log.isDebugEnabled()) {
+                log.debug("Add new AxisDataset at index: " + index);
+                log.debug("X extent: " + xyBounds[0]);
+                log.debug("Y extent: " + xyBounds[1]);
+            }
+
             axisDataset.addArea(area);
         }
-        else {
-            /* No range merging, for areas extending to infinity this
-             * causes problems. */
-        }
+
+        /* No range merging, for areas extending to infinity this causes problems. */
+        /* No range merging, for areas extending to infinity this causes problems. */
+        if( StyledSeriesBuilder.isBigDoubleValue( xyBounds[1].getLower() ) || StyledSeriesBuilder.isBigDoubleValue( xyBounds[1].getLower() ) )
+            return;
+        
+        combineXBounds(xyBounds[0], 0);
+        combineYBounds(xyBounds[1], index);
     }
 
     /**
@@ -701,6 +701,12 @@
     protected void autoZoom(XYPlot plot) {
         log.debug("Zoom to specified ranges.");
 
+        /* allow chart extenders to tweak zoom behavior */
+        final Collection<ChartExtender> extenders = this.diagramAttributes.getExtenders();
+        for (final ChartExtender extender : extenders) {
+            extender.beforeAutoZoom(this);
+        }        
+
         Range xrange = getDomainAxisRange();
         Range yrange = getValueAxisRange();
 
@@ -735,9 +741,12 @@
             log.debug("Prepare zoom settings for y axis at index: " + i);
             zoom(plot, yaxis, getYBounds(Integer.valueOf(i)), yrange);
         }
+        
+        for (final ChartExtender extender : extenders) {
+            extender.afterAutoZoom(this);
+        }
     }
 
-
     protected Range getDomainAxisRange() {
         String[] ranges = getDomainAxisRangeFromRequest();
 
@@ -1067,7 +1076,7 @@
     }
 
     @Override
-    public String getDefaultChartTitle() {
+    protected final String getDefaultChartTitle(CallContext context) {
         DiagramAttributes.Title dTitle = diagramAttributes.getTitle();
         if (dTitle == null) {
             return "Title not configured in conf.xml";
@@ -1076,8 +1085,9 @@
         return dTitle.evaluate((D4EArtifact)getMaster(), context);
     }
 
+    
     @Override
-    public String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(CallContext context) {
         String parts = "";
         DiagramAttributes.Title dTitle = diagramAttributes.getSubtitle();
         if (dTitle == null &&
@@ -1108,7 +1118,7 @@
      * Get internationalized label for the x axis.
      */
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(CallContext context) {
         DiagramAttributes.DomainAxisAttributes dx =
             diagramAttributes.getDomainAxis();
 
@@ -1121,8 +1131,7 @@
         return "Domain Axis Title not configured in conf.xml";
     }
 
-    @Override
-    protected String getDefaultYAxisLabel(String axisName) {
+    protected final String getDefaultYAxisLabel(String axisName) {
         Set labelSet = axesLabels.get(diagramAttributes.getAxisIndex(axisName));
         log.debug("Labels for axis: " + labelSet);
         if (labelSet != null && !labelSet.isEmpty()) {
@@ -1152,8 +1161,9 @@
      *
      * @return a list of Y axis sections.
      */
-    protected List<AxisSection> buildYAxisSections() {
-        List<AxisSection> axisSections = new ArrayList<AxisSection>();
+    @Override
+    protected final List<AxisSection> buildYAxisSections() {
+        List<AxisSection> axisSections = new ArrayList<>();
 
         List<DiagramAttributes.AxisAttributes> axesAttrs =
             diagramAttributes.getAxesAttributes();
@@ -1266,19 +1276,25 @@
 
     @Override
     protected NumberAxis createYAxis(int index) {
+        
+        final AxisAttributes axisAttributes = diagramAttributes.getAxesAttributes().get(index);
+        
+        boolean logarithmic = (Boolean)axisAttributes.isLog().evaluate((D4EArtifact)getMaster(), getContext());
+
         NumberAxis axis;
-        boolean logarithmic = (Boolean)diagramAttributes.getAxesAttributes().
-            get(index).isLog().evaluate((D4EArtifact)getMaster(), context);
-
         if (logarithmic) {
             axis = new LogarithmicAxis(getYAxisLabel(index));
         } else {
             axis = super.createYAxis(index);
         }
 
-        if (diagramAttributes.getAxesAttributes().get(index).includeZero()) {
+        if (axisAttributes.includeZero()) {
             axis.setAutoRangeIncludesZero(true);
         }
+        
+        axis.setLowerMargin(axisAttributes.getLowerMargin());
+        axis.setUpperMargin(axisAttributes.getUpperMargin());
+        
         return axis;
     }
 
@@ -1295,4 +1311,4 @@
     public void addSubtitle(String part) {
         this.subTitleParts.add(part);
     }
-}
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -28,6 +28,7 @@
 import org.dive4elements.river.themes.ThemeDocument;
 
 import org.dive4elements.artifactdatabase.state.State;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.GaugeDischargeCurveArtifact;
 
 import org.apache.log4j.Logger;
@@ -121,8 +122,8 @@
         if (getMaster() instanceof GaugeDischargeCurveArtifact) {
             GaugeDischargeCurveArtifact myMaster =
                 (GaugeDischargeCurveArtifact) getMaster();
-            State state = myMaster.getCurrentState(context);
-            if (myMaster.STATIC_STATE_NAME.equals(state.getID())) {
+            State state = myMaster.getCurrentState(getContext());
+            if (GaugeDischargeCurveArtifact.STATIC_STATE_NAME.equals(state.getID())) {
                 return;
             }
         }
@@ -213,13 +214,13 @@
      * Returns always null to suppress subtitles.
      */
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return null;
     }
 
 
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
     }
 
@@ -278,6 +279,8 @@
         String name = artifactFacet.getFacetName();
         log.debug("DischargeCurveGenerator.doOut: " + name);
 
+        final CallContext context = getContext();
+        
         MiscDischargeProcessor dProcessor = new MiscDischargeProcessor(
             getRange()[0]);
         if (dProcessor.canHandle(name)) {
@@ -376,8 +379,7 @@
         double y,
         ThemeDocument theme
     ) {
-        List<XYTextAnnotation> textAnnos =
-            new ArrayList<XYTextAnnotation>();
+        final List<XYTextAnnotation> textAnnos = new ArrayList<>();
         XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
                 title,
                 x,
@@ -429,8 +431,7 @@
 
         // If no Q values (i.e. all -1) found, add annotations.
         if (hasNoDischarge(data)) {
-            List<StickyAxisAnnotation> xy =
-                new ArrayList<StickyAxisAnnotation>();
+            final List<StickyAxisAnnotation> xy = new ArrayList<>();
 
             for (double y: data[1]) {
                 if (translate != 0d) {
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DischargeGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DischargeGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -39,7 +39,7 @@
     public void addDatasets(XYPlot plot) {
         super.addDatasets(plot);
 
-        Object pnp = context.getContextValue(PNP);
+        Object pnp = getContext().getContextValue(PNP);
         if (!(pnp instanceof Number)) {
             return;
         }
@@ -52,7 +52,7 @@
             return;
         }
 
-        AxisDataset data = datasets.get(wAxisIndex);
+        AxisDataset data = getDatasets().get(wAxisIndex);
         if (data == null) {
             // No W axis
             return;
@@ -94,8 +94,7 @@
             getYAxisFontSize(wAxisIndex));
 
         String axisName = "W.in.cm";
-        String axisLabel = Resources.getMsg(context.getMeta(),
-            I18N_AXIS_LABEL, "W [cm]");
+        String axisLabel = msg( I18N_AXIS_LABEL, "W [cm]" );
 
         IdentifiableNumberAxis axis = new IdentifiableNumberAxis(
             axisName, axisLabel);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,6 +9,7 @@
 package org.dive4elements.river.exports;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.jfree.Bounds;
@@ -95,13 +96,13 @@
 
 
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
     }
 
 
     @Override
-    protected String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(final CallContext context) {
         double[] dist  = getRange();
 
         Object[] args = new Object[] {
@@ -114,7 +115,7 @@
 
 
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
     }
 
@@ -123,7 +124,7 @@
     protected String getDefaultYAxisLabel(int index) {
         String label = "default";
         if (index == YAXIS.W.idx) {
-            label = msg(I18N_YAXIS_LABEL_W, new Object[] { getRiverUnit() });
+            label = msg(I18N_YAXIS_LABEL_W, I18N_YAXIS_LABEL_W, new Object[] { getRiverUnit() });
         }
         else if (index == YAXIS.Q.idx) {
             label = msg(I18N_YAXIS_LABEL_Q);
@@ -192,6 +193,8 @@
             log.error("No facet given. Cannot create dataset.");
             return;
         }
+        
+        final CallContext context = getContext();
 
         if (name.equals(DURATION_W)) {
             doWOut(
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ExportSection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ExportSection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -18,13 +18,15 @@
     public static final String WIDTH_ATTR  = "width";
     public static final String HEIGHT_ATTR = "height";
 
+    private static final String METADATA_ATTR = "chart_settings_export_metadata";
+
 
     public ExportSection() {
         super("export");
     }
 
 
-    public void setWidth(int width) {
+    public void setWidth(final int width) {
         if (width <= 0) {
             return;
         }
@@ -38,7 +40,7 @@
     }
 
 
-    public void setHeight(int height) {
+    public void setHeight(final int height) {
         if (height <= 0) {
             return;
         }
@@ -50,5 +52,12 @@
     public Integer getHeight() {
         return getIntegerValue(HEIGHT_ATTR);
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+    public void setMetadata(final boolean metadata) {
+        setBooleanValue(METADATA_ATTR, metadata);
+    }
+
+    public boolean getMetadata() {
+        return getBooleanValue(METADATA_ATTR, true);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -13,7 +13,7 @@
 import org.apache.log4j.Logger;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
-
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
 
 import org.dive4elements.river.artifacts.access.HistoricalDischargeAccess;
@@ -90,13 +90,13 @@
     }
 
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE);
     }
 
     @Override
-    protected String getDefaultChartSubtitle() {
-        D4EArtifact flys = (D4EArtifact) master;
+    protected String getDefaultChartSubtitle(final CallContext context) {
+        D4EArtifact flys = getArtifact();
         Timerange evalTime = new HistoricalDischargeAccess(flys)
             .getEvaluationTimerange();
 
@@ -107,7 +107,7 @@
     }
 
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL);
     }
 
@@ -138,6 +138,8 @@
         log.debug("Theme description is: "
             + artifactFacet.getFacetDescription());
 
+        final CallContext context = getContext();
+        
         if (name.equals(HISTORICAL_DISCHARGE_Q)) {
             doHistoricalDischargeOutQ(
                 (D4EArtifact) artifactFacet.getArtifact(),
--- a/artifacts/src/main/java/org/dive4elements/river/exports/LegendSection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/LegendSection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -55,8 +55,8 @@
     }
 
 
-    public Boolean getVisibility() {
-        return getBooleanValue(VISIBILITY_ATTR);
+    public boolean getVisibility() {
+        return getBooleanValue(VISIBILITY_ATTR, true);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,6 +10,7 @@
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.geom.Lines;
 import org.dive4elements.river.artifacts.model.AreaFacet;
@@ -157,18 +158,17 @@
      * @return the default title for this chart.
      */
     @Override
-    public String getDefaultChartTitle() {
+    public String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
     }
 
-
     /**
      * Returns the default subtitle for this chart.
      *
      * @return the default subtitle for this chart.
      */
     @Override
-    protected String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(final CallContext context) {
         double[] dist = getRange();
 
         Object[] args = null;
@@ -208,8 +208,8 @@
      * Get internationalized label for the x axis.
      */
     @Override
-    protected String getDefaultXAxisLabel() {
-        D4EArtifact flys = (D4EArtifact) master;
+    protected String getDefaultXAxisLabel(CallContext context) {
+        D4EArtifact flys = getArtifact();
 
         return msg(
             I18N_XAXIS_LABEL,
@@ -241,7 +241,7 @@
      * Get internationalized label for the y axis.
      */
     protected String getWAxisLabel() {
-        D4EArtifact flys = (D4EArtifact) master;
+        D4EArtifact flys = getArtifact();
 
         String unit = RiverUtils.getRiver(flys).getWstUnit().getName();
 
@@ -340,6 +340,8 @@
             return;
         }
 
+        CallContext context = getContext();
+        
         Processor wProcessor = new WOutProcessor();
         Processor qProcessor = new QOutProcessor();
         Processor bdyProcessor = new BedDiffYearProcessor();
--- a/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator2.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator2.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,6 +10,7 @@
 
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.jfree.Bounds;
 import org.dive4elements.river.themes.ThemeDocument;
 import org.dive4elements.river.artifacts.model.FacetTypes;
@@ -62,7 +63,7 @@
         "chart.subtitle.radius";
 
     @Override
-    public String getDefaultChartSubtitle() {
+    public String getDefaultChartSubtitle(final CallContext context) {
         double[] dist = getRange();
 
         String parts = "";
@@ -124,6 +125,7 @@
 
         // This might not be neccessary if every facet uses only the
         // radius and does not do its own zoomscale calculation.
+        final CallContext context = getContext();
         context.putContextValue("startkm", candidate.getLowerBound());
         context.putContextValue("endkm", candidate.getUpperBound());
         context.putContextValue("bounds_defined", true);
@@ -146,6 +148,7 @@
         }
 
         // fake startkm and endkm for the dry run
+        final CallContext context = getContext();
         context.putContextValue("startkm", 0d);
         context.putContextValue("endkm", 42d);
         for (SuperBundle superbundle: postOutAF) {
@@ -185,15 +188,13 @@
 
             SuperBundle superbundle = new SuperBundle(bundle, theme, visible);
             if (postOutAF == null) {
-                postOutAF = new ArrayList<SuperBundle>();
+                postOutAF = new ArrayList<>();
             }
             postOutAF.add(superbundle);
             if (visible) {
                 log.debug("Adding radius subtitle.");
 
-                addSubtitle(Resources.getMsg(
-                            getCallContext().getMeta(),
-                            I18N_SUBTITLE_RADIUS) + ": $RADIUS");
+                addSubtitle(msg(I18N_SUBTITLE_RADIUS) + ": $RADIUS");
             }
             return;
         }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/NormalizedReferenceCurveGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/NormalizedReferenceCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,6 +8,8 @@
 
 package org.dive4elements.river.exports;
 
+import org.dive4elements.artifacts.CallContext;
+
 /**
  * An OutGenerator that generates reference curves.
  */
@@ -25,7 +27,7 @@
 
     /** Get default chart title. */
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return msg(
             I18N_NORMALIZED_CHART_TITLE,
             I18N_NORMALIZED_CHART_TITLE_DEFAULT);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,6 +9,7 @@
 package org.dive4elements.river.exports;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.WW;
 import org.dive4elements.river.artifacts.model.WW.ApplyFunctionIterator;
@@ -86,12 +87,12 @@
 
     /** Get default chart title. */
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
     }
 
     @Override
-    protected String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(final CallContext context) {
         Object[] args = new Object[] {
             getRiverName(),
         };
@@ -102,14 +103,14 @@
 
     /** True if axis is in cm (because at gauge). */
     protected boolean getInCm(int index) {
-        Object obj = context.getContextValue("reference.curve.axis.scale");
+        Object obj = getContext().getContextValue("reference.curve.axis.scale");
         return obj instanceof WWAxisTypes && ((WWAxisTypes)obj).getInCm(index);
     }
 
 
     /** Get Label for X-axis (W). */
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(getInCm(0) ? I18N_X_AXIS_IN_CM : I18N_X_AXIS_IN_M);
     }
 
@@ -149,6 +150,8 @@
             return;
         }
 
+        final CallContext context = getContext();
+        
         if (name.equals(facetName())) {
             doReferenceOut(artifactFacet.getData(context), theme, visible);
         }
@@ -194,7 +197,7 @@
     ) {
         WW ww = (WW)data;
 
-        Object obj = context.getContextValue("reference.curve.axis.scale");
+        Object obj = getContext().getContextValue("reference.curve.axis.scale");
 
         WWAxisTypes wwat = obj instanceof WWAxisTypes
             ? (WWAxisTypes)obj
@@ -236,7 +239,7 @@
     /** Set the tick units for given axis. */
     protected void setAxisTickUnit(double tick, ValueAxis axis) {
         TickUnits units = new TickUnits();
-        units.add(new NumberTickUnit(tick, Formatter.getWaterlevelW(context)));
+        units.add(new NumberTickUnit(tick, Formatter.getWaterlevelW(getContext())));
         axis.setStandardTickUnits(units);
         axis.setAutoTickUnitSelection(true);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -400,5 +400,14 @@
         ground.add(series.getMaxX(), BIG_DOUBLE_VALUE);
         return ground;
     }
+
+
+    /** Checks if a given value is the BIG_DOUBLE_VALUE  */
+    public static boolean isBigDoubleValue(Number value) {
+        if( value == null )
+            return false;
+        
+        return Math.abs( BIG_DOUBLE_VALUE  - Math.abs(value.doubleValue()) ) < 0.1;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,12 +9,12 @@
 package org.dive4elements.river.exports;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.jfree.Bounds;
 import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation;
 import org.dive4elements.river.jfree.DoubleBounds;
 import org.dive4elements.river.jfree.RiverAnnotation;
-import org.dive4elements.river.jfree.AnnotationHelper;
 import org.dive4elements.river.jfree.StyledTimeSeries;
 import org.dive4elements.river.jfree.TimeBounds;
 import org.dive4elements.river.jfree.AxisDataset;
@@ -93,14 +93,12 @@
         attributes = new HashMap<String, String>();
     }
 
-
-
     @Override
-    public JFreeChart generateChart() {
+    protected JFreeChart generateChart(CallContext context) {
         log.info("Generate Timeseries Chart.");
 
         JFreeChart chart = ChartFactory.createTimeSeriesChart(
-            getChartTitle(),
+            getChartTitle(context),
             getXAxisLabel(),
             getYAxisLabel(0),
             null,
@@ -113,7 +111,8 @@
         chart.setBackgroundPaint(Color.WHITE);
         plot.setBackgroundPaint(Color.WHITE);
 
-        addSubtitles(chart);
+        addSubtitles(context, chart);
+        addMetadataSubtitle( context, chart );
         adjustPlot(plot);
         addDatasets(plot);
         adjustAxes(plot);
@@ -125,11 +124,8 @@
 
         consumeAxisSettings(plot);
 
-        AnnotationHelper.addAnnotationsToRenderer(
-            annotations,
-            plot,
-            getChartSettings(),
-            datasets);
+        addAnnotationsToRenderer(plot);
+        
         addLogo(plot);
         aggregateLegendEntries(plot);
         return chart;
@@ -628,7 +624,7 @@
         catch(JSONException ex) {
             String str = array.getString(0);
             DateFormat df = DateFormat.getDateInstance(
-                    DateFormat.MEDIUM, Resources.getLocale(context.getMeta()));
+                    DateFormat.MEDIUM, Resources.getLocale(getContext().getMeta()));
             return df.parse(str);
         }
     }
@@ -855,7 +851,7 @@
      * setLowerTimeRange */
     @Override
     protected List<AxisSection> buildXAxisSections() {
-        List<AxisSection> axisSections = new ArrayList<AxisSection>();
+        List<AxisSection> axisSections = new ArrayList<>();
 
         String identifier = "X";
 
--- a/artifacts/src/main/java/org/dive4elements/river/exports/TypeSection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/TypeSection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -123,26 +123,25 @@
     }
 
 
-    public void setBooleanValue(String key, boolean value) {
-        Attribute attr = getAttribute(key);
-        if (attr == null) {
-            attr = new BooleanAttribute(key, value, true);
-            addAttribute(key, attr);
-        }
-        else {
+    protected final void setBooleanValue(String key, boolean value) {
+        final Attribute attr = getAttribute(key);
+        if (attr == null)
+            addAttribute(key, new BooleanAttribute(key, value, true));
+        else 
             attr.setValue(value);
-        }
     }
 
-
-    public Boolean getBooleanValue(String key) {
-        Attribute attr = getAttribute(key);
+    protected final boolean getBooleanValue(final String key, boolean defaultValue) {
+        final Attribute attr = getAttribute(key);
 
         if (attr instanceof BooleanAttribute) {
-            return (Boolean) attr.getValue();
+            final Boolean value = (Boolean) attr.getValue();
+            if( value == null )
+                return defaultValue;
+            
+            return value;
         }
 
-        return null;
+        return defaultValue;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelDescriptionBuilder.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,213 @@
+/** 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.exports;
+
+import java.text.NumberFormat;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.utils.Formatter;
+import org.dive4elements.river.utils.RiverUtils;
+import org.dive4elements.river.utils.RiverUtils.WQ_MODE;
+
+/**
+ * Helper that encapsulates the logic how the 'description' column in waterlevel exporting is generated.
+ * TODO: this class should also be used in WaterlevelExport (all code is copied from there), but this would involve
+ * heavy testing and we leave this to the one who is responsible to clean up this mess.
+ *
+ * @author Gernot Belger
+ */
+public final class WaterlevelDescriptionBuilder {
+
+    private static final String CSV_META_Q = "export.waterlevel.csv.meta.q";
+
+    // FIXME: unit 'NN + m' is wrong:
+    // - use river-elevation system in case of absolute heights
+    // - use 'cm am Pegel' in other cases
+    private static final String CSV_META_W = "export.waterlevel.csv.meta.w";
+
+    private static final String CSV_Q_DESC_HEADER = "export.waterlevel.csv.header.q.desc";
+
+    // FIXME: missing in resource-files! hence always the default is used...
+    private static final String CSV_W_DESC_HEADER = "export.waterlevel.csv.header.w.desc";
+
+    private static final String DEFAULT_CSV_Q_DESC_HEADER = "Bezeichnung";
+
+    private static final String DEFAULT_CSV_W_DESC_HEADER = "W/Pegel [cm]";
+
+    private final boolean isQ;
+
+    private final boolean atGauge;
+
+    private final CallContext context;
+
+    private final WQ_MODE mode;
+
+    private final D4EArtifact artifact;
+
+    public WaterlevelDescriptionBuilder(final D4EArtifact artifact, final CallContext context) {
+        this.context = context;
+
+        // REMARK: taken from WaterlevelExporter, should be moved into WInfoArtifact
+        this.mode = RiverUtils.getWQMode(artifact);
+        this.atGauge = this.mode == WQ_MODE.QGAUGE || this.mode == WQ_MODE.WGAUGE;
+        this.isQ = this.mode == WQ_MODE.QGAUGE || this.mode == WQ_MODE.QFREE;
+
+        this.artifact = artifact;
+    }
+
+    public boolean isAtGauge() {
+        return this.atGauge;
+    }
+
+    public String getMetadata() {
+
+        switch (this.mode) {
+        case QFREE:
+        case QGAUGE: {
+            final String data = getMetadataQ();
+            if (data == null)
+                return null;
+
+            return Resources.getMsg(this.context.getMeta(), CSV_META_Q, CSV_META_Q, data);
+        }
+
+        // TODO: probably none, default is wrong here, but this how it was implemented in WaterlevelExporter.
+        case WFREE:
+        case WGAUGE:
+        case NONE:
+        default:
+            final double[] ws = RiverUtils.getWs(this.artifact);
+
+            if (ws == null || ws.length <= 0)
+                return null;
+
+            // FIXME: we also have here a case single?!
+
+            // FIXME: use correct wst unit!
+
+            // FIXME: bad formatting ofd values. Use the correct Formatter!
+            final String lower = String.valueOf(ws[0]);
+            final String upper = String.valueOf(ws[ws.length - 1]);
+
+            return Resources.getMsg(this.context.getMeta(), CSV_META_W, CSV_META_W, lower, upper);
+        }
+    }
+
+    private String getMetadataQ() {
+
+        final double[] qs = RiverUtils.getQs(this.artifact);
+        if (qs == null || qs.length == 0)
+            return null;
+
+        final RiverUtils.WQ_INPUT input = RiverUtils.getWQInputMode(this.artifact);
+
+        switch (input) {
+        case ADAPTED:
+        case RANGE:
+            return String.valueOf(qs[0]) + " - " + String.valueOf(qs[qs.length - 1]);
+
+        case SINGLE:
+            String data = String.valueOf(qs[0]);
+            for (int i = 1; i < qs.length; i++)
+                data += ", " + String.valueOf(qs[i]);
+            return data;
+
+        default:
+            return null;
+        }
+    }
+
+    public String getColumnHeader() {
+
+        if (!this.atGauge)
+            return null;
+
+        // REMARK: bad inter-dependency to WaterlevelExporter, but we want to really copy the logic from WInfo
+        if (this.isQ)
+            return Resources.getMsg(this.context.getMeta(), CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER);
+
+        return Resources.getMsg(this.context.getMeta(), CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER);
+    }
+
+    public String getDesc(final WQKms wqkms) {
+        return getDesc(wqkms, this.isQ);
+    }
+
+    public String getDesc(final WQKms wqkms, final boolean isQoverride) {
+        String colDesc = "";
+
+        if (this.artifact instanceof WINFOArtifact && isQoverride) {
+            colDesc = getCSVRowTitle((WINFOArtifact) this.artifact, wqkms);
+        } else if (!isQoverride) {
+            final Double value = RiverUtils.getValueFromWQ(wqkms);
+            colDesc = (value != null) ? Formatter.getWaterlevelW(this.context).format(value) : null;
+        }
+
+        if (this.artifact instanceof WINFOArtifact) {
+            if (wqkms != null && wqkms.getRawValue() != null) {
+                final WINFOArtifact winfo = (WINFOArtifact) this.artifact;
+                colDesc = RiverUtils.getNamedMainValue(winfo, wqkms.getRawValue());
+                // For 'W am Pegel' s
+                if (colDesc == null) {
+                    final Double value = RiverUtils.getValueFromWQ(wqkms);
+                    colDesc = (value != null) ? Formatter.getWaterlevelW(this.context).format(value) : null;
+                }
+            }
+        }
+
+        if (colDesc == null)
+            return "";
+
+        /*
+         * Quick hack. Can be removed when database strings are
+         * adapted or left in here as it should never be harmful.
+         */
+        return colDesc.replace("Amtl.Festlegung_", "Amtl. ");
+    }
+
+    private String getCSVRowTitle(final WINFOArtifact winfo, final WQKms wqkms) {
+
+        if (this.mode == WQ_MODE.WFREE || this.mode == WQ_MODE.QGAUGE)
+            return localizeWQKms(wqkms);
+
+        final Double v = wqkms.getRawValue();
+
+        final String nmv = RiverUtils.getNamedMainValue(winfo, v);
+
+        if (nmv != null && nmv.length() > 0) {
+            return RiverUtils.stripNamedMainValue(nmv);
+        }
+
+        return localizeWQKms(wqkms);
+    }
+
+    /**
+     * Get a string like 'W=' or 'Q=' with a number following in localized
+     * format.
+     */
+    private String localizeWQKms(final WQKms wqkms) {
+        final Double rawValue = wqkms.getRawValue();
+
+        if (rawValue == null) {
+            return wqkms.getName();
+        }
+
+        final NumberFormat nf = Formatter.getRawFormatter(this.context);
+
+        if (this.mode == WQ_MODE.WFREE || this.mode == WQ_MODE.WGAUGE)
+            return "W=" + nf.format(rawValue);
+
+        return "Q=" + nf.format(rawValue);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -13,52 +13,45 @@
 import java.text.DateFormat;
 import java.text.NumberFormat;
 import java.util.ArrayList;
-import java.util.Map;
+import java.util.Date;
 import java.util.HashMap;
-import java.util.Date;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
-
-import au.com.bytecode.opencsv.CSVWriter;
-
-import gnu.trove.TDoubleArrayList;
-
-import org.dive4elements.river.artifacts.model.ConstantWQKms;
-
-import net.sf.jasperreports.engine.JasperExportManager;
-import net.sf.jasperreports.engine.JasperFillManager;
-import net.sf.jasperreports.engine.JasperPrint;
-import net.sf.jasperreports.engine.JRException;
-
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.artifacts.common.utils.Config;
-
-import org.dive4elements.river.model.Gauge;
-
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.FixationArtifact;
+import org.dive4elements.river.artifacts.StaticWQKmsArtifact;
+import org.dive4elements.river.artifacts.WINFOArtifact;
 import org.dive4elements.river.artifacts.access.FixRealizingAccess;
 import org.dive4elements.river.artifacts.access.IsOfficialAccess;
 import org.dive4elements.river.artifacts.access.RangeAccess;
-import org.dive4elements.river.artifacts.FixationArtifact;
-import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.WINFOArtifact;
-import org.dive4elements.river.artifacts.StaticWQKmsArtifact;
 import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.ConstantWQKms;
 import org.dive4elements.river.artifacts.model.Segment;
+import org.dive4elements.river.artifacts.model.WKmsJRDataSource;
 import org.dive4elements.river.artifacts.model.WQCKms;
 import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.model.WQKmsResult;
 import org.dive4elements.river.artifacts.model.WstLine;
-import org.dive4elements.river.artifacts.model.WKmsJRDataSource;
-import org.dive4elements.river.artifacts.model.WQKmsResult;
 import org.dive4elements.river.artifacts.resources.Resources;
-
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.utils.Formatter;
 import org.dive4elements.river.utils.RiverUtils;
 import org.dive4elements.river.utils.RiverUtils.WQ_MODE;
-import org.dive4elements.river.utils.Formatter;
+
+import au.com.bytecode.opencsv.CSVWriter;
+import gnu.trove.TDoubleArrayList;
+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 (wst, csv, pdf) of data that resulted from
@@ -68,7 +61,7 @@
  */
 public class WaterlevelExporter extends AbstractExporter {
 
-    /** The log used in this exporter.*/
+    /** The log used in this exporter. */
     private static Logger log = Logger.getLogger(WaterlevelExporter.class);
 
     public static final String FACET_WST = "wst";
@@ -76,150 +69,141 @@
     /* This should be the same as in the StaticWQKmsArtifact */
     public static final String STATICWQKMSNAME = "staticwqkms";
 
-    public static final String CSV_KM_HEADER =
-        "export.waterlevel.csv.header.km";
-
-    public static final String CSV_W_HEADER =
-        "export.waterlevel.csv.header.w";
-
-    public static final String CSV_Q_HEADER =
-        "export.waterlevel.csv.header.q";
-
-    public static final String CSV_Q_DESC_HEADER =
-        "export.waterlevel.csv.header.q.desc";
-
-    public static final String CSV_W_DESC_HEADER =
-        "export.waterlevel.csv.header.w.desc";
-
-    public static final String CSV_LOCATION_HEADER =
-        "export.waterlevel.csv.header.location";
-
-    public static final String CSV_GAUGE_HEADER =
-        "export.waterlevel.csv.header.gauge";
-
-    public static final String CSV_META_RESULT =
-        "export.waterlevel.csv.meta.result";
-
-    public static final String CSV_META_CREATION =
-        "export.waterlevel.csv.meta.creation";
-
-    public static final String CSV_META_CALCULATIONBASE =
-        "export.waterlevel.csv.meta.calculationbase";
+    public static final String CSV_KM_HEADER = "export.waterlevel.csv.header.km";
 
-    public static final String CSV_META_RIVER =
-        "export.waterlevel.csv.meta.river";
-
-    public static final String CSV_META_RANGE =
-        "export.waterlevel.csv.meta.range";
-
-    public static final String CSV_META_GAUGE =
-        "export.waterlevel.csv.meta.gauge";
-
-    public static final String CSV_META_Q =
-        "export.waterlevel.csv.meta.q";
-
-    public static final String CSV_META_W =
-        "export.waterlevel.csv.meta.w";
+    public static final String CSV_W_HEADER = "export.waterlevel.csv.header.w";
 
-    public static final String CSV_NOT_IN_GAUGE_RANGE =
-        "export.waterlevel.csv.not.in.gauge.range";
-
-    public static final Pattern NUMBERS_PATTERN =
-        Pattern.compile("\\D*(\\d++.\\d*)\\D*");
+    public static final String CSV_Q_HEADER = "export.waterlevel.csv.header.q";
 
-    public static final String DEFAULT_CSV_KM_HEADER       = "Fluss-Km";
-    public static final String DEFAULT_CSV_W_HEADER        = "W [NN + m]";
-    public static final String DEFAULT_CSV_Q_HEADER        = "Q [m\u00b3/s]";
-    public static final String DEFAULT_CSV_Q_DESC_HEADER   = "Bezeichnung";
-    public static final String DEFAULT_CSV_W_DESC_HEADER   = "W/Pegel [cm]";
+    /**
+     * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
+     */
+    @Deprecated
+    public static final String CSV_Q_DESC_HEADER = "export.waterlevel.csv.header.q.desc";
+
+    /**
+     * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
+     */
+    @Deprecated
+    public static final String CSV_W_DESC_HEADER = "export.waterlevel.csv.header.w.desc";
+
+    public static final String CSV_LOCATION_HEADER = "export.waterlevel.csv.header.location";
+
+    public static final String CSV_GAUGE_HEADER = "export.waterlevel.csv.header.gauge";
+
+    public static final String CSV_META_RESULT = "export.waterlevel.csv.meta.result";
+
+    public static final String CSV_META_CREATION = "export.waterlevel.csv.meta.creation";
+
+    public static final String CSV_META_CALCULATIONBASE = "export.waterlevel.csv.meta.calculationbase";
+
+    public static final String CSV_META_RIVER = "export.waterlevel.csv.meta.river";
+
+    public static final String CSV_META_RANGE = "export.waterlevel.csv.meta.range";
+
+    public static final String CSV_META_GAUGE = "export.waterlevel.csv.meta.gauge";
+
+    public static final String CSV_META_Q = "export.waterlevel.csv.meta.q";
+
+    public static final String CSV_META_W = "export.waterlevel.csv.meta.w";
+
+    public static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range";
+
+    public static final Pattern NUMBERS_PATTERN = Pattern.compile("\\D*(\\d++.\\d*)\\D*");
+
+    public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km";
+    public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]";
+    public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]";
+    /**
+     * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
+     */
+    @Deprecated
+    public static final String DEFAULT_CSV_Q_DESC_HEADER = "Bezeichnung";
+    /**
+     * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
+     */
+    @Deprecated
+    public static final String DEFAULT_CSV_W_DESC_HEADER = "W/Pegel [cm]";
     public static final String DEFAULT_CSV_LOCATION_HEADER = "Lage";
-    public static final String DEFAULT_CSV_GAUGE_HEADER    = "Bezugspegel";
-    public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE =
-        "außerhalb des gewählten Bezugspegels";
+    public static final String DEFAULT_CSV_GAUGE_HEADER = "Bezugspegel";
+    public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE = "außerhalb des gewählten Bezugspegels";
 
     public static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode";
-    public static final String JASPER_FILE     = "export.waterlevel.pdf.file";
+    public static final String JASPER_FILE = "export.waterlevel.pdf.file";
 
-    /** The storage that contains all WQKms objects that are calculated.*/
+    /** The storage that contains all WQKms objects that are calculated. */
     protected List<WQKms[]> data;
 
-    /** The storage that contains official fixings if available.*/
+    /** The storage that contains official fixings if available. */
     protected List<WQKms> officalFixings;
 
     public WaterlevelExporter() {
-        data = new ArrayList<WQKms[]>();
+        this.data = new ArrayList<>();
     }
 
     @Override
-    public void generate()
-    throws IOException
-    {
+    public void generate() throws IOException {
         log.debug("WaterlevelExporter.generate");
 
-        /* Check for official fixings. They should also be included in the
-         * export but only the calculation result is added with addData */
-
-        officalFixings = new ArrayList<WQKms>();
+        /*
+         * Check for official fixings. They should also be included in the
+         * export but only the calculation result is added with addData
+         */
 
-        for (Artifact art: collection.getArtifactsByName(
-                STATICWQKMSNAME, context)
-        ) {
+        this.officalFixings = new ArrayList<>();
+
+        for (final Artifact art : this.collection.getArtifactsByName(STATICWQKMSNAME, this.context)) {
             if (art instanceof StaticWQKmsArtifact) {
-                IsOfficialAccess access =
-                    new IsOfficialAccess((D4EArtifact)art);
-                StaticWQKmsArtifact sart = (StaticWQKmsArtifact) art;
+                final IsOfficialAccess access = new IsOfficialAccess((D4EArtifact) art);
+                final StaticWQKmsArtifact sart = (StaticWQKmsArtifact) art;
                 if (!access.isOfficial()) {
                     continue;
                 }
 
                 /* Check that we add the data only once */
-                WQKms toAdd = sart.getWQKms();
-                String newName = toAdd.getName();
+                final WQKms toAdd = sart.getWQKms();
+                final String newName = toAdd.getName();
 
                 boolean exists = false;
-                for (WQKms wqkm: officalFixings) {
-                    /* The same official fixing could be in two
-                       artifacts/outs so let's deduplicate */
+                for (final WQKms wqkm : this.officalFixings) {
+                    /*
+                     * The same official fixing could be in two
+                     * artifacts/outs so let's deduplicate
+                     */
                     if (wqkm.getName().equals(newName)) {
                         exists = true;
                     }
                 }
                 if (!exists) {
-                    officalFixings.add(toAdd);
+                    this.officalFixings.add(toAdd);
                     log.debug("Adding additional offical fixing: " + newName);
                 }
             }
         }
 
-        if (facet != null && facet.equals(AbstractExporter.FACET_CSV)) {
+        if (this.facet != null && this.facet.equals(AbstractExporter.FACET_CSV)) {
             generateCSV();
-        }
-        else if (facet != null && facet.equals(FACET_WST)) {
+        } else if (this.facet != null && this.facet.equals(FACET_WST)) {
             generateWST();
-        }
-        else if (facet != null && facet.equals(AbstractExporter.FACET_PDF)) {
+        } else if (this.facet != null && this.facet.equals(AbstractExporter.FACET_PDF)) {
             generatePDF();
-        }
-        else {
+        } else {
             throw new IOException("invalid facet for exporter");
         }
     }
 
-
     @Override
     protected void addData(Object d) {
         if (d instanceof CalculationResult) {
-            d = ((CalculationResult)d).getData();
-            if (d instanceof WQKms []) {
-                data.add((WQKms [])d);
-            }
-            else if (d instanceof WQKmsResult) {
-                data.add(((WQKmsResult) d).getWQKms());
+            d = ((CalculationResult) d).getData();
+            if (d instanceof WQKms[]) {
+                this.data.add((WQKms[]) d);
+            } else if (d instanceof WQKmsResult) {
+                this.data.add(((WQKmsResult) d).getWQKms());
             }
         }
     }
 
-
     /**
      * Prepare the column titles of waterlevel exports.
      * Titles in this export include the Q value. If a Q value matches a named
@@ -227,13 +211,15 @@
      * title. This method resets the name of the <i>wqkms</i> object if such
      * named main value fits to the chosen Q.
      *
-     * @param winfo A WINFO Artifact.
-     * @param wqkms A WQKms object that should be prepared.
+     * @param winfo
+     *            A WINFO Artifact.
+     * @param wqkms
+     *            A WQKms object that should be prepared.
      */
-    protected String getColumnTitle(WINFOArtifact winfo, WQKms wqkms) {
+    protected String getColumnTitle(final WINFOArtifact winfo, final WQKms wqkms) {
         log.debug("WaterlevelExporter.getColumnTitle");
 
-        String name = wqkms.getName();
+        final String name = wqkms.getName();
 
         log.debug("Name of WQKms = '" + name + "'");
 
@@ -241,25 +227,25 @@
             return name;
         }
 
-        Matcher m = NUMBERS_PATTERN.matcher(name);
+        final Matcher m = NUMBERS_PATTERN.matcher(name);
 
         if (m.matches()) {
-            String raw = m.group(1);
+            final String raw = m.group(1);
 
             try {
-                double v = Double.valueOf(raw);
+                final double v = Double.valueOf(raw);
 
                 String nmv = RiverUtils.getNamedMainValue(winfo, v);
 
                 if (nmv != null && nmv.length() > 0) {
-                    nmv  = RiverUtils.stripNamedMainValue(nmv);
+                    nmv = RiverUtils.stripNamedMainValue(nmv);
                     nmv += "=" + String.valueOf(v);
                     log.debug("Set named main value '" + nmv + "'");
 
                     return nmv;
                 }
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 // do nothing here
             }
         }
@@ -267,21 +253,24 @@
         return name;
     }
 
-
-    protected String getCSVRowTitle(WINFOArtifact winfo, WQKms wqkms) {
+    /**
+     * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
+     */
+    @Deprecated
+    protected String getCSVRowTitle(final WINFOArtifact winfo, final WQKms wqkms) {
         log.debug("WaterlevelExporter.prepareNamedValue");
 
-        String name = wqkms.getName();
+        final String name = wqkms.getName();
 
         log.debug("Name of WQKms = '" + name + "'");
 
-        WQ_MODE wqmode = RiverUtils.getWQMode(winfo);
+        final WQ_MODE wqmode = RiverUtils.getWQMode(winfo);
 
         if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.QGAUGE) {
             return localizeWQKms(winfo, wqkms);
         }
 
-        Double v = wqkms.getRawValue();
+        final Double v = wqkms.getRawValue();
 
         String nmv = RiverUtils.getNamedMainValue(winfo, v);
 
@@ -295,39 +284,38 @@
         return localizeWQKms(winfo, wqkms);
     }
 
-
     /**
      * Get a string like 'W=' or 'Q=' with a number following in localized
      * format.
+     *
+     * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
      */
-    protected String localizeWQKms(WINFOArtifact winfo, WQKms wqkms) {
-        WQ_MODE wqmode   = RiverUtils.getWQMode(winfo);
-        Double  rawValue = wqkms.getRawValue();
+    @Deprecated
+    protected String localizeWQKms(final WINFOArtifact winfo, final WQKms wqkms) {
+        final WQ_MODE wqmode = RiverUtils.getWQMode(winfo);
+        final Double rawValue = wqkms.getRawValue();
 
         if (rawValue == null) {
             return wqkms.getName();
         }
 
-        NumberFormat nf = Formatter.getRawFormatter(context);
+        final NumberFormat nf = Formatter.getRawFormatter(this.context);
 
         if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.WGAUGE) {
             return "W=" + nf.format(rawValue);
-        }
-        else {
+        } else {
             return "Q=" + nf.format(rawValue);
         }
     }
 
-
     @Override
-    protected void writeCSVData(CSVWriter writer) {
+    protected void writeCSVData(final CSVWriter writer) {
         log.info("WaterlevelExporter.writeData");
 
-        WQ_MODE mode    = RiverUtils.getWQMode((D4EArtifact)master);
-        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 WQ_MODE mode = RiverUtils.getWQMode((D4EArtifact) this.master);
+        final boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE;
+        final boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE;
+        final RiverUtils.WQ_INPUT input = RiverUtils.getWQInputMode((D4EArtifact) this.master);
 
         writeCSVMeta(writer);
         writeCSVHeader(writer, atGauge, isQ);
@@ -335,19 +323,21 @@
         Double first = Double.NaN;
         Double last = Double.NaN;
 
-        for (WQKms[] tmp: data) {
-            for (WQKms wqkms: tmp) {
+        for (final WQKms[] tmp : this.data) {
+            for (final WQKms wqkms : tmp) {
                 wQKms2CSV(writer, wqkms, atGauge, isQ);
-                double[] firstLast = wqkms.getFirstLastKM();
+                final double[] firstLast = wqkms.getFirstLastKM();
                 if (first.isNaN()) {
                     /* Initialize */
                     first = firstLast[0];
                     last = firstLast[1];
                 }
                 if (firstLast[0] > firstLast[1]) {
-                    /* Calculating upstream we assert that it is
+                    /*
+                     * Calculating upstream we assert that it is
                      * impossible that the direction changes during this
-                     * loop */
+                     * loop
+                     */
                     first = Math.max(first, firstLast[0]);
                     last = Math.min(last, firstLast[1]);
                 } else if (firstLast[0] < firstLast[1]) {
@@ -359,35 +349,38 @@
             }
         }
         /* Append the official fixing at the bottom */
-        for (WQKms wqkms: officalFixings) {
+        for (final WQKms wqkms : this.officalFixings) {
             wQKms2CSV(writer, filterWQKms(wqkms, first, last), atGauge, isQ);
         }
     }
 
-
-    /** Filter a wqkms object to a distance.
+    /**
+     * Filter a wqkms object to a distance.
      *
      * To handle upstream / downstream and to limit
      * the officialFixings to the calculation distance
      * we create a new wqkms object here and fill it only
      * with the relevant data.
      *
-     * @param wqkms: The WQKms Object to filter
-     * @param first: The fist kilometer of the range
-     * @param last: The last kilometer of the range
+     * @param wqkms:
+     *            The WQKms Object to filter
+     * @param first:
+     *            The fist kilometer of the range
+     * @param last:
+     *            The last kilometer of the range
      *
      * @return A new WQKms with the relevant data sorted by direction
      */
-    private WQKms filterWQKms(WQKms wqkms, Double first, Double last) {
+    private WQKms filterWQKms(final WQKms wqkms, final Double first, final Double last) {
         if (first.isNaN() || last.isNaN()) {
             log.warn("Filtering official fixing without valid first/last.");
             return wqkms;
         }
-        int firstIdx = first > last ? wqkms.size() - 1 : 0;
-        int lastIdx  = first > last ? 0 : wqkms.size() -1;
-        WQKms filtered = new WQKms (wqkms.size());
+        final int firstIdx = first > last ? wqkms.size() - 1 : 0;
+        final int lastIdx = first > last ? 0 : wqkms.size() - 1;
+        final WQKms filtered = new WQKms(wqkms.size());
         filtered.setName(wqkms.getName());
-        double [] dp = new double [3];
+        double[] dp = new double[3];
 
         if (first > last) {
             for (int i = wqkms.size() - 1; i >= 0; i--) {
@@ -407,169 +400,101 @@
         return filtered;
     }
 
-
-    protected void writeCSVMeta(CSVWriter writer) {
+    protected void writeCSVMeta(final CSVWriter writer) {
         log.info("WaterlevelExporter.writeCSVMeta");
 
         // TODO use Access instead of RiverUtils
 
-        CallMeta meta = context.getMeta();
-
-        D4EArtifact flys = (D4EArtifact) master;
+        final CallMeta meta = this.context.getMeta();
 
-        writer.writeNext(new String[] {
-            Resources.getMsg(
-                meta,
-                CSV_META_RESULT,
-                CSV_META_RESULT,
-                new Object[] { RiverUtils.getRivername(flys) })
-        });
+        final D4EArtifact flys = (D4EArtifact) this.master;
 
-        Locale locale = Resources.getLocale(meta);
-        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+        writer.writeNext(new String[] { Resources.getMsg(meta, CSV_META_RESULT, CSV_META_RESULT, new Object[] { RiverUtils.getRivername(flys) }) });
 
-        writer.writeNext(new String[] {
-            Resources.getMsg(
-                meta,
-                CSV_META_CREATION,
-                CSV_META_CREATION,
-                new Object[] { df.format(new Date()) })
+        final Locale locale = Resources.getLocale(meta);
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+
+        writer.writeNext(new String[] { Resources.getMsg(meta, CSV_META_CREATION, CSV_META_CREATION, new Object[] { df.format(new Date()) }) });
+
+        writer.writeNext(new String[] { Resources.getMsg(meta, CSV_META_CALCULATIONBASE, CSV_META_CALCULATIONBASE, new Object[] { "" }) // TODO what is required
+                                                                                                                                        // at this place?
         });
 
-        writer.writeNext(new String[] {
-            Resources.getMsg(
-                meta,
-                CSV_META_CALCULATIONBASE,
-                CSV_META_CALCULATIONBASE,
-                new Object[] { "" }) // TODO what is required at this place?
-        });
-
-        writer.writeNext(new String[] {
-            Resources.getMsg(
-                meta,
-                CSV_META_RIVER,
-                CSV_META_RIVER,
-                new Object[] { RiverUtils.getRivername(flys) })
-        });
+        writer.writeNext(new String[] { Resources.getMsg(meta, CSV_META_RIVER, CSV_META_RIVER, new Object[] { RiverUtils.getRivername(flys) }) });
 
-        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] })
-        });
+        final RangeAccess rangeAccess = new RangeAccess(flys);
+        final 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] }) });
 
-        writer.writeNext(new String[] {
-            Resources.getMsg(
-                meta,
-                CSV_META_GAUGE,
-                CSV_META_GAUGE,
-                new Object[] { RiverUtils.getGaugename(flys) })
-        });
+        writer.writeNext(new String[] { Resources.getMsg(meta, CSV_META_GAUGE, CSV_META_GAUGE, new Object[] { RiverUtils.getGaugename(flys) }) });
 
-        RiverUtils.WQ_MODE wq = RiverUtils.getWQMode(flys);
+        // TODO: code extracted into WaterlevelDescriptionBuilder, should be used instead.
+        final RiverUtils.WQ_MODE wq = RiverUtils.getWQMode(flys);
         if (wq == RiverUtils.WQ_MODE.QFREE || wq == RiverUtils.WQ_MODE.QGAUGE) {
-            double[] qs  = RiverUtils.getQs(flys);
-            RiverUtils.WQ_INPUT input = RiverUtils.getWQInputMode(flys);
+            final double[] qs = RiverUtils.getQs(flys);
+            final RiverUtils.WQ_INPUT input = RiverUtils.getWQInputMode(flys);
 
             String data = "";
 
-            if ((input == RiverUtils.WQ_INPUT.ADAPTED ||
-                input == RiverUtils.WQ_INPUT.RANGE) &&
-                qs != null && qs.length > 0)
-            {
+            if ((input == RiverUtils.WQ_INPUT.ADAPTED || input == RiverUtils.WQ_INPUT.RANGE) && qs != null && qs.length > 0) {
                 data = String.valueOf(qs[0]);
-                data += " - " + String.valueOf(qs[qs.length-1]);
-            }
-            else if (input == RiverUtils.WQ_INPUT.SINGLE && qs != null){
+                data += " - " + String.valueOf(qs[qs.length - 1]);
+            } else if (input == RiverUtils.WQ_INPUT.SINGLE && qs != null) {
                 data = String.valueOf(qs[0]);
                 for (int i = 1; i < qs.length; i++) {
                     data += ", " + String.valueOf(qs[i]);
                 }
-            }
-            else {
+            } else {
                 log.warn("Could not determine Q range!");
             }
 
-            writer.writeNext(new String[] {
-                Resources.getMsg(
-                    meta,
-                    CSV_META_Q,
-                    CSV_META_Q,
-                    new Object[] {data})
-            });
-        }
-        else {
-            double[] ws = RiverUtils.getWs(flys);
+            writer.writeNext(new String[] { Resources.getMsg(meta, CSV_META_Q, CSV_META_Q, new Object[] { data }) });
+        } else {
+            final double[] ws = RiverUtils.getWs(flys);
 
             String lower = "";
             String upper = "";
 
             if (ws != null && ws.length > 0) {
                 lower = String.valueOf(ws[0]);
-                upper = String.valueOf(ws[ws.length-1]);
-            }
-            else {
+                upper = String.valueOf(ws[ws.length - 1]);
+            } else {
                 log.warn("Could not determine W range!");
             }
 
-            writer.writeNext(new String[] {
-                Resources.getMsg(
-                    meta,
-                    CSV_META_W,
-                    CSV_META_W,
-                    new Object[] { lower, upper })
-            });
+            writer.writeNext(new String[] { Resources.getMsg(meta, CSV_META_W, CSV_META_W, new Object[] { lower, upper }) });
         }
 
         writer.writeNext(new String[] { "" });
     }
 
-
     /**
      * Write the header, with different headings depending on whether at a
      * gauge or at a location.
      */
-    protected void writeCSVHeader(
-        CSVWriter writer,
-        boolean   atGauge,
-        boolean   isQ
-    ) {
+    protected void writeCSVHeader(final CSVWriter writer, final boolean atGauge, final boolean isQ) {
         log.info("WaterlevelExporter.writeCSVHeader");
 
-        String unit = RiverUtils.getRiver(
-            (D4EArtifact) master).getWstUnit().getName();
+        final String unit = RiverUtils.getRiver((D4EArtifact) this.master).getWstUnit().getName();
 
         if (atGauge) {
-            writer.writeNext(new String[] {
-                msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER),
-                msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
-                msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER),
-                (isQ
-                    ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER)
-                    : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)),
-                msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER),
-                msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER)
-            });
-        }
-        else {
-            writer.writeNext(new String[] {
-                msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER),
+            writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
+                    msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER),
+
+                    // FIXME: use WaterlevelDescriptionBuilder instead and also remove all this duplicate code.
+                    (isQ ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)),
+                    msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) });
+        } else {
+            writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER),
                     // TODO flys/issue1128 (unit per river)
-                msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
-                msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER),
-                msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER)
-            });
+                    msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER),
+                    msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) });
         }
     }
 
-
     /** Linearly search for gauge which is valid at km. */
-    private static Gauge findGauge(double km, List<Gauge> gauges) {
-        for (Gauge gauge: gauges) {
+    private static Gauge findGauge(final double km, final List<Gauge> gauges) {
+        for (final Gauge gauge : gauges) {
             if (gauge.getRange().contains(km)) {
                 return gauge;
             }
@@ -577,8 +502,8 @@
         return null;
     }
 
-    private static Segment findSegment(double km, List<Segment> segments) {
-        for (Segment segment: segments) {
+    private static Segment findSegment(final double km, final List<Segment> segments) {
+        for (final Segment segment : segments) {
             if (segment.inside(km)) {
                 return segment;
             }
@@ -586,66 +511,55 @@
         return null;
     }
 
-
-    private void writeRow4(CSVWriter writer, double wqkm[], D4EArtifact flys) {
-        NumberFormat kmf = getKmFormatter();
-        NumberFormat wf  = getWFormatter();
-        NumberFormat qf  = getQFormatter();
-        writer.writeNext(new String[] {
-            kmf.format(wqkm[2]),
-            wf.format(wqkm[0]),
-            qf.format(RiverUtils.roundQ(wqkm[1])),
-            RiverUtils.getLocationDescription(flys, wqkm[2])
-        });
+    private void writeRow4(final CSVWriter writer, final double wqkm[], final D4EArtifact flys) {
+        final NumberFormat kmf = getKmFormatter();
+        final NumberFormat wf = getWFormatter();
+        final NumberFormat qf = getQFormatter();
+        writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), qf.format(RiverUtils.roundQ(wqkm[1])),
+                RiverUtils.getLocationDescription(flys, wqkm[2]) });
     }
 
     /** Write an csv-row at gauge location. */
-    private void writeRow6(CSVWriter writer, double wqkm[], String wOrQDesc,
-        D4EArtifact flys, String gaugeName) {
-        NumberFormat kmf = getKmFormatter();
-        NumberFormat wf  = getWFormatter();
-        NumberFormat qf  = getQFormatter();
+    private void writeRow6(final CSVWriter writer, final double wqkm[], final String wOrQDesc, final D4EArtifact flys, final String gaugeName) {
+        final NumberFormat kmf = getKmFormatter();
+        final NumberFormat wf = getWFormatter();
+        final NumberFormat qf = getQFormatter();
 
-        writer.writeNext(new String[] {
-            kmf.format(wqkm[2]),
-            wf.format(wqkm[0]),
-            qf.format(RiverUtils.roundQ(wqkm[1])),
-            wOrQDesc,
-            RiverUtils.getLocationDescription(flys, wqkm[2]),
-            gaugeName
-        });
+        writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), qf.format(RiverUtils.roundQ(wqkm[1])), wOrQDesc,
+                RiverUtils.getLocationDescription(flys, wqkm[2]), gaugeName });
     }
 
-    private String getDesc(WQKms wqkms, boolean isQ)
-    {
-        D4EArtifact flys = (D4EArtifact) master;
+    /**
+     * @deprecated Use {@link WaterlevelDescriptionBuilder} instead.
+     */
+    @Deprecated
+    private String getDesc(final WQKms wqkms, final boolean isQ) {
+        final D4EArtifact flys = (D4EArtifact) this.master;
         String colDesc = "";
 
         if (flys instanceof WINFOArtifact && isQ) {
-            colDesc = getCSVRowTitle((WINFOArtifact)flys, wqkms);
-        }
-        else if (!isQ) {
-            Double value = RiverUtils.getValueFromWQ(wqkms);
-            colDesc = (value != null) ?
-                Formatter.getWaterlevelW(context).format(value) : null;
+            colDesc = getCSVRowTitle((WINFOArtifact) flys, wqkms);
+        } else if (!isQ) {
+            final Double value = RiverUtils.getValueFromWQ(wqkms);
+            colDesc = (value != null) ? Formatter.getWaterlevelW(this.context).format(value) : null;
         }
 
         if (flys instanceof WINFOArtifact) {
             if (wqkms != null && wqkms.getRawValue() != null) {
-                WINFOArtifact winfo = (WINFOArtifact) flys;
-                colDesc = RiverUtils.getNamedMainValue(
-                    winfo, wqkms.getRawValue());
+                final WINFOArtifact winfo = (WINFOArtifact) flys;
+                colDesc = RiverUtils.getNamedMainValue(winfo, wqkms.getRawValue());
                 // For 'W am Pegel' s
                 if (colDesc == null) {
-                    Double value = RiverUtils.getValueFromWQ(wqkms);
-                    colDesc = (value != null) ?
-                        Formatter.getWaterlevelW(context).format(value) : null;
+                    final Double value = RiverUtils.getValueFromWQ(wqkms);
+                    colDesc = (value != null) ? Formatter.getWaterlevelW(this.context).format(value) : null;
                 }
             }
         }
         if (colDesc != null) {
-            /* Quick hack. Can be removed when database strings are
-             * adapted or left in here as it should never be harmful. */
+            /*
+             * Quick hack. Can be removed when database strings are
+             * adapted or left in here as it should never be harmful.
+             */
             colDesc = colDesc.replace("Amtl.Festlegung_", "Amtl. ");
         }
 
@@ -655,12 +569,7 @@
     /**
      * Write "rows" of csv data from wqkms with writer.
      */
-    protected void wQKms2CSV(
-        CSVWriter writer,
-        WQKms     wqkms,
-        boolean   atGauge,
-        boolean   isQ
-    ) {
+    protected void wQKms2CSV(final CSVWriter writer, final WQKms wqkms, final boolean atGauge, final boolean isQ) {
         log.debug("WaterlevelExporter.wQKms2CSV");
 
         // Skip constant data.
@@ -668,38 +577,35 @@
             return;
         }
 
-        NumberFormat kmf = getKmFormatter();
-        NumberFormat wf  = getWFormatter();
-        NumberFormat qf  = getQFormatter();
+        final NumberFormat kmf = getKmFormatter();
+        final NumberFormat wf = getWFormatter();
+        final NumberFormat qf = getQFormatter();
 
-        int      size   = wqkms.size();
+        final int size = wqkms.size();
         double[] result = new double[3];
 
-        D4EArtifact flys        = (D4EArtifact) master;
-        RangeAccess rangeAccess = new RangeAccess(flys);
-
-        List<Gauge>  gauges     = RiverUtils.getGauges(flys);
+        final D4EArtifact flys = (D4EArtifact) this.master;
+        final RangeAccess rangeAccess = new RangeAccess(flys);
 
-        Gauge gauge = rangeAccess.getRiver().determineRefGauge(
-            rangeAccess.getKmRange(), rangeAccess.isRange());
+        final List<Gauge> gauges = RiverUtils.getGauges(flys);
 
-        String       gaugeName  = gauge.getName();
-        String       desc       = "";
-        String       notinrange = msg(
-            CSV_NOT_IN_GAUGE_RANGE,
-            DEFAULT_CSV_NOT_IN_GAUGE_RANGE);
+        final Gauge gauge = rangeAccess.getRiver().determineRefGauge(rangeAccess.getKmRange(), rangeAccess.isRange());
+
+        final String gaugeName = gauge.getName();
+        String desc = "";
+        final String notinrange = msg(CSV_NOT_IN_GAUGE_RANGE, DEFAULT_CSV_NOT_IN_GAUGE_RANGE);
         List<Segment> segments = null;
         boolean isFixRealize = false;
 
-        double a = gauge.getRange().getA().doubleValue();
-        double b = gauge.getRange().getB().doubleValue();
-        long startTime = System.currentTimeMillis();
+        final double a = gauge.getRange().getA().doubleValue();
+        final double b = gauge.getRange().getB().doubleValue();
+        final long startTime = System.currentTimeMillis();
 
         desc = getDesc(wqkms, isQ);
 
         if (flys instanceof FixationArtifact) {
             // Get W/Q input per gauge for this case.
-            FixRealizingAccess fixAccess = new FixRealizingAccess(flys);
+            final FixRealizingAccess fixAccess = new FixRealizingAccess(flys);
             segments = fixAccess.getSegments();
             if (segments != null && !segments.isEmpty()) {
                 isFixRealize = true;
@@ -711,20 +617,16 @@
             // Kms tend to be close together so caching the last sector
             // is a good time saving heuristic.
             Segment lastSegment = null;
-            Gauge   lastGauge   = null;
+            Gauge lastGauge = null;
 
-            NumberFormat nf =
-                Formatter.getFormatter(context.getMeta(), 0, 0);
+            final NumberFormat nf = Formatter.getFormatter(this.context.getMeta(), 0, 0);
 
             for (int i = 0; i < size; ++i) {
                 result = wqkms.get(i, result);
-                double km = result[2];
+                final double km = result[2];
 
                 if (segments != null) {
-                    Segment found = lastSegment != null
-                                    && lastSegment.inside(km)
-                        ? lastSegment
-                        : findSegment(km, segments);
+                    final Segment found = lastSegment != null && lastSegment.inside(km) ? lastSegment : findSegment(km, segments);
 
                     if (found != null) {
                         desc = nf.format(found.getValues()[0]);
@@ -734,67 +636,55 @@
 
                 String gaugeN;
                 if (isFixRealize) {
-                    Gauge found = lastGauge != null
-                                  && lastGauge.getRange().contains(km)
-                        ? lastGauge
-                        : findGauge(km, gauges);
+                    final Gauge found = lastGauge != null && lastGauge.getRange().contains(km) ? lastGauge : findGauge(km, gauges);
 
                     gaugeN = found != null ? found.getName() : notinrange;
                     lastGauge = found;
-                }
-                else {
+                } else {
                     // TODO issue1114: Take correct gauge
-                    gaugeN = km >= a && km <= b
-                        ? gaugeName
-                        : notinrange;
+                    gaugeN = km >= a && km <= b ? gaugeName : notinrange;
                 }
                 writeRow6(writer, result, desc, flys, gaugeN);
             }
-        }
-        else { // Not at gauge.
+        } else { // Not at gauge.
             for (int i = 0; i < size; ++i) {
                 result = wqkms.get(i, result);
                 writeRow4(writer, result, flys);
             }
         }
 
-        long stopTime = System.currentTimeMillis();
+        final long stopTime = System.currentTimeMillis();
 
         if (log.isDebugEnabled()) {
-            log.debug("Writing CSV took " +
-                (float)(stopTime-startTime)/1000f + " secs.");
+            log.debug("Writing CSV took " + (stopTime - startTime) / 1000f + " secs.");
         }
     }
 
-
     /**
      * Generates the output in WST format.
      */
-    protected void generateWST()
-    throws    IOException
-    {
+    protected void generateWST() throws IOException {
         log.info("WaterlevelExporter.generateWST");
 
-        int cols = data.get(0).length + officalFixings.size();
-        WstWriter writer = new WstWriter(cols);
+        final int cols = this.data.get(0).length + this.officalFixings.size();
+        final WstWriter writer = new WstWriter(cols);
 
         writeWSTData(writer);
 
-        writer.write(out);
+        writer.write(this.out);
     }
 
-
-    protected void writeWSTData(WstWriter writer) {
+    protected void writeWSTData(final WstWriter writer) {
         log.debug("WaterlevelExporter.writeWSTData");
 
         double[] result = new double[4];
 
-        for (WQKms[] tmp: data) {
-            for (WQKms wqkms: tmp) {
+        for (final WQKms[] tmp : this.data) {
+            for (final WQKms wqkms : tmp) {
                 if (wqkms instanceof ConstantWQKms) {
                     continue;
                 }
-                int size = wqkms != null ? wqkms.size() : 0;
+                final int size = wqkms != null ? wqkms.size() : 0;
 
                 addWSTColumn(writer, wqkms);
 
@@ -820,21 +710,21 @@
         //
         // There was some confusion how to implement this. see flys/issue1620
         // for details.
-        for (WQKms wqkms: officalFixings) {
+        for (final WQKms wqkms : this.officalFixings) {
             // To add some spaces here or to add them in the writer,..
             writer.addColumn(getDesc(wqkms, true));
 
             // Get all lines from the calculation
-            Map <Double, WstLine> calcLines = writer.getLines();
+            final Map<Double, WstLine> calcLines = writer.getLines();
 
             // All KM values where we have a point for
-            TDoubleArrayList officialKms = wqkms.allKms();
+            final TDoubleArrayList officialKms = wqkms.allKms();
 
-            for (Map.Entry<Double, WstLine> entry : calcLines.entrySet()) {
+            for (final Map.Entry<Double, WstLine> entry : calcLines.entrySet()) {
                 // Bad for perfomance but the user can wait a bit for WST
                 // so lets not spend time optimizing too much,.. *hides*
-                double km = entry.getKey().doubleValue();
-                int idx = officialKms.indexOf(km);
+                final double km = entry.getKey().doubleValue();
+                final int idx = officialKms.indexOf(km);
                 if (idx != -1) {
                     entry.getValue().add(wqkms.getW(idx), wqkms.getQ(idx));
                 }
@@ -842,7 +732,6 @@
         }
     }
 
-
     /**
      * Register a new column at <i>writer</i>. The name /
      * title of the column depends on the Q or W value of <i>wqkms</i>. If a Q
@@ -850,72 +739,68 @@
      * the named main value. Otherwise, the name returned by
      * <i>WQKms.getName()</i> is set.
      *
-     * @param writer The WstWriter.
-     * @param wqkms The new WST column.
+     * @param writer
+     *            The WstWriter.
+     * @param wqkms
+     *            The new WST column.
      */
-    protected void addWSTColumn(WstWriter writer, WQKms wqkms) {
+    protected void addWSTColumn(final WstWriter writer, final WQKms wqkms) {
         if (wqkms instanceof ConstantWQKms) {
             return;
         }
-        if (master instanceof WINFOArtifact) {
-            writer.addColumn(getColumnTitle((WINFOArtifact) master, wqkms));
-        }
-        else {
+        if (this.master instanceof WINFOArtifact) {
+            writer.addColumn(getColumnTitle((WINFOArtifact) this.master, wqkms));
+        } else {
             writer.addColumn(wqkms.getName());
         }
     }
 
-
     @Override
-    protected void writePDF(OutputStream out) {
+    protected void writePDF(final OutputStream out) {
         log.debug("write PDF");
-        WKmsJRDataSource source = createJRData();
+        final WKmsJRDataSource source = createJRData();
 
-        String jasperFile = Resources.getMsg(
-                                context.getMeta(),
-                                JASPER_FILE,
-                                "/jasper/waterlevel_en.jasper");
-        String confPath = Config.getConfigDirectory().toString();
+        final String jasperFile = // "/jasper/waterlevel_en.jasper";
+                Resources.getMsg(this.context.getMeta(), JASPER_FILE, "/jasper/waterlevel_en.jasper");
+        final String confPath = Config.getConfigDirectory().toString();
 
-
-        Map parameters = new HashMap();
+        final Map parameters = new HashMap();
         parameters.put("ReportTitle", "Exported Data");
         try {
-            JasperPrint print = JasperFillManager.fillReport(
-                confPath + jasperFile,
-                parameters,
-                source);
+            final JasperPrint print = JasperFillManager.fillReport(confPath + jasperFile, parameters, source);
             JasperExportManager.exportReportToPdfStream(print, out);
         }
-        catch(JRException je) {
+        catch (final JRException je) {
             log.warn("Error generating PDF Report!", je);
         }
     }
 
     protected WKmsJRDataSource createJRData() {
-        WKmsJRDataSource source = new WKmsJRDataSource();
+        final WKmsJRDataSource source = new WKmsJRDataSource();
 
-        WQ_MODE mode    = RiverUtils.getWQMode((D4EArtifact)master);
-        boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE;
-        boolean isQ     = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE;
+        final WQ_MODE mode = RiverUtils.getWQMode((D4EArtifact) this.master);
+        final boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE;
+        final boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE;
 
         Double first = Double.NaN;
         Double last = Double.NaN;
 
         addMetaData(source);
-        for (WQKms[] tmp: data) {
-            for (WQKms wqkms: tmp) {
+        for (final WQKms[] tmp : this.data) {
+            for (final WQKms wqkms : tmp) {
                 addWKmsData(wqkms, atGauge, isQ, source);
-                double[] firstLast = wqkms.getFirstLastKM();
+                final double[] firstLast = wqkms.getFirstLastKM();
                 if (first.isNaN()) {
                     /* Initialize */
                     first = firstLast[0];
                     last = firstLast[1];
                 }
                 if (firstLast[0] > firstLast[1]) {
-                    /* Calculating upstream we assert that it is
+                    /*
+                     * Calculating upstream we assert that it is
                      * impossible that the direction changes during this
-                     * loop */
+                     * loop
+                     */
                     first = Math.max(first, firstLast[0]);
                     last = Math.min(last, firstLast[1]);
                 } else if (firstLast[0] < firstLast[1]) {
@@ -928,44 +813,35 @@
         }
 
         /* Append the official fixing at the bottom */
-        for (WQKms wqkms: officalFixings) {
+        for (final WQKms wqkms : this.officalFixings) {
             addWKmsData(filterWQKms(wqkms, first, last), atGauge, isQ, source);
         }
         return source;
     }
 
-    protected void addMetaData(WKmsJRDataSource source) {
-        CallMeta meta = context.getMeta();
-
-        D4EArtifact flys = (D4EArtifact) master;
+    protected void addMetaData(final WKmsJRDataSource source) {
+        final CallMeta meta = this.context.getMeta();
 
-        source.addMetaData ("river", RiverUtils.getRivername(flys));
+        final D4EArtifact flys = (D4EArtifact) this.master;
 
-        Locale locale = Resources.getLocale(meta);
-        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
-        NumberFormat kmf = getKmFormatter();
+        source.addMetaData("river", RiverUtils.getRivername(flys));
+
+        final Locale locale = Resources.getLocale(meta);
+        final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+        final NumberFormat kmf = getKmFormatter();
 
         source.addMetaData("date", df.format(new Date()));
 
-        RangeAccess rangeAccess = new RangeAccess(flys);
-        double[] kms = rangeAccess.getKmRange();
-        source.addMetaData("range",
-                kmf.format(kms[0]) + " - " + kmf.format(kms[kms.length-1]));
+        final RangeAccess rangeAccess = new RangeAccess(flys);
+        final double[] kms = rangeAccess.getKmRange();
+        source.addMetaData("range", kmf.format(kms[0]) + " - " + kmf.format(kms[kms.length - 1]));
 
         source.addMetaData("gauge", RiverUtils.getGaugename(flys));
 
-        source.addMetaData("calculation", Resources.getMsg(
-                                            locale,
-                                            PDF_HEADER_MODE,
-                                            "Waterlevel"));
+        source.addMetaData("calculation", Resources.getMsg(locale, PDF_HEADER_MODE, "Waterlevel"));
     }
 
-    protected void addWKmsData(
-        WQKms wqkms,
-        boolean atGauge,
-        boolean isQ,
-        WKmsJRDataSource source)
-    {
+    protected void addWKmsData(final WQKms wqkms, final boolean atGauge, final boolean isQ, final WKmsJRDataSource source) {
         log.debug("WaterlevelExporter.addWKmsData");
 
         // Skip constant data.
@@ -973,65 +849,44 @@
             return;
         }
 
-        NumberFormat kmf = getKmFormatter();
-        NumberFormat wf  = getWFormatter();
-        NumberFormat qf  = getQFormatter();
+        final NumberFormat kmf = getKmFormatter();
+        final NumberFormat wf = getWFormatter();
+        final NumberFormat qf = getQFormatter();
 
-        int      size   = wqkms.size();
+        final int size = wqkms.size();
         double[] result = new double[3];
 
-        D4EArtifact flys        = (D4EArtifact) master;
-        RangeAccess rangeAccess = new RangeAccess(flys);
-
-        Gauge gauge = rangeAccess.getRiver().determineRefGauge(
-            rangeAccess.getKmRange(), rangeAccess.isRange());
+        final D4EArtifact flys = (D4EArtifact) this.master;
+        final RangeAccess rangeAccess = new RangeAccess(flys);
 
-        String       gaugeName  = gauge.getName();
-        String       desc       = "";
-        String       notinrange = msg(
-            CSV_NOT_IN_GAUGE_RANGE,
-            DEFAULT_CSV_NOT_IN_GAUGE_RANGE);
+        final Gauge gauge = rangeAccess.getRiver().determineRefGauge(rangeAccess.getKmRange(), rangeAccess.isRange());
 
-        double a = gauge.getRange().getA().doubleValue();
-        double b = gauge.getRange().getB().doubleValue();
+        final String gaugeName = gauge.getName();
+        String desc = "";
+        final String notinrange = msg(CSV_NOT_IN_GAUGE_RANGE, DEFAULT_CSV_NOT_IN_GAUGE_RANGE);
+
+        final double a = gauge.getRange().getA().doubleValue();
+        final double b = gauge.getRange().getB().doubleValue();
 
         desc = getDesc(wqkms, isQ);
-        long startTime = System.currentTimeMillis();
+        final long startTime = System.currentTimeMillis();
 
-        for (int i = 0; i < size; i ++) {
+        for (int i = 0; i < size; i++) {
             result = wqkms.get(i, result);
 
             if (atGauge) {
-                source.addData(new String[] {
-                    kmf.format(result[2]),
-                    wf.format(result[0]),
-                    qf.format(RiverUtils.roundQ(result[1])),
-                    desc,
-                    RiverUtils.getLocationDescription(flys, result[2]),
-                    result[2] >= a && result[2] <= b
-                        ? gaugeName
-                        : notinrange
-                });
-            }
-            else {
-                source.addData(new String[] {
-                    kmf.format(result[2]),
-                    wf.format(result[0]),
-                    qf.format(RiverUtils.roundQ(result[1])),
-                    desc,
-                    RiverUtils.getLocationDescription(flys, result[2]),
-                    result[2] >= a && result[2] <= b
-                        ? gaugeName
-                        : notinrange
-                });
+                source.addData(new String[] { kmf.format(result[2]), wf.format(result[0]), qf.format(RiverUtils.roundQ(result[1])), desc,
+                        RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange });
+            } else {
+                source.addData(new String[] { kmf.format(result[2]), wf.format(result[0]), qf.format(RiverUtils.roundQ(result[1])), desc,
+                        RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange });
             }
         }
 
-        long stopTime = System.currentTimeMillis();
+        final long stopTime = System.currentTimeMillis();
 
         if (log.isDebugEnabled()) {
-            log.debug("Writing PDF data took " +
-                (float)(stopTime-startTime)/1000f + " secs.");
+            log.debug("Writing PDF data took " + (stopTime - startTime) / 1000f + " secs.");
         }
     }
 }
--- a/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -40,6 +40,7 @@
 import org.json.JSONException;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.jfree.Bounds;
 import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation;
 import org.dive4elements.river.jfree.DoubleBounds;
@@ -47,7 +48,6 @@
 import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
 import org.dive4elements.river.jfree.StyledXYSeries;
 import org.dive4elements.river.jfree.AxisDataset;
-import org.dive4elements.river.jfree.AnnotationHelper;
 import org.dive4elements.river.themes.ThemeDocument;
 
 
@@ -102,11 +102,11 @@
      * Generate the chart anew (including localized axis and all).
      */
     @Override
-    public JFreeChart generateChart() {
+    protected JFreeChart generateChart(CallContext context) {
         log.debug("XYChartGenerator.generateChart");
 
         JFreeChart chart = ChartFactory.createXYLineChart(
-            getChartTitle(),
+            getChartTitle(context),
             getXAxisLabel(),
             getYAxisLabel(0),
             null,
@@ -121,7 +121,8 @@
 
         chart.setBackgroundPaint(Color.WHITE);
         plot.setBackgroundPaint(Color.WHITE);
-        addSubtitles(chart);
+        addSubtitles(context, chart);
+        addMetadataSubtitle(context, chart);
         adjustPlot(plot);
 
         //debugAxis(plot);
@@ -301,7 +302,11 @@
 
 
     protected NumberAxis createXAxis(String label) {
-        return new NumberAxis(label);
+        NumberAxis axis = new NumberAxis(label);
+        // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+        axis.setLowerMargin(0);
+        axis.setUpperMargin(0);
+        return axis;
     }
 
 
@@ -989,10 +994,5 @@
     public void setInverted(boolean inverted) {
         this.inverted = inverted;
     }
-
-    protected void addAnnotationsToRenderer(XYPlot plot) {
-        AnnotationHelper.addAnnotationsToRenderer(annotations, plot,
-                getChartSettings(), datasets);
-    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -19,6 +19,7 @@
 import org.jfree.data.xy.XYSeries;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.access.FixAnalysisAccess;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.model.DateRange;
@@ -114,7 +115,7 @@
     ) {
         log.debug("doExtremeCurveBaseOut");
         ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet();
-        Curve curve = (Curve) facet.getData(aaf.getArtifact(), context);
+        Curve curve = (Curve) facet.getData(aaf.getArtifact(), getContext());
         if (curve == null) {
             log.warn("doExtremeCurveBaseOut: Facet does not contain Curve");
             return;
@@ -155,7 +156,7 @@
     ) {
         log.debug("doExtremeCurveOut");
         ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet();
-        Curve curve = (Curve) facet.getData(aaf.getArtifact(), context);
+        Curve curve = (Curve) facet.getData(aaf.getArtifact(), getContext());
         if (curve == null) {
             log.warn("doExtremeCurveOut: Facet does not contain Curve");
             return;
@@ -189,29 +190,29 @@
 
 
     @Override
-    protected String getChartTitle() {
+    protected String getChartTitle(final CallContext context) {
         return Resources.format(
-                context.getMeta(),
+                getContext().getMeta(),
                 I18N_CHART_TITLE,
                 I18N_CHART_TITLE_DEFAULT,
-                context.getContextValue(CURRENT_KM));
+                getContext().getContextValue(CURRENT_KM));
     }
 
 
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
     }
 
     @Override
-    protected String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(final CallContext context) {
         FixAnalysisAccess access = new FixAnalysisAccess(artifact);
         DateRange dateRange = access.getDateRange();
         DateRange refRange  = access.getReferencePeriod();
 
         if (dateRange != null && refRange != null) {
             return Resources.format(
-                    context.getMeta(),
+                    getContext().getMeta(),
                     I18N_CHART_SUBTITLE,
                     "",
                     access.getRiverName(),
@@ -225,8 +226,8 @@
     }
 
     @Override
-    protected void addSubtitles(JFreeChart chart) {
-        String defaultSubtitle = getDefaultChartSubtitle();
+    protected void addSubtitles(final CallContext context, JFreeChart chart) {
+        String defaultSubtitle = getDefaultChartSubtitle(context);
 
         if (defaultSubtitle == null || defaultSubtitle.length() == 0) {
             return;
@@ -236,13 +237,13 @@
     }
 
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
     }
 
     @Override
     protected String getDefaultYAxisLabel(int pos) {
-        D4EArtifact flys = (D4EArtifact) master;
+        D4EArtifact flys = getArtifact();
 
         String unit = RiverUtils.getRiver(flys).getWstUnit().getName();
         if (pos == 0) {
--- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/DeltaWtExporter.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/DeltaWtExporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,63 +8,48 @@
 
 package org.dive4elements.river.exports.fixings;
 
-import au.com.bytecode.opencsv.CSVWriter;
-
-import org.dive4elements.artifacts.CallMeta;
-
-import org.dive4elements.river.artifacts.model.CalculationResult;
-
-import org.dive4elements.river.artifacts.model.fixings.AnalysisPeriod;
-import org.dive4elements.river.artifacts.model.fixings.FixAnalysisResult;
-import org.dive4elements.river.artifacts.model.fixings.QWD;
-
-import org.dive4elements.river.artifacts.resources.Resources;
-
-import org.dive4elements.river.exports.AbstractExporter;
-
-import org.dive4elements.river.utils.Formatter;
-import org.dive4elements.river.utils.KMIndex;
-
 import java.io.IOException;
 import java.io.OutputStream;
-
 import java.text.DateFormat;
 import java.text.MessageFormat;
 import java.text.NumberFormat;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.TreeMap;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.RiverAccess;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.fixings.AnalysisPeriod;
+import org.dive4elements.river.artifacts.model.fixings.FixAnalysisResult;
+import org.dive4elements.river.artifacts.model.fixings.QWD;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.exports.AbstractExporter;
+import org.dive4elements.river.utils.Formatter;
+import org.dive4elements.river.utils.KMIndex;
+
+import au.com.bytecode.opencsv.CSVWriter;
 
 /** Exports fixation analysis deltaw(t) computation results to csv. */
-public class DeltaWtExporter
-extends      AbstractExporter
-{
+public class DeltaWtExporter extends AbstractExporter {
     /** Private log. */
     private static Logger log = Logger.getLogger(DeltaWtExporter.class);
 
-    public static final String CSV_KM_HEADER =
-        "export.fixings.deltawt.csv.header.km";
-
-    public static final String CSV_DELTA_W_HEADER =
-        "export.fixings.deltawt.csv.header.deltaw";
-
-    public static final String CSV_Q_HEADER =
-        "export.fixings.deltawt.csv.header.q";
+    public static final String CSV_KM_HEADER = "export.fixings.deltawt.csv.header.km";
 
-    public static final String CSV_W_HEADER =
-        "export.fixings.deltawt.csv.header.w";
+    public static final String CSV_DELTA_W_HEADER = "export.fixings.deltawt.csv.header.deltaw";
 
-    public static final String CSV_TRANGE_HEADER =
-        "export.fixings.deltawt.csv.header.time.range";
+    public static final String CSV_Q_HEADER = "export.fixings.deltawt.csv.header.q";
 
-    public static final String CSV_T_HEADER =
-        "export.fixings.deltawt.csv.header.t";
+    public static final String CSV_W_HEADER = "export.fixings.deltawt.csv.header.w";
 
-    public static final String CSV_T_FORMAT =
-        "export.fixings.deltawt.csv.t.format";
+    public static final String CSV_TRANGE_HEADER = "export.fixings.deltawt.csv.header.time.range";
+
+    public static final String CSV_T_HEADER = "export.fixings.deltawt.csv.header.t";
+
+    public static final String CSV_T_FORMAT = "export.fixings.deltawt.csv.t.format";
 
     public static final String DEFAULT_CSV_KM_HEADER = "km";
 
@@ -76,143 +61,122 @@
 
     public static final String DEFAULT_CSV_T_HEADER = "Datum";
 
-    public static final String DEFAULT_CSV_TRANGE_DESC_HEADER =
-        "Status";
-
-    public static final String CSV_REFERENCE =
-        "export.fixings.deltawt.csv.reference";
-
-    public static final String CSV_ANALYSIS =
-        "export.fixings.deltawt.csv.analysis";
+    public static final String DEFAULT_CSV_TRANGE_DESC_HEADER = "Status";
 
-    public static final String DEFAULT_CSV_REFERENCE =
-        "B";
+    public static final String CSV_REFERENCE = "export.fixings.deltawt.csv.reference";
 
-    public static final String DEFAULT_CSV_ANALYSIS =
-        "A{0,number,integer}";
+    public static final String CSV_ANALYSIS = "export.fixings.deltawt.csv.analysis";
 
-    public static final String DEFAULT_CSV_T_FORMAT =
-        "dd.MM.yyyy";
+    public static final String DEFAULT_CSV_REFERENCE = "B";
 
-    protected List<KMIndex<AnalysisPeriod []>> analysisPeriods;
+    public static final String DEFAULT_CSV_ANALYSIS = "A{0,number,integer}";
+
+    public static final String DEFAULT_CSV_T_FORMAT = "dd.MM.yyyy";
+
+    protected List<KMIndex<AnalysisPeriod[]>> analysisPeriods;
 
     protected List<KMIndex<QWD[]>> referenceEvents;
 
     public DeltaWtExporter() {
-        analysisPeriods = new ArrayList<KMIndex<AnalysisPeriod []>>();
-        referenceEvents = new ArrayList<KMIndex<QWD[]>>();
+        this.analysisPeriods = new ArrayList<>();
+        this.referenceEvents = new ArrayList<>();
     }
 
     @Override
-    protected void addData(Object d) {
+    protected void addData(final Object d) {
         log.debug("DeltaWtExporter.addData");
         if (!(d instanceof CalculationResult)) {
             log.warn("Invalid data type");
             return;
         }
 
-        Object data = ((CalculationResult)d).getData();
+        final Object data = ((CalculationResult) d).getData();
         if (!(data instanceof FixAnalysisResult)) {
             log.warn("Invalid data stored in result.");
         }
-        FixAnalysisResult result = (FixAnalysisResult)data;
-        analysisPeriods.add(result.getAnalysisPeriods());
-        referenceEvents.add(result.getReferenced());
+        final FixAnalysisResult result = (FixAnalysisResult) data;
+        this.analysisPeriods.add(result.getAnalysisPeriods());
+        this.referenceEvents.add(result.getReferenced());
     }
 
     @Override
-    protected void writeCSVData(CSVWriter writer) throws IOException {
+    protected void writeCSVData(final CSVWriter writer) throws IOException {
 
-        boolean debug = log.isDebugEnabled();
+        final boolean debug = log.isDebugEnabled();
 
         writeCSVHeader(writer);
 
-        NumberFormat kmF = getKMFormatter();
-        NumberFormat dwF = getDeltaWFormatter();
-        NumberFormat qF  = getQFormatter();
-        NumberFormat wF  = getWFormatter();
-
-        DateFormat dF = getDateFormatter();
+        final NumberFormat kmF = getKMFormatter();
+        final NumberFormat dwF = getDeltaWFormatter();
+        final NumberFormat qF = getQFormatter();
+        final NumberFormat wF = getWFormatter();
 
-        TreeMap<Double, ArrayList<String []>> sorted =
-            new TreeMap<Double, ArrayList<String []>>();
-
-        String referenceS = getReference();
+        final DateFormat dF = getDateFormatter();
 
-        for (KMIndex<QWD[]> reference: referenceEvents) {
+        final TreeMap<Double, ArrayList<String[]>> sorted = new TreeMap<>();
 
-            for (KMIndex.Entry<QWD[]> kmEntry: reference) {
+        final String referenceS = getReference();
 
-                Double km = kmEntry.getKm();
+        for (final KMIndex<QWD[]> reference : this.referenceEvents) {
 
-                ArrayList<String []> list = sorted.get(km);
+            for (final KMIndex.Entry<QWD[]> kmEntry : reference) {
+
+                final Double km = kmEntry.getKm();
+
+                ArrayList<String[]> list = sorted.get(km);
 
                 if (list == null) {
-                    list = new ArrayList<String []>();
+                    list = new ArrayList<>();
                     sorted.put(km, list);
                 }
 
-                String kmS = kmF.format(kmEntry.getKm());
-                for (QWD qwd: kmEntry.getValue()) {
-                    String deltaWS = dwF.format(qwd.getDeltaW());
-                    String qS      = qF.format(qwd.getQ());
-                    String wS      = wF.format(qwd.getW());
-                    String dateS   = dF.format(qwd.getDate());
+                final String kmS = kmF.format(kmEntry.getKm());
+                for (final QWD qwd : kmEntry.getValue()) {
+                    final String deltaWS = dwF.format(qwd.getDeltaW());
+                    final String qS = qF.format(qwd.getQ());
+                    final String wS = wF.format(qwd.getW());
+                    final String dateS = dF.format(qwd.getDate());
 
-                    list.add(new String[] {
-                        kmS,
-                        dateS,
-                        qS,
-                        wS,
-                        referenceS,
-                        deltaWS
-                        });
+                    list.add(new String[] { kmS, dateS, qS, wS, referenceS, deltaWS });
                 }
             }
         }
 
         if (debug) {
-            log.debug("AnalysisPeriods: " + analysisPeriods.size());
+            log.debug("AnalysisPeriods: " + this.analysisPeriods.size());
         }
 
-        String analysisTemplate = getAnalysisTemplate();
-
-        for (KMIndex<AnalysisPeriod []> periods: analysisPeriods) {
+        final String analysisTemplate = getAnalysisTemplate();
 
-            for (KMIndex.Entry<AnalysisPeriod []> kmEntry: periods) {
+        for (final KMIndex<AnalysisPeriod[]> periods : this.analysisPeriods) {
 
-                Double km = kmEntry.getKm();
+            for (final KMIndex.Entry<AnalysisPeriod[]> kmEntry : periods) {
 
-                ArrayList<String []> list = sorted.get(km);
+                final Double km = kmEntry.getKm();
+
+                ArrayList<String[]> list = sorted.get(km);
 
                 if (list == null) {
-                    list = new ArrayList<String []>();
+                    list = new ArrayList<>();
                     sorted.put(km, list);
                 }
 
-                String kmS = kmF.format(kmEntry.getKm());
+                final String kmS = kmF.format(kmEntry.getKm());
                 int analysisCount = 1;
 
-                for (AnalysisPeriod period: kmEntry.getValue()) {
+                for (final AnalysisPeriod period : kmEntry.getValue()) {
                     // Typically resulting in A1,A2...
-                    String analyisS = MessageFormat.format(analysisTemplate,
-                        analysisCount);
-                    QWD [] qwds = period.getQWDs();
+                    final String analyisS = MessageFormat.format(analysisTemplate, analysisCount);
+                    final QWD[] qwds = period.getQWDs();
 
                     if (qwds != null) {
-                        for (QWD qwd: qwds) {
-                            String deltaWS = dwF.format(qwd.getDeltaW());
-                            String qS      = qF.format(qwd.getQ());
-                            String wS      = wF.format(qwd.getW());
-                            String dateS   = dF.format(qwd.getDate());
+                        for (final QWD qwd : qwds) {
+                            final String deltaWS = dwF.format(qwd.getDeltaW());
+                            final String qS = qF.format(qwd.getQ());
+                            final String wS = wF.format(qwd.getW());
+                            final String dateS = dF.format(qwd.getDate());
 
-                            list.add(new String[] {
-                                kmS,
-                                dateS,
-                                qS,
-                                wS,
-                                analyisS,
-                                deltaWS });
+                            list.add(new String[] { kmS, dateS, qS, wS, analyisS, deltaWS });
                         }
                     }
                     ++analysisCount;
@@ -220,8 +184,8 @@
             }
         }
 
-        for (ArrayList<String []> list: sorted.values()) {
-            for (String [] row: list) {
+        for (final ArrayList<String[]> list : sorted.values()) {
+            for (final String[] row : list) {
                 writer.writeNext(row);
             }
         }
@@ -231,64 +195,56 @@
 
     /** Template to create "State" strings like A1,A2... */
     protected String getAnalysisTemplate() {
-        return Resources.getMsg(
-            context.getMeta(),
-            CSV_ANALYSIS, DEFAULT_CSV_ANALYSIS);
+        return Resources.getMsg(this.context.getMeta(), CSV_ANALYSIS, DEFAULT_CSV_ANALYSIS);
     }
 
     protected String getReference() {
-        return Resources.getMsg(
-            context.getMeta(),
-            CSV_REFERENCE, DEFAULT_CSV_REFERENCE);
+        return Resources.getMsg(this.context.getMeta(), CSV_REFERENCE, DEFAULT_CSV_REFERENCE);
     }
 
     protected NumberFormat getKMFormatter() {
-        return Formatter.getFixDeltaWKM(context);
+        return Formatter.getFixDeltaWKM(this.context);
     }
 
     protected NumberFormat getDeltaWFormatter() {
-        return Formatter.getFixDeltaWDeltaW(context);
+        return Formatter.getFixDeltaWDeltaW(this.context);
     }
 
+    @Override
     protected NumberFormat getQFormatter() {
-        return Formatter.getFixDeltaWQ(context);
+        return Formatter.getFixDeltaWQ(this.context);
     }
 
+    @Override
     protected NumberFormat getWFormatter() {
-        return Formatter.getFixDeltaWW(context);
+        return Formatter.getFixDeltaWW(this.context);
     }
 
     protected DateFormat getDateFormatter() {
-        CallMeta meta = context.getMeta();
-        return Formatter.getDateFormatter(
-            meta,
-            Resources.getMsg(
-                meta,
-                CSV_T_FORMAT,
-                DEFAULT_CSV_T_FORMAT));
+        final CallMeta meta = this.context.getMeta();
+        return Formatter.getDateFormatter(meta, Resources.getMsg(meta, CSV_T_FORMAT, DEFAULT_CSV_T_FORMAT));
     }
 
-    protected void writeCSVHeader(CSVWriter writer) {
+    protected void writeCSVHeader(final CSVWriter writer) {
         log.debug("DeltaWtExporter.writeCSVHeader");
 
-        /* issue825
-        km; Ereignis, Abfluss, GEMESSENER Wasserstand;
-        Status (RECHTSBÃœNDIG), del W
-        */
+        /*
+         * issue825
+         * km; Ereignis, Abfluss, GEMESSENER Wasserstand;
+         * Status (RECHTSBÃœNDIG), del W
+         */
+        final RiverAccess river = new RiverAccess((D4EArtifact) this.master);
+        final String unit = river.getRiver().getWstUnit().getName();
 
-        writer.writeNext(new String[] {
-            msg(CSV_KM_HEADER,      DEFAULT_CSV_KM_HEADER),
-            msg(CSV_T_HEADER,       DEFAULT_CSV_T_HEADER),
-            msg(CSV_Q_HEADER,       DEFAULT_CSV_Q_HEADER),
-            msg(CSV_W_HEADER,       DEFAULT_CSV_W_HEADER),
-            msg(CSV_TRANGE_HEADER,  DEFAULT_CSV_TRANGE_DESC_HEADER),
-            msg(CSV_DELTA_W_HEADER, DEFAULT_CSV_DELTA_W_HEADER)
-        });
+        writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_T_HEADER, DEFAULT_CSV_T_HEADER),
+                msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }),
+                msg(CSV_TRANGE_HEADER, DEFAULT_CSV_TRANGE_DESC_HEADER), msg(CSV_DELTA_W_HEADER, DEFAULT_CSV_DELTA_W_HEADER) });
     }
 
     @Override
-    protected void writePDF(OutputStream out) {
+    protected void writePDF(final OutputStream out) {
         // TODO: Implement me!
+        // wird doch NICHT erledigt vom WaterlevelExporter
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -106,24 +106,24 @@
 
 
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE);
     }
 
 
     @Override
-    protected String getChartTitle() {
+    protected String getChartTitle(final CallContext context) {
         return Resources.format(
                 context.getMeta(),
                 I18N_CHART_TITLE,
                 "",
                 FixChartGenerator
-                .getCurrentKmFromRequest(request).doubleValue());
+                .getCurrentKmFromRequest(getRequest()).doubleValue());
     }
 
 
     @Override
-    protected String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(final CallContext context) {
         FixAnalysisAccess access = new FixAnalysisAccess(artifact);
         DateRange dateRange = access.getDateRange();
         DateRange refRange  = access.getReferencePeriod();
@@ -140,7 +140,7 @@
 
 
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL);
     }
 
@@ -171,6 +171,8 @@
 
         this.artifact = (D4EArtifact)artifactFacet.getArtifact();
 
+        final CallContext context = getContext();
+        
         if (name.contains(FIX_SECTOR_AVERAGE_DWT)) {
             doSectorAverageOut(
                     (D4EArtifact) artifactFacet.getArtifact(),
@@ -388,10 +390,10 @@
             return;
         }
 
-        Locale locale = Resources.getLocale(context.getMeta());
+        Locale locale = Resources.getLocale(getContext().getMeta());
         NumberFormat nf = NumberFormat.getInstance(locale);
 
-        List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();
+        List<XYTextAnnotation> textAnnos = new ArrayList<>();
 
         for (int[] idxs: annoIdxMap.values()) {
 
--- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -28,6 +28,7 @@
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.StaticWKmsArtifact;
 import org.dive4elements.river.artifacts.WINFOArtifact;
@@ -115,7 +116,7 @@
 
     /** Returns value != 0 if the current km is not at a gauge. */
     public double getCurrentGaugeDatum() {
-        Object ckm = context.getContextValue(CURRENT_KM);
+        Object ckm = getContext().getContextValue(CURRENT_KM);
         if (ckm != null) {
             return DischargeCurveGenerator.getCurrentGaugeDatum(
                 (Double) ckm,
@@ -210,6 +211,8 @@
 
         this.artifact = (D4EArtifact) aaf.getArtifact();
 
+        final CallContext context = getContext();
+        
         if(name.startsWith(FIX_SECTOR_AVERAGE_WQ)) {
             doSectorAverageOut(aaf, doc, visible);
         }
@@ -286,7 +289,7 @@
     ) {
         log.debug("doSectorAverageOut");
 
-        QWDDateRange qwdd = (QWDDateRange) aaf.getData(context);
+        QWDDateRange qwdd = (QWDDateRange) aaf.getData(getContext());
         QWD qwd = qwdd != null ? qwdd.getQWD() : null;
 
         if(qwd != null) {
@@ -305,7 +308,7 @@
     ) {
         log.debug("doAnalysisEventsOut");
 
-        QWD qwd = (QWD)aaf.getData(context);
+        QWD qwd = (QWD)aaf.getData(getContext());
 
         if (qwd == null) {
             log.debug("doAnalysisEventsOut: qwd == null");
@@ -365,7 +368,7 @@
     ) {
         log.debug("doReferenceEventsOut");
 
-        QWI qwd = (QWI)aaf.getData(context);
+        QWI qwd = (QWI)aaf.getData(getContext());
         if (qwd == null) {
             log.debug("doReferenceEventsOut: qwds == null");
             return;
@@ -421,7 +424,7 @@
         boolean       visible
     ) {
         XYSeries series = new StyledXYSeries(title, theme);
-        Double ckm = (Double) context.getContextValue(CURRENT_KM);
+        Double ckm = (Double) getContext().getContextValue(CURRENT_KM);
         if (wqkms == null || wqkms.getKms().length == 0 || ckm == null) {
             log.info("addPointFromWQKms: No event data to show.");
             return;
@@ -458,7 +461,7 @@
     ) {
         log.debug("doEventsOut");
         // Find W/Q at km.
-        addPointFromWQKms((WQKms) aaf.getData(context),
+        addPointFromWQKms((WQKms) aaf.getData(getContext()),
             aaf.getFacetDescription(), doc, visible);
     }
 
@@ -472,7 +475,7 @@
 
         FixWQCurveFacet facet = (FixWQCurveFacet)aaf.getFacet();
         FixFunction func = (FixFunction)facet.getData(
-                aaf.getArtifact(), context);
+                aaf.getArtifact(), getContext());
 
         if (func == null) {
             log.warn("doWQCurveOut: Facet does not contain FixFunction");
@@ -527,7 +530,7 @@
     ) {
         log.debug("doOutlierOut");
 
-        QWI[] qws = (QWI[])aaf.getData(context);
+        QWI[] qws = (QWI[])aaf.getData(getContext());
         addQWSeries(qws, aaf, doc, visible);
     }
 
@@ -543,7 +546,7 @@
             return;
         }
 
-        Object qsectorsObj = aaf.getData(context);
+        Object qsectorsObj = aaf.getData(getContext());
         if (qsectorsObj == null || !(qsectorsObj instanceof List)) {
             log.warn("No QSectors coming from data.");
             return;
@@ -631,7 +634,7 @@
             log.debug("Got WKms");
             WKms data = (WKms) wqkms;
 
-            Double ckm = (Double) context.getContextValue(CURRENT_KM);
+            Double ckm = (Double) getContext().getContextValue(CURRENT_KM);
             double location = (ckm != null)
                     ? ckm.doubleValue()
                     : getRange()[0];
@@ -709,7 +712,7 @@
             // be delivered by the facet already (instead of in the Generator).
             log.debug("FixWQCurveGenerator: doWQOut: WQKms");
 
-            addPointFromWQKms((WQKms)aaf.getData(context),
+            addPointFromWQKms((WQKms)aaf.getData(getContext()),
                 aaf.getFacetDescription(), theme, visible);
         }
         else {
@@ -773,7 +776,7 @@
     }
 
     @Override
-    protected String getChartTitle() {
+    protected String getChartTitle(final CallContext context) {
         return Resources.format(
                 context.getMeta(),
                 I18N_CHART_TITLE,
@@ -782,12 +785,12 @@
     }
 
     @Override
-    protected String getDefaultChartTitle() {
+    protected String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
     }
 
     @Override
-    protected String getDefaultChartSubtitle() {
+    protected String getDefaultChartSubtitle(final CallContext context) {
         FixAnalysisAccess access = new FixAnalysisAccess(artifact);
         DateRange dateRange = access.getDateRange();
         DateRange refRange  = access.getReferencePeriod();
@@ -808,8 +811,8 @@
     }
 
     @Override
-    protected void addSubtitles(JFreeChart chart) {
-        String defaultSubtitle = getDefaultChartSubtitle();
+    protected void addSubtitles(final CallContext context, final JFreeChart chart) {
+        String defaultSubtitle = getDefaultChartSubtitle(getContext());
 
         if (defaultSubtitle == null || defaultSubtitle.length() == 0) {
             return;
@@ -841,13 +844,13 @@
     }
 
     @Override
-    protected String getDefaultXAxisLabel() {
+    protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
     }
 
     @Override
     protected String getDefaultYAxisLabel(int pos) {
-        D4EArtifact flys = (D4EArtifact) master;
+        D4EArtifact flys = getArtifact();
 
         String unit = pos == 0
             ? "cm"
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/AnnotationProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/AnnotationProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -38,7 +38,7 @@
             // Nothing to do
             return;
         }
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         if (!(bundle.getData(context) instanceof RiverAnnotation)) {
             // Just a bit defensive should not happen
             log.error("Incompatible facet in doOut");
@@ -62,7 +62,7 @@
             // Nothing to do
             return;
         }
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         if (!(bundle.getData(context) instanceof RiverAnnotation)) {
             // Just a bit defensive should not happen
             log.error("Incompatible facet in doOut");
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/AreaProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/AreaProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -83,7 +83,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         String seriesName = bundle.getFacetDescription();
         StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(theme);
 
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -43,7 +43,7 @@
             ThemeDocument    theme,
             boolean          visible
     ) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
         Map<String, String> metaData = bundle.getFacet().getMetaData(
             bundle.getArtifact(), context);
@@ -74,7 +74,7 @@
             boolean visible,
             int index
     ) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
 
         if (!(data instanceof double[][])) {
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -42,7 +42,7 @@
             ThemeDocument    theme,
             boolean          visible
     ) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData =
             bundle.getFacet().getMetaData(bundle.getArtifact(), context);
         yAxisLabel = metaData.get("Y");
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedHeightProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedHeightProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -35,6 +35,10 @@
     public static final String I18N_AXIS_LABEL =
         "chart.bedheight_middle.section.yaxis.label";
 
+    public final static String FACET_BED_HEIGHTS_MIN = "bedheight_min";
+
+    public final static String FACET_BED_HEIGHTS_MAX = "bedheight_min";
+    
     protected static final double GAP_TOLERANCE = 0.101d;
 
     protected String yAxisLabel;
@@ -46,7 +50,7 @@
             ThemeDocument    theme,
             boolean          visible) {
         XYSeries series = prepareSeries(
-            bundle, theme, generator.getCallContext());
+            bundle, theme, generator.getContext());
         if (series != null) {
             generator.addAxisSeries(series, axisName, visible);
         }
@@ -61,7 +65,7 @@
             int index
     ) {
         XYSeries series = prepareSeries(
-            bundle, theme, generator.getCallContext());
+            bundle, theme, generator.getContext());
         if (series != null) {
             generator.addAxisSeries(series, index, visible);
         }
@@ -101,6 +105,8 @@
     @Override
     public boolean canHandle(String facetType) {
         return FacetTypes.BEDHEIGHT.equals(facetType)
+            || FACET_BED_HEIGHTS_MIN.equals(facetType)
+            || FACET_BED_HEIGHTS_MAX.equals(facetType)
             || FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT1.equals(facetType)
             || FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT2.equals(facetType)
             || FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED.equals(
@@ -114,7 +120,7 @@
         D4EArtifact flys = (D4EArtifact) generator.getMaster();
         String unit = new RiverAccess(flys).getRiver().getWstUnit().getName();
 
-        CallMeta meta = generator.getCallContext().getMeta();
+        CallMeta meta = generator.getContext().getMeta();
 
         if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
             return Resources.getMsg(
@@ -127,4 +133,4 @@
                 I18N_AXIS_LABEL,
                 new Object[] { unit });
     }
-}
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDensityProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDensityProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -37,7 +37,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
         Map<String, String> metaData = bundle.getFacet().getMetaData();
@@ -69,7 +69,7 @@
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
 
-        CallMeta meta = generator.getCallContext().getMeta();
+        CallMeta meta = generator.getContext().getMeta();
 
         if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
             return Resources.getMsg(meta, yAxisLabel);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDiameterProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityDiameterProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -37,7 +37,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData = bundle.getFacet().getMetaData();
         StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
@@ -71,7 +71,7 @@
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
 
-        CallMeta meta = generator.getCallContext().getMeta();
+        CallMeta meta = generator.getContext().getMeta();
 
         if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
             return Resources.getMsg(meta, yAxisLabel);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityPorosityProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedQualityPorosityProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -37,7 +37,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData = bundle.getFacet().getMetaData();
         StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedWidthProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedWidthProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -41,7 +41,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData = bundle.getFacet().getMetaData();
         StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/DeltaWProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/DeltaWProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -88,7 +88,7 @@
     private void doSectorAverageOut(DiagramGenerator generator,
             ArtifactAndFacet bundle,
             ThemeDocument doc, boolean visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         int index = bundle.getFacet().getIndex();
         int sectorNdx = index & 3;
 
@@ -118,7 +118,7 @@
 
     private void doReferenceEventsOut(DiagramGenerator generator,
             ArtifactAndFacet bundle, ThemeDocument doc, boolean visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
 
         KMIndex<QWD> kms =
                 (KMIndex<QWD>)bundle.getData(context);
@@ -148,7 +148,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument doc,
             boolean visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
 
         KMIndex<QWD> kms =
                 (KMIndex<QWD>)bundle.getData(context);
@@ -178,7 +178,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument doc,
             boolean visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
 
         int index = bundle.getFacet().getIndex();
         int sectorNdx = index & 3;
@@ -221,7 +221,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument doc,
             boolean visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
 
         KMIndex<double[]> kms =
                 (KMIndex<double[]>)bundle.getData(context);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/DischargeProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/DischargeProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -60,7 +60,7 @@
             ThemeDocument theme,
             boolean visible
     ) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
         if (data instanceof WQKms) {
             doDischargeOut(
@@ -99,7 +99,7 @@
         ThemeDocument theme,
         boolean       visible
     ) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData = bundle.getFacet().getMetaData(
             bundle.getArtifact(), context);
         WQKms data = (WQKms)bundle.getData(context);
@@ -123,7 +123,7 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
-        CallMeta meta = generator.getCallContext().getMeta();
+        CallMeta meta = generator.getContext().getMeta();
         RiverAccess access =
             new RiverAccess((D4EArtifact)generator.getMaster());
         String unit = access.getRiver().getWstUnit().getName();
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWAProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWAProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -39,7 +39,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
 
         XYSeries series = new StyledXYSeries(
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -39,7 +39,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
 
         XYSeries series = new StyledXYSeries(
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDerivedProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDerivedProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -48,12 +48,12 @@
         ThemeDocument theme,
         boolean visible
     ) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData = bundle.getFacet().getMetaData(
             bundle.getArtifact(), context);
         FixDerivateFacet facet = (FixDerivateFacet)bundle.getFacet();
         FixFunction func = (FixFunction)facet.getData(
-                bundle.getArtifact(), generator.getCallContext());
+                bundle.getArtifact(), generator.getContext());
 
         yAxisLabel = metaData.get("Y");
 
@@ -86,7 +86,7 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
-        CallMeta meta = generator.getCallContext().getMeta();
+        CallMeta meta = generator.getContext().getMeta();
         RiverAccess access =
             new RiverAccess((D4EArtifact)generator.getMaster());
         String unit = access.getRiver().getWstUnit().getName();
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FixWQProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixWQProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -111,7 +111,7 @@
     ) {
         log.debug("doSectorAverageOut");
         QWDDateRange qwdd = (QWDDateRange)bundle.getData(
-            generator.getCallContext());
+            generator.getContext());
         QWD qwd = qwdd != null ? qwdd.getQWD() : null;
 
         if(qwd != null) {
@@ -154,7 +154,7 @@
     ) {
         log.debug("doAnalysisEventsOut");
 
-        QWD qwd = (QWD)bundle.getData(generator.getCallContext());
+        QWD qwd = (QWD)bundle.getData(generator.getContext());
 
         if (qwd == null) {
             log.debug("doAnalysisEventsOut: qwd == null");
@@ -206,7 +206,7 @@
         boolean visible) {
         log.debug("doReferenceEventsOut");
 
-        QWI qwd = (QWI)bundle.getData(generator.getCallContext());
+        QWI qwd = (QWI)bundle.getData(generator.getContext());
         if (qwd == null) {
             log.debug("doReferenceEventsOut: qwds == null in "
                 + bundle.getFacetDescription());
@@ -259,7 +259,7 @@
 
         FixWQCurveFacet facet = (FixWQCurveFacet)bundle.getFacet();
         FixFunction func = (FixFunction)facet.getData(
-                bundle.getArtifact(), generator.getCallContext());
+                bundle.getArtifact(), generator.getContext());
 
         if (func == null) {
             log.warn("doWQCurveOut: Facet does not contain FixFunction");
@@ -292,7 +292,7 @@
     ) {
         log.debug("doOutlierOut");
 
-        QWI[] qws = (QWI[])bundle.getData(generator.getCallContext());
+        QWI[] qws = (QWI[])bundle.getData(generator.getContext());
         if(qws != null) {
             XYSeries series = new StyledXYSeries(
                 bundle.getFacetDescription(),
@@ -338,7 +338,7 @@
             return;
         }
 
-        Object qsectorsObj = bundle.getData(generator.getCallContext());
+        Object qsectorsObj = bundle.getData(generator.getContext());
         if (qsectorsObj == null || !(qsectorsObj instanceof List)) {
             log.warn("No QSectors coming from data.");
             return;
@@ -405,7 +405,7 @@
         ThemeDocument    theme,
         boolean          visible
     ) {
-        Object data = bundle.getData(generator.getCallContext());
+        Object data = bundle.getData(generator.getContext());
         List<StickyAxisAnnotation> xy = new ArrayList<StickyAxisAnnotation>();
         if (data instanceof double[][]) {
             log.debug("Got double[][]");
@@ -430,7 +430,7 @@
             WKms wkms = (WKms) data;
 
             Double ckm =
-                (Double)generator.getCallContext().getContextValue(
+                (Double)generator.getContext().getContextValue(
                     FixChartGenerator.CURRENT_KM);
             double location = (ckm != null)
                     ? ckm.doubleValue()
@@ -454,14 +454,14 @@
         ThemeDocument    theme,
         boolean          visible
     ) {
-        Object data = bundle.getData(generator.getCallContext());
+        Object data = bundle.getData(generator.getContext());
         if (data instanceof WQKms) {
             WQKms wqkms = (WQKms)data;
             // TODO As in doEventsOut, the value-searching should
             // be delivered by the facet already
             XYSeries series = new StyledXYSeries(
                 bundle.getFacetDescription(), theme);
-            Double ckm = (Double) generator.getCallContext()
+            Double ckm = (Double) generator.getContext()
                 .getContextValue(CURRENT_KM);
 
             if (wqkms == null || wqkms.getKms().length == 0 || ckm == null) {
@@ -525,7 +525,7 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
-        CallMeta meta = generator.getCallContext().getMeta();
+        CallMeta meta = generator.getContext().getMeta();
 
         RiverAccess access = new RiverAccess((D4EArtifact)generator
             .getMaster());
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FlowVelocityProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FlowVelocityProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -41,7 +41,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData = bundle.getFacet().getMetaData();
         StyledXYSeries series = new StyledXYSeries(
             bundle.getFacetDescription(),
@@ -94,6 +94,9 @@
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
         if (yAxisLabel != null && !yAxisLabel.isEmpty()) {
+        	// FIXME/UNINTENDED: yAxisLabel is probably a resolved message (side-effect of StyledXYSeries#putMetadata),
+        	// and cannot be resolved again.
+        	// An explicit (German) default label is therefore given here, probably the English version will also show German (CHECK)
             return generator.msg(yAxisLabel, I18N_AXIS_LABEL_DEFAULT);
         }
         return generator.msg(
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/ManualPointsProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/ManualPointsProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -40,7 +40,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         String seriesName = bundle.getFacetDescription();
         XYSeries series = new StyledXYSeries(seriesName, theme);
         String jsonData = (String) bundle.getData(context);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/MiddleBedHeightProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/MiddleBedHeightProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -43,7 +43,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Map<String, String> metaData = bundle.getFacet().getMetaData();
         yAxisLabel = metaData.get("Y");
 
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/MiscDischargeProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/MiscDischargeProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -66,7 +66,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
         if (HISTORICAL_DISCHARGE_WQ_Q.equals(bundle.getFacetName())) {
             doHistoricalDischargeOutQ(generator, bundle, theme, visible);
@@ -108,7 +108,7 @@
             boolean visible,
             int axisIndex
     ) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
         /* TODO: Remove the first case.*/
         if (bundle.getFacetName().equals(STATIC_WQ)) {
@@ -145,7 +145,7 @@
     ) {
         XYSeries series = new StyledXYSeries(
             bundle.getFacetDescription(), theme);
-        Object wq = bundle.getData(generator.getCallContext());
+        Object wq = bundle.getData(generator.getContext());
         if (wq instanceof double[][]) {
             double [][] data = (double [][]) wq;
             StyledSeriesBuilder.addPoints(series, data, true);
@@ -278,7 +278,7 @@
         boolean visible
     ) {
         double value = Double.valueOf(
-            bundle.getData(generator.getCallContext()).toString());
+            bundle.getData(generator.getContext()).toString());
         generator.addDomainMarker(
             new StyledValueMarker(value, theme), visible);
     }
@@ -290,7 +290,7 @@
         boolean visible
     ) {
         double value = Double.valueOf(
-            bundle.getData(generator.getCallContext()).toString());
+            bundle.getData(generator.getContext()).toString());
         generator.addValueMarker(
             new StyledValueMarker(value, theme), visible);
     }
@@ -373,7 +373,7 @@
 
     @Override
     public String getAxisLabel(DiagramGenerator generator) {
-        CallMeta meta = generator.getCallContext().getMeta();
+        CallMeta meta = generator.getContext().getMeta();
         RiverAccess access = new RiverAccess((D4EArtifact)generator
             .getMaster());
         String unit = access.getRiver().getWstUnit().getName();
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/QOutProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/QOutProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -47,7 +47,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
         XYSeries series = new StyledXYSeries(
             bundle.getFacetDescription(), theme);
@@ -81,7 +81,7 @@
             boolean          visible,
             int              index)
     {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         WQKms wqkms = (WQKms) bundle.getData(context);
 
         XYSeries series = new StyledXYSeries(
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/SQRelationProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/SQRelationProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -47,7 +47,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         String facetName = bundle.getFacetName();
         StyledXYSeries series;
         Object data = bundle.getData(context);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/SedimentDensityProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/SedimentDensityProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -41,7 +41,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
         Object data = bundle.getData(context);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/SedimentLoadLSProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/SedimentLoadLSProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -31,7 +31,7 @@
             ThemeDocument    theme,
             boolean          visible) {
         log.debug("doOut " + bundle.getFacetName());
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 false, // Handle NaN
                 theme);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/SedimentLoadProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/SedimentLoadProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -41,7 +41,7 @@
             ThemeDocument    theme,
             boolean          visible) {
 
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 false, // Handle NaN
                 theme);
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/ShearStressProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/ShearStressProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -37,7 +37,7 @@
             ArtifactAndFacet bundle,
             ThemeDocument    theme,
             boolean          visible) {
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         XYSeries series = new StyledXYSeries(bundle.getFacetDescription(),
                 theme);
         String facetName = bundle.getFacetName();
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -50,7 +50,7 @@
             boolean          visible
     ) {
         log.debug("Processing facet: " + bundle.getFacetName());
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
         Object data = bundle.getData(context);
 
         XYSeries series = new StyledXYSeries(
@@ -128,7 +128,7 @@
     {
         log.debug("doOut");
 
-        CallContext context = generator.getCallContext();
+        CallContext context = generator.getContext();
 
         XYSeries series = new StyledXYSeries(
             bundle.getFacetDescription(), theme);
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/AnnotationHelper.java	Fri Feb 09 15:39:49 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,413 +0,0 @@
-/* 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.jfree;
-
-import org.dive4elements.river.themes.ThemeDocument;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.SortedMap;
-
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Font;
-
-import org.jfree.ui.TextAnchor;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.LegendItem;
-import org.jfree.chart.LegendItemCollection;
-import org.jfree.chart.annotations.XYTextAnnotation;
-import org.jfree.chart.annotations.XYLineAnnotation;
-import org.jfree.chart.renderer.xy.XYItemRenderer;
-
-import org.dive4elements.river.themes.LineStyle;
-import org.dive4elements.river.themes.TextStyle;
-import org.dive4elements.river.exports.ChartSettings;
-import org.dive4elements.river.exports.LegendSection;
-import org.dive4elements.river.exports.ChartArea;
-
-import org.apache.log4j.Logger;
-
-/** Annotation helper class, handles plotting of annotations. */
-public class AnnotationHelper {
-    private static final Logger log = Logger.getLogger(AnnotationHelper.class);
-
-    protected static float ANNOTATIONS_AXIS_OFFSET = 0.02f;
-
-    /* arr this would be better in chartsettings */
-    public static final int    DEFAULT_FONT_SIZE       = 12;
-    public static final String DEFAULT_FONT_NAME       = "Tahoma";
-
-
-    public static void addYAnnotationsToRenderer(
-        SortedMap<Integer, RiverAnnotation> yAnnotations,
-        XYPlot plot,
-        ChartSettings settings,
-        Map<Integer, AxisDataset> datasets
-    ) {
-        List<RiverAnnotation> annotations = new ArrayList<RiverAnnotation>();
-
-        for (Map.Entry<Integer, RiverAnnotation> entry:
-                 yAnnotations.entrySet()) {
-            int axis = entry.getKey();
-            AxisDataset dataset = datasets.get(new Integer(axis));
-
-            if (dataset == null || dataset.getRange() == null) {
-                log.warn("No dataset available and active for axis " + axis);
-            }
-            else {
-                RiverAnnotation ya = entry.getValue();
-                for (StickyAxisAnnotation sta: ya.getAxisTextAnnotations()) {
-                    sta.setAxisSymbol(axis);
-                }
-                annotations.add(ya);
-            }
-        }
-
-        addAnnotationsToRenderer(annotations, plot, settings, datasets);
-    }
-
-    /**
-     * Add annotations (Sticky, Text and hyk zones) to a plot.
-     * @param annotations Annotations to add
-     * @param plot XYPlot to add annotations to.
-     * @param settings ChartSettings object for settings.
-     * @param datasets Map of axis index and datasets
-     */
-    public static void addAnnotationsToRenderer(
-        List<RiverAnnotation> annotations,
-        XYPlot plot,
-        ChartSettings settings,
-        Map<Integer, AxisDataset> datasets
-    ) {
-        if (annotations == null || annotations.isEmpty()) {
-            log.debug("addAnnotationsToRenderer: no annotations.");
-            return;
-        }
-
-        // OPTMIMIZE: Pre-calculate positions
-        ChartArea area = new ChartArea(
-            plot.getDomainAxis(0),
-            plot.getRangeAxis());
-
-        // Walk over all Annotation sets.
-        for (RiverAnnotation fa: annotations) {
-
-            // Access text styling, if any.
-            ThemeDocument theme = fa.getTheme();
-            TextStyle textStyle = null;
-            LineStyle lineStyle = null;
-
-            // Get Theming information and add legend item.
-            if (theme != null) {
-                textStyle = theme.parseComplexTextStyle();
-                lineStyle = theme.parseComplexLineStyle();
-                if (fa.getLabel() != null) {
-                    // Legend handling, maybe misplaced?
-                    LegendItemCollection lic = new LegendItemCollection();
-                    LegendItemCollection old = plot.getFixedLegendItems();
-
-                    Color color = theme.parseLineColorField();
-                    if (color == null) {
-                        color = Color.BLACK;
-                    }
-
-                    Color textColor = theme.parseTextColor();
-                    if (textColor == null) {
-                        textColor = Color.BLACK;
-                    }
-
-                    LegendItem newItem = new LegendItem(fa.getLabel(), color);
-                    LegendSection ls = (settings != null ?
-                            settings.getLegendSection() : null);
-                    newItem.setLabelFont (new Font(
-                        DEFAULT_FONT_NAME,
-                        Font.PLAIN,
-                        ls != null ? ls.getFontSize() : null)
-                    );
-
-                    newItem.setLabelPaint(textColor);
-
-                    lic.add(newItem);
-                    // (Re-)Add prior legend entries.
-                    if (old != null) {
-                        old.addAll(lic);
-                    }
-                    else {
-                        old = lic;
-                    }
-                    plot.setFixedLegendItems(old);
-                }
-            }
-
-            // The 'Sticky' Annotations (at axis, with line and text).
-            for (StickyAxisAnnotation sta: fa.getAxisTextAnnotations()) {
-                addStickyAnnotation(
-                    sta, plot, area, lineStyle, textStyle, theme,
-                    datasets.get(new Integer(sta.getAxisSymbol())));
-            }
-
-            // Other Text Annotations (e.g. labels of (manual) points).
-            for (XYTextAnnotation ta: fa.getTextAnnotations()) {
-                // Style the text.
-                if (textStyle != null) {
-                    textStyle.apply(ta);
-                }
-                ta.setY(area.above(0.05d, ta.getY()));
-                plot.getRenderer().addAnnotation(
-                    ta, org.jfree.ui.Layer.FOREGROUND);
-            }
-        }
-    }
-
-    /**
-     * Add a text and a line annotation.
-     * @param area convenience to determine positions in plot.
-     * @param theme (optional) theme document
-     */
-    public static void addStickyAnnotation(
-        StickyAxisAnnotation annotation,
-        XYPlot plot,
-        ChartArea area,
-        LineStyle lineStyle,
-        TextStyle textStyle,
-        ThemeDocument theme,
-        AxisDataset dataset
-    ) {
-        // OPTIMIZE pre-calculate area-related values
-        final float TEXT_OFF = 0.03f;
-
-        XYLineAnnotation lineAnnotation = null;
-        XYTextAnnotation textAnnotation = null;
-
-        int axisIndex = annotation.getAxisSymbol();
-        XYItemRenderer renderer = null;
-        if (dataset != null && dataset.getDatasets().length > 0) {
-            renderer = plot.getRendererForDataset(dataset.getDatasets()[0]);
-        }
-        else {
-            renderer = plot.getRenderer();
-        }
-
-        if (annotation.atX()) {
-            textAnnotation = new CollisionFreeXYTextAnnotation(
-                annotation.getText(),
-                annotation.getPos(),
-                area.ofGround(TEXT_OFF));
-            // OPTIMIZE externalize the calculation involving PI.
-            //textAnnotation.setRotationAngle(270f*Math.PI/180f);
-            lineAnnotation = createGroundStickAnnotation(
-                area, annotation.getPos(), lineStyle);
-            textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
-            textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
-        }
-        else {
-            // Stick to the "right" (opposed to left) Y-Axis.
-            if (axisIndex != 0 && plot.getRangeAxis(axisIndex) != null) {
-                // OPTIMIZE: Pass a different area to this function,
-                //           do the adding to renderer outside (let this
-                //           function return the annotations).
-                //           Note that this path is travelled rarely.
-                textAnnotation = new CollisionFreeXYTextAnnotation(
-                    annotation.getText(),
-                    area.ofRight(TEXT_OFF),
-                    annotation.getPos()
-                );
-                textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT);
-                textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT);
-                lineAnnotation = createRightStickAnnotation(
-                    area, annotation.getPos(), lineStyle);
-
-                // hit-lines for duration curve
-                ChartArea area2 = new ChartArea(
-                    plot.getDomainAxis(), plot.getRangeAxis(axisIndex));
-                if (!Float.isNaN(annotation.getHitPoint()) && theme != null) {
-                    // New line annotation to hit curve.
-                    if (theme.parseShowVerticalLine()) {
-                        XYLineAnnotation hitLineAnnotation =
-                            createStickyLineAnnotation(
-                                StickyAxisAnnotation.SimpleAxis.X_AXIS,
-                                annotation.getHitPoint(), annotation.getPos(),
-                                // annotation.getHitPoint(),
-                                area2, lineStyle);
-                        renderer.addAnnotation(hitLineAnnotation,
-                            org.jfree.ui.Layer.BACKGROUND);
-                    }
-                    if (theme.parseShowHorizontalLine()) {
-                        XYLineAnnotation lineBackAnnotation =
-                            createStickyLineAnnotation(
-                                StickyAxisAnnotation.SimpleAxis.Y_AXIS2,
-                                annotation.getPos(), annotation.getHitPoint(),
-                                area2, lineStyle);
-                        renderer.addAnnotation(lineBackAnnotation,
-                            org.jfree.ui.Layer.BACKGROUND);
-                    }
-                }
-            }
-            else { // Stick to the left y-axis.
-                textAnnotation = new CollisionFreeXYTextAnnotation(
-                    annotation.getText(),
-                    area.ofLeft(TEXT_OFF),
-                    annotation.getPos());
-                textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
-                textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
-                lineAnnotation = createLeftStickAnnotation(
-                    area, annotation.getPos(), lineStyle);
-                if (!Float.isNaN(annotation.getHitPoint()) && theme != null) {
-                    // New line annotation to hit curve.
-                    if (theme.parseShowHorizontalLine()) {
-                        XYLineAnnotation hitLineAnnotation =
-                            createStickyLineAnnotation(
-                                StickyAxisAnnotation.SimpleAxis.Y_AXIS,
-                                annotation.getPos(), annotation.getHitPoint(),
-                                area, lineStyle);
-                        renderer.addAnnotation(hitLineAnnotation,
-                            org.jfree.ui.Layer.BACKGROUND);
-                    }
-                    if (theme.parseShowVerticalLine()) {
-                        XYLineAnnotation lineBackAnnotation =
-                            createStickyLineAnnotation(
-                                StickyAxisAnnotation.SimpleAxis.X_AXIS,
-                                annotation.getHitPoint(), annotation.getPos(),
-                                area, lineStyle);
-                        renderer.addAnnotation(lineBackAnnotation,
-                            org.jfree.ui.Layer.BACKGROUND);
-                    }
-                }
-            }
-        }
-
-        // Style the text.
-        if (textStyle != null) {
-            textStyle.apply(textAnnotation);
-        }
-
-        // Add the Annotations to renderer.
-        renderer.addAnnotation(textAnnotation, org.jfree.ui.Layer.FOREGROUND);
-        renderer.addAnnotation(lineAnnotation, org.jfree.ui.Layer.FOREGROUND);
-    }
-
-   /**
-     * Create annotation that sticks to "ground" (X) axis.
-     * @param area helper to calculate coordinates
-     * @param pos one-dimensional position (distance from axis)
-     * @param lineStyle the line style to use for the line.
-     */
-    public static XYLineAnnotation createGroundStickAnnotation(
-        ChartArea area, float pos, LineStyle lineStyle
-    ) {
-        // Style the line.
-        if (lineStyle != null) {
-            return new XYLineAnnotation(
-                pos, area.atGround(),
-                pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET),
-                new BasicStroke(lineStyle.getWidth()),lineStyle.getColor());
-        }
-        else {
-            return new XYLineAnnotation(
-                pos, area.atGround(),
-                pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET));
-        }
-    }
-
-
-    /**
-     * Create annotation that sticks to the second Y axis ("right").
-     * @param area helper to calculate coordinates
-     * @param pos one-dimensional position (distance from axis)
-     * @param lineStyle the line style to use for the line.
-     */
-    public static XYLineAnnotation createRightStickAnnotation(
-        ChartArea area, float pos, LineStyle lineStyle
-    ) {
-        // Style the line.
-        if (lineStyle != null) {
-            return new XYLineAnnotation(
-                area.atRight(), pos,
-                area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos,
-                new BasicStroke(lineStyle.getWidth()), lineStyle.getColor());
-        }
-        else {
-            return new XYLineAnnotation(
-                area.atRight(), pos,
-                area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos);
-        }
-    }
-    /**
-     * Create annotation that sticks to the first Y axis ("left").
-     * @param area helper to calculate coordinates
-     * @param pos one-dimensional position (distance from axis)
-     * @param lineStyle the line style to use for the line.
-     */
-    public static XYLineAnnotation createLeftStickAnnotation(
-        ChartArea area, float pos, LineStyle lineStyle
-    ) {
-        // Style the line.
-        if (lineStyle != null) {
-            return new XYLineAnnotation(
-                area.atLeft(), pos,
-                area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos,
-                new BasicStroke(lineStyle.getWidth()), lineStyle.getColor());
-        }
-        else {
-            return new XYLineAnnotation(
-                area.atLeft(), pos,
-                area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos);
-        }
-    }
-
-
-    /**
-     * Create a line from a axis to a given point.
-     * @param axis   The "simple" axis.
-     * @param fromD1 from-location in first dimension.
-     * @param toD2   to-location in second dimension.
-     * @param area   helper to calculate offsets.
-     * @param lineStyle optional line style.
-     */
-    public static XYLineAnnotation createStickyLineAnnotation(
-        StickyAxisAnnotation.SimpleAxis axis, float fromD1, float toD2,
-        ChartArea area, LineStyle lineStyle
-    ) {
-        double anchorX1 = 0d, anchorX2 = 0d, anchorY1 = 0d, anchorY2 = 0d;
-        switch(axis) {
-            case X_AXIS:
-                anchorX1 = fromD1;
-                anchorX2 = fromD1;
-                anchorY1 = area.atGround();
-                anchorY2 = toD2;
-                break;
-            case Y_AXIS:
-                anchorX1 = area.atLeft();
-                anchorX2 = toD2;
-                anchorY1 = fromD1;
-                anchorY2 = fromD1;
-                break;
-            case Y_AXIS2:
-                anchorX1 = area.atRight();
-                anchorX2 = toD2;
-                anchorY1 = fromD1;
-                anchorY2 = fromD1;
-                break;
-        }
-        // Style the line.
-        if (lineStyle != null) {
-            return new XYLineAnnotation(
-                anchorX1, anchorY1,
-                anchorX2, anchorY2,
-                new BasicStroke(lineStyle.getWidth()), lineStyle.getColor());
-        }
-        else {
-            return new XYLineAnnotation(
-                anchorX1, anchorY1,
-                anchorX2, anchorY2);
-        }
-    }
-
-};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/AreaFillPattern.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,79 @@
+/** 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.jfree;
+
+import java.awt.Color;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.LookupOp;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Fill patterns for area styles.
+ * REMARK: if this enum is changed, probably the ui in StyleEditorWindow must be changed too
+ *
+ * @author Gernot Belger
+ */
+public enum AreaFillPattern {
+
+    patternFill("/images/areapatterns/patternFill.png"), //
+    patternPoints("/images/areapatterns/patternPoints.png"), //
+    paternCross("/images/areapatterns/paternCross.png"), //
+    patternDagonalLeft("/images/areapatterns/patternDagonalLeft.png"), //
+    patternDiagonalRight("/images/areapatterns/patternDiagonalRight.png");
+
+    private static Logger log = Logger.getLogger(AreaFillPattern.class);
+
+    private static final BufferedImage MISSING_IMAGE = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
+
+    private final String imagePath;
+
+    private BufferedImage image = null;
+
+    AreaFillPattern(final String imagePath) {
+        this.imagePath = imagePath;
+    }
+
+    public BufferedImage getImage(final Color color) {
+
+        if (this.image == null)
+            this.image = loadImage();
+
+        if (color == null)
+            return this.image;
+
+        /*
+         * apply color and transparency, the .png must be encoded as 32bit images (rgba), with only black as non transparent
+         * color
+         */
+        final int numComponents = this.image.getColorModel().getNumComponents();
+        if (numComponents != 4) {
+            log.warn(String.format("Pattern image must be a 32bit image (rgba): %s", this.imagePath));
+            return this.image;
+        }
+
+        final BufferedImageOp lookup = new LookupOp(new ColorMapper(Color.black, color), null);
+        return lookup.filter(this.image, null);
+    }
+
+    private BufferedImage loadImage() {
+        try {
+            return ImageIO.read(getClass().getResource(this.imagePath));
+        }
+        catch (final IOException e) {
+            log.error(String.format("failed ot load pattern: %s", this.imagePath), e);
+            return MISSING_IMAGE;
+        }
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/AxisDataset.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/AxisDataset.java	Fri Jul 13 11:56:22 2018 +0200
@@ -71,10 +71,15 @@
         for (XYDataset dataset: datasets) {
             Range newRange = null;
             if (dataset instanceof StyledAreaSeriesCollection) {
-                /* We do not include areas in the range calculation because
-                 * they are used with very large / small values to draw areas
-                 * with axis boundaries */
-                continue;
+                final StyledAreaSeriesCollection areaSeries = (StyledAreaSeriesCollection) dataset;
+                if( areaSeries.shouldCalculateRange() )
+                    newRange = areaSeries.getRangeBounds(false);
+                else {
+                    /* For most area themes, we do not include areas in the range calculation because
+                     * they are used with very large / small values to draw areas
+                     * with axis boundaries */
+                    continue;
+                }
             } else if (dataset instanceof RangeInfo) {
                 /* The usual case for most series */
                 newRange = ((RangeInfo) dataset).getRangeBounds(false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/ColorMapper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,43 @@
+/** 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.jfree;
+
+import java.awt.Color;
+import java.awt.image.LookupTable;
+
+final class ColorMapper extends LookupTable {
+
+    private final int[] from;
+    private final int[] to;
+
+    public ColorMapper(final Color from, final Color to) {
+        super(0, 4);
+
+        this.from = new int[] { from.getRed(), from.getGreen(), from.getBlue(), from.getAlpha(), };
+        this.to = new int[] { to.getRed(), to.getGreen(), to.getBlue(), to.getAlpha(), };
+    }
+
+    @Override
+    public int[] lookupPixel(final int[] src, final int[] dest) {
+        final int[] out = dest == null ? new int[src.length] : dest;
+
+        // REMARK: only compare rgb, so we even keep the transparency level
+        if (src[0] == this.from[0] && src[1] == this.from[1] && src[2] == this.from[2]) {
+            out[0] = this.to[0];
+            out[1] = this.to[1];
+            out[2] = this.to[2];
+            out[3] = src[3];
+        } else {
+            System.arraycopy(src, 0, out, 0, src.length);
+        }
+
+        return out;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/DoubleBounds.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/DoubleBounds.java	Fri Jul 13 11:56:22 2018 +0200
@@ -51,7 +51,7 @@
 
     @Override
     public void applyBounds(ValueAxis axis) {
-        axis.setRange(new Range(lower, upper));
+        axis.setRangeWithMargins(new Range(lower, upper));
     }
 
 
@@ -67,7 +67,7 @@
             axis.setRange(new Range(Math.max(lower-space, 0.0001),
                         Math.max(upper+space, 0.0002)));
         } else {
-            axis.setRange(new Range(lower-space, upper+space));
+            axis.setRangeWithMargins(new Range(lower-space, upper+space));
         }
     }
 
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/EnhancedLineAndShapeRenderer.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/EnhancedLineAndShapeRenderer.java	Fri Jul 13 11:56:22 2018 +0200
@@ -45,8 +45,7 @@
     private static final long serialVersionUID = 1L;
 
     /** Own log. */
-    private static final Logger log =
-        Logger.getLogger(EnhancedLineAndShapeRenderer.class);
+    private static final Logger log = Logger.getLogger(EnhancedLineAndShapeRenderer.class);
 
     protected BooleanList isMinimumShapeVisible;
     protected BooleanList isMaximumShapeVisible;
@@ -61,95 +60,85 @@
     protected BooleanList showLineLabelBG;
     protected Map<Integer, Color> lineLabelBGColors;
 
-
-    public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) {
+    public EnhancedLineAndShapeRenderer(final boolean lines, final boolean shapes) {
         super(lines, shapes);
         this.isMinimumShapeVisible = new BooleanList();
         this.isMaximumShapeVisible = new BooleanList();
-        this.showLineLabel         = new BooleanList();
-        this.showLineLabelBG       = new BooleanList();
-        this.seriesMinimum         = new HashMap<Integer, Double>();
-        this.seriesMaximum         = new HashMap<Integer, Double>();
-        this.seriesMinimumX        = new HashMap<Integer, Double>();
-        this.lineLabelFonts        = new HashMap<Integer, Font>();
-        this.lineLabelTextColors   = new HashMap<Integer, Color>();
-        this.lineLabelBGColors     = new HashMap<Integer, Color>();
+        this.showLineLabel = new BooleanList();
+        this.showLineLabelBG = new BooleanList();
+        this.seriesMinimum = new HashMap<>();
+        this.seriesMaximum = new HashMap<>();
+        this.seriesMinimumX = new HashMap<>();
+        this.lineLabelFonts = new HashMap<>();
+        this.lineLabelTextColors = new HashMap<>();
+        this.lineLabelBGColors = new HashMap<>();
     }
 
-
     /**
      * Draw a background-box of a text to render.
-     * @param g2 graphics device to use
-     * @param text text to draw
-     * @param textX x-position for text
-     * @param textY y-position for text
-     * @param bgColor color to fill box with.
+     *
+     * @param g2
+     *            graphics device to use
+     * @param text
+     *            text to draw
+     * @param textX
+     *            x-position for text
+     * @param textY
+     *            y-position for text
+     * @param bgColor
+     *            color to fill box with.
      */
-    public static void drawTextBox(Graphics2D g2,
-        String text, float textX, float textY, Color bgColor
-    ) {
-        Rectangle2D hotspotBox = g2.getFontMetrics().getStringBounds(text, g2);
-        float w = (float)hotspotBox.getWidth();
-        float h = (float)hotspotBox.getHeight();
-        hotspotBox.setRect(textX, textY-h, w, h);
-        Color oldColor = g2.getColor();
+    public static void drawTextBox(final Graphics2D g2, final String text, final float textX, final float textY, final Color bgColor) {
+        final Rectangle2D hotspotBox = g2.getFontMetrics().getStringBounds(text, g2);
+        final float w = (float) hotspotBox.getWidth();
+        final float h = (float) hotspotBox.getHeight();
+        hotspotBox.setRect(textX, textY - h, w, h);
+        final Color oldColor = g2.getColor();
         g2.setColor(bgColor);
         g2.fill(hotspotBox);
         g2.setColor(oldColor);
     }
 
-
     /**
      * Whether or not a specific item in a series (maybe the maxima) should
      * be rendered with shape.
      */
-    public boolean getItemShapeVisible(
-        XYDataset dataset,
-        int series,
-        int item
-    ){
+    private boolean getItemShapeVisible(final XYDataset dataset, final int series, final int item) {
         if (super.getItemShapeVisible(series, item)) {
             return true;
         }
 
-        if (isMinimumShapeVisible(series)
-            && isMinimum(dataset, series, item)
-        ) {
+        if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) {
             return true;
         }
 
-        if (isMaximumShapeVisible(series)
-            && isMaximum(dataset, series, item)
-        ) {
+        if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) {
             return true;
         }
 
         return false;
     }
 
-
     /**
      * Rectangle used to draw maximums shape.
      */
-    public Shape getMaximumShape(int series, int column) {
+    private Shape getMaximumShape(final int series, final int column) {
         return new Rectangle2D.Double(-5d, -5d, 10d, 10d);
     }
 
-
     /**
      * Rectangle used to draw minimums shape.
      */
-    public Shape getMinimumShape(int series, int column) {
+    private Shape getMinimumShape(final int series, final int column) {
         return new Rectangle2D.Double(-5d, -5d, 10d, 10d);
     }
 
-
     /** Get fill paint for the maximum indicators. */
-    public Paint getMaximumFillPaint(int series, int column) {
-        Paint p = getItemPaint(series, column);
+    private Paint getMaximumFillPaint(final int series, final int column) {
+        final Paint p = getItemPaint(series, column);
 
         if (p instanceof Color) {
-            Color c = (Color) p;
+            final Color c = (Color) p;
             Color b = c;
 
             for (int i = 0; i < 2; i++) {
@@ -163,13 +152,12 @@
         return p;
     }
 
-
     /** Get fill paint for the minimum indicators. */
-    public Paint getMinimumFillPaint(int series, int column) {
-        Paint p = getItemPaint(series, column);
+    private Paint getMinimumFillPaint(final int series, final int column) {
+        final Paint p = getItemPaint(series, column);
 
         if (p instanceof Color) {
-            Color c = (Color) p;
+            final Color c = (Color) p;
             Color b = c;
 
             for (int i = 0; i < 2; i++) {
@@ -183,82 +171,63 @@
         return p;
     }
 
-
     /**
      * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted
      * method getItemShapeVisible() which now takes an XYDataset. So, 99% of
      * code equal the code in XYLineAndShapeRenderer.
      */
     @Override
-    protected void drawSecondaryPass(
-        Graphics2D       g2,
-        XYPlot           plot,
-        XYDataset        dataset,
-        int              pass,
-        int              series,
-        int              item,
-        ValueAxis        domainAxis,
-        Rectangle2D      dataArea,
-        ValueAxis        rangeAxis,
-        CrosshairState   crosshairState,
-        EntityCollection entities
-    ) {
+    protected void drawSecondaryPass(final Graphics2D g2, final XYPlot plot, final XYDataset dataset, final int pass, final int series, final int item,
+            final ValueAxis domainAxis, final Rectangle2D dataArea, final ValueAxis rangeAxis, final CrosshairState crosshairState,
+            final EntityCollection entities) {
         Shape entityArea = null;
 
         // get the data point...
-        double x1 = dataset.getXValue(series, item);
-        double y1 = dataset.getYValue(series, item);
+        final double x1 = dataset.getXValue(series, item);
+        final double y1 = dataset.getYValue(series, item);
         if (Double.isNaN(y1) || Double.isNaN(x1)) {
             return;
         }
 
-        PlotOrientation orientation = plot.getOrientation();
-        RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
-        RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
-        double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
-        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
+        final PlotOrientation orientation = plot.getOrientation();
+        final RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
+        final RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
+        final double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
+        final double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
 
         if (getItemShapeVisible(dataset, series, item)) {
             Shape shape = null;
 
             // OPTIMIZE: instead of calculating minimum and maximum for every
-            //           point, calculate it just once (assume that dataset
-            //           content does not change during rendering).
-            // NOTE:     Above OPTIMIZE might already be fulfilled to
-            //           most extend.
-            boolean isMinimum = isMinimumShapeVisible(series)
-                && isMinimum(dataset, series, item);
+            // point, calculate it just once (assume that dataset
+            // content does not change during rendering).
+            // NOTE: Above OPTIMIZE might already be fulfilled to
+            // most extend.
+            final boolean isMinimum = isMinimumShapeVisible(series) && isMinimum(dataset, series, item);
 
-            boolean isMaximum = isMaximumShapeVisible(series)
-                && isMaximum(dataset, series, item);
+            final boolean isMaximum = isMaximumShapeVisible(series) && isMaximum(dataset, series, item);
 
             if (isMinimum) {
                 log.debug("Create a Minimum shape.");
                 shape = getMinimumShape(series, item);
-            }
-            else if (isMaximum) {
+            } else if (isMaximum) {
                 log.debug("Create a Maximum shape.");
                 shape = getMaximumShape(series, item);
-            }
-            else {
+            } else {
                 shape = getItemShape(series, item);
             }
 
             if (orientation == PlotOrientation.HORIZONTAL) {
-                shape = ShapeUtilities.createTranslatedShape(shape, transY1,
-                        transX1);
-            }
-            else if (orientation == PlotOrientation.VERTICAL) {
-                shape = ShapeUtilities.createTranslatedShape(shape, transX1,
-                        transY1);
+                shape = ShapeUtilities.createTranslatedShape(shape, transY1, transX1);
+            } else if (orientation == PlotOrientation.VERTICAL) {
+                shape = ShapeUtilities.createTranslatedShape(shape, transX1, transY1);
             }
             entityArea = shape;
             if (shape.intersects(dataArea)) {
                 if (getItemShapeFilled(series, item)) {
                     if (getUseFillPaint()) {
                         g2.setPaint(getItemFillPaint(series, item));
-                    }
-                    else {
+                    } else {
                         g2.setPaint(getItemPaint(series, item));
                     }
                     g2.fill(shape);
@@ -266,8 +235,7 @@
                 if (getDrawOutlines()) {
                     if (getUseOutlinePaint()) {
                         g2.setPaint(getItemOutlinePaint(series, item));
-                    }
-                    else {
+                    } else {
                         g2.setPaint(getItemPaint(series, item));
                     }
                     g2.setStroke(getItemOutlineStroke(series, item));
@@ -280,8 +248,7 @@
                     g2.setPaint(getItemOutlinePaint(series, item));
                     g2.setStroke(getItemOutlineStroke(series, item));
                     g2.draw(shape);
-                }
-                else if (isMaximum) {
+                } else if (isMaximum) {
                     g2.setPaint(getMaximumFillPaint(series, item));
                     g2.fill(shape);
                     g2.setPaint(getItemOutlinePaint(series, item));
@@ -299,78 +266,27 @@
         }
 
         // Draw the item label if there is one...
-        if (isItemLabelVisible(series, item)) {
-            drawItemLabel(g2, orientation, dataset, series, item, xx, yy,
-                    (y1 < 0.0));
-        }
+        if (isItemLabelVisible(series, item))
+            drawItemLabel(g2, orientation, dataset, series, item, xx, yy, (y1 < 0.0));
 
         // Draw label of line.
-        if (dataset instanceof XYSeriesCollection
-            && isShowLineLabel(series)
-            && isMinimumX (dataset, series, item)
-            ) {
-            XYSeries xYSeries = ((XYSeriesCollection)dataset)
-                .getSeries(series);
-            String waterlevelLabel = (xYSeries instanceof HasLabel)
-                ? ((HasLabel)xYSeries).getLabel()
-                : xYSeries.getKey().toString();
+        if (dataset instanceof XYSeriesCollection && isShowLineLabel(series) && isMinimumX(dataset, series, item)) {
+            final XYSeries xYSeries = ((XYSeriesCollection) dataset).getSeries(series);
+            final String waterlevelLabel = (xYSeries instanceof HasLabel) ? ((HasLabel) xYSeries).getLabel() : xYSeries.getKey().toString();
             // TODO Force water of some German rivers to flow
             // direction mountains.
 
-            Font oldFont = g2.getFont();
-
-            Color oldColor = g2.getColor();
-            g2.setFont(this.getLineLabelFont(series));
-            g2.setColor(this.getLineLabelTextColor(series));
-            g2.setBackground(Color.black);
-
-            // Try to always display label if the data is visible.
-            if (!isPointInRect(dataArea, xx, yy)) {
-                // Move into the data area.
-                xx = Math.max(xx, dataArea.getMinX());
-                xx = Math.min(xx, dataArea.getMaxX());
-                yy = Math.max(yy, dataArea.getMinY());
-                yy = Math.min(yy, dataArea.getMaxY());
-            }
+            final Font labelFont = this.getLineLabelFont(series);
+            final Color labelColor = this.getLineLabelTextColor(series);
+            final boolean showBG = isShowLineLabelBG(series);
+            final Color bgColor = getLineLabelBGColor(series);
 
-            // Move to right until no collisions exist anymore
-            Shape hotspot = TextUtilities.calculateRotatedStringBounds(
-                waterlevelLabel, g2, (float)xx, (float)yy-3f,
-                TextAnchor.CENTER_LEFT,
-                0f, TextAnchor.CENTER_LEFT);
-            while (JFreeUtil.collides(hotspot, entities,
-                                      CollisionFreeLineLabelEntity.class)) {
-                xx += 5f;
-                hotspot = TextUtilities.calculateRotatedStringBounds(
-                    waterlevelLabel,
-                    g2,
-                    (float)xx,
-                    (float)yy-3f,
-                    TextAnchor.CENTER_LEFT,
-                    0f,
-                    TextAnchor.CENTER_LEFT);
-            }
-
-            // Register to avoid collissions.
-            entities.add(new CollisionFreeLineLabelEntity(hotspot,
-                1, "", ""));
-
-            // Fill background.
-            if (isShowLineLabelBG(series)) {
-                drawTextBox(g2, waterlevelLabel, (float)xx, (float)yy-3f,
-                    getLineLabelBGColor(series));
-            }
-
-            g2.drawString(waterlevelLabel, (float)xx, (float)yy-3f);
-
-            g2.setFont(oldFont);
-            g2.setColor(oldColor);
+            drawLineLabel(g2, dataArea, entities, xx, yy, labelFont, labelColor, showBG, bgColor, waterlevelLabel);
         }
 
-        int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
-        int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
-        updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex,
-                rangeAxisIndex, transX1, transY1, orientation);
+        final int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
+        final int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
+        updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, rangeAxisIndex, transX1, transY1, orientation);
 
         // Add an entity for the item, but only if it falls within the data
         // area...
@@ -379,77 +295,115 @@
         }
     }
 
+    public static void drawLineLabel(final Graphics2D g2, final Rectangle2D dataArea, final EntityCollection entities, final double labelX, final double labelY,
+            final Font font,
+            final Color fgColor,
+            final boolean showBG, final Color bgColor, final String label) {
+
+        final Font oldFont = g2.getFont();
+        final Color oldColor = g2.getColor();
+
+        g2.setFont(font);
+        g2.setColor(fgColor);
+        g2.setBackground(Color.black);
+
+        // Try to always display label if the data is visible.
+        double posX = labelX;
+        double posY = labelY;
+        if (!isPointInRect(dataArea, posX, posY)) {
+            // Move into the data area.
+            posX = Math.max(posX, dataArea.getMinX());
+            posX = Math.min(posX, dataArea.getMaxX());
+            posY = Math.max(posY, dataArea.getMinY());
+            posY = Math.min(posY, dataArea.getMaxY());
+        }
+
+        // Move to right until no collisions exist anymore
+        Shape hotspot = TextUtilities.calculateRotatedStringBounds(label, g2, (float) posX, (float) posY - 3f, TextAnchor.CENTER_LEFT, 0f,
+                TextAnchor.CENTER_LEFT);
+        while (JFreeUtil.collides(hotspot, entities, CollisionFreeLineLabelEntity.class)) {
+            posX += 5f;
+            hotspot = TextUtilities.calculateRotatedStringBounds(label, g2, (float) posX, (float) posY - 3f, TextAnchor.CENTER_LEFT, 0f,
+                    TextAnchor.CENTER_LEFT);
+        }
+
+        // Register to avoid collissions.
+        entities.add(new CollisionFreeLineLabelEntity(hotspot, 1, "", ""));
+
+        // Fill background.
+        if (showBG)
+            drawTextBox(g2, label, (float) posX, (float) posY - 3f, bgColor);
+
+        g2.drawString(label, (float) posX, (float) posY - 3f);
+
+        g2.setFont(oldFont);
+        g2.setColor(oldColor);
+    }
 
     /**
      * Sets whether or not the minimum should be rendered with shape.
      */
-    public void setIsMinimumShapeVisisble(int series, boolean isVisible) {
+    public void setIsMinimumShapeVisisble(final int series, final boolean isVisible) {
         this.isMinimumShapeVisible.setBoolean(series, isVisible);
     }
 
-
     /**
      * Whether or not the minimum should be rendered with shape.
      */
-    public boolean isMinimumShapeVisible(int series) {
+    private boolean isMinimumShapeVisible(final int series) {
         if (this.isMinimumShapeVisible.size() <= series) {
             return false;
         }
 
-        return isMinimumShapeVisible.getBoolean(series);
+        return this.isMinimumShapeVisible.getBoolean(series);
     }
 
-
     /**
      * Sets whether or not the maximum should be rendered with shape.
      */
-    public void setIsMaximumShapeVisible(int series, boolean isVisible) {
+    public void setIsMaximumShapeVisible(final int series, final boolean isVisible) {
         this.isMaximumShapeVisible.setBoolean(series, isVisible);
     }
 
-
     /**
      * Whether or not the maximum should be rendered with shape.
      */
-    public boolean isMaximumShapeVisible(int series) {
+    private boolean isMaximumShapeVisible(final int series) {
         if (this.isMaximumShapeVisible.size() <= series) {
             return false;
         }
 
-        return isMaximumShapeVisible.getBoolean(series);
+        return this.isMaximumShapeVisible.getBoolean(series);
     }
 
     /** Whether or not a label should be shown for series. */
-    public boolean isShowLineLabel(int series) {
+    private boolean isShowLineLabel(final int series) {
         if (this.showLineLabel.size() <= series) {
             return false;
         }
 
-        return showLineLabel.getBoolean(series);
+        return this.showLineLabel.getBoolean(series);
     }
 
-
     /** Sets whether or not a label should be shown for series. */
-    public void setShowLineLabel(boolean showLineLabel, int series) {
+    public void setShowLineLabel(final boolean showLineLabel, final int series) {
         this.showLineLabel.setBoolean(series, showLineLabel);
     }
 
-
     /** Whether or not a label should be shown for series. */
-    public boolean isShowLineLabelBG(int series) {
+    private boolean isShowLineLabelBG(final int series) {
         if (this.showLineLabelBG.size() <= series) {
             return false;
         }
 
-        return showLineLabelBG.getBoolean(series);
+        return this.showLineLabelBG.getBoolean(series);
     }
 
-
-    public void setShowLineLabelBG(int series, boolean doShow) {
+    public void setShowLineLabelBG(final int series, final boolean doShow) {
         this.showLineLabelBG.setBoolean(series, doShow);
     }
 
-    public Color getLineLabelBGColor(int series) {
+    private Color getLineLabelBGColor(final int series) {
         if (this.lineLabelBGColors.size() <= series) {
             return null;
         }
@@ -457,11 +411,11 @@
         return this.lineLabelBGColors.get(series);
     }
 
-    public void setLineLabelBGColor(int series, Color color) {
+    public void setLineLabelBGColor(final int series, final Color color) {
         this.lineLabelBGColors.put(series, color);
     }
 
-    public Color getLineLabelTextColor(int series) {
+    private Color getLineLabelTextColor(final int series) {
         if (this.lineLabelTextColors.size() <= series) {
             return null;
         }
@@ -469,35 +423,33 @@
         return this.lineLabelTextColors.get(series);
     }
 
-    public void setLineLabelTextColor(int series, Color color) {
+    public void setLineLabelTextColor(final int series, final Color color) {
         this.lineLabelTextColors.put(series, color);
     }
 
-    public void setLineLabelFont(Font font, int series) {
+    public void setLineLabelFont(final Font font, final int series) {
         this.lineLabelFonts.put(series, font);
     }
 
-    public Font getLineLabelFont(int series) {
+    private Font getLineLabelFont(final int series) {
         return this.lineLabelFonts.get(series);
     }
 
-
     /**
      * True if the given item of given dataset has the smallest
      * X value within this set.
      */
-    public boolean isMinimumX(XYDataset dataset, int series, int item) {
+    private boolean isMinimumX(final XYDataset dataset, final int series, final int item) {
         return dataset.getXValue(series, item) == getMinimumX(dataset, series);
     }
 
-
     /**
      * Get Minimum X Value of a given series in a dataset.
      * The value is stored for later use if queried the first time.
      */
-    public double getMinimumX(XYDataset dataset, int series) {
-        Integer key = Integer.valueOf(series);
-        Double  old = seriesMinimumX.get(key);
+    private double getMinimumX(final XYDataset dataset, final int series) {
+        final Integer key = Integer.valueOf(series);
+        final Double old = this.seriesMinimumX.get(key);
 
         if (old != null) {
             return old.doubleValue();
@@ -508,35 +460,33 @@
         double min = Double.MAX_VALUE;
 
         for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
-            double tmpValue = dataset.getXValue(series, i);
+            final double tmpValue = dataset.getXValue(series, i);
 
             if (tmpValue < min) {
                 min = tmpValue;
             }
         }
 
-        seriesMinimumX.put(key, Double.valueOf(min));
+        this.seriesMinimumX.put(key, Double.valueOf(min));
 
         return min;
     }
 
-
     /**
      * True if the given item of given dataset has the smallest
      * Y value within this set.
      */
-    public boolean isMinimum(XYDataset dataset, int series, int item) {
+    private boolean isMinimum(final XYDataset dataset, final int series, final int item) {
         return dataset.getYValue(series, item) == getMinimum(dataset, series);
     }
 
-
     /**
      * Get Minimum Y Value of a given series in a dataset.
      * The value is stored for later use if queried the first time.
      */
-    public double getMinimum(XYDataset dataset, int series) {
-        Integer key = Integer.valueOf(series);
-        Double  old = seriesMinimum.get(key);
+    private double getMinimum(final XYDataset dataset, final int series) {
+        final Integer key = Integer.valueOf(series);
+        final Double old = this.seriesMinimum.get(key);
 
         if (old != null) {
             return old.doubleValue();
@@ -547,35 +497,33 @@
         double min = Double.MAX_VALUE;
 
         for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
-            double tmpValue = dataset.getYValue(series, i);
+            final double tmpValue = dataset.getYValue(series, i);
 
             if (tmpValue < min) {
                 min = tmpValue;
             }
         }
 
-        seriesMinimum.put(key, Double.valueOf(min));
+        this.seriesMinimum.put(key, Double.valueOf(min));
 
         return min;
     }
 
-
     /**
      * True if the given item of given dataset has the biggest
      * Y value within this set.
      */
-    public boolean isMaximum(XYDataset dataset, int series, int item) {
+    private boolean isMaximum(final XYDataset dataset, final int series, final int item) {
         return dataset.getYValue(series, item) == getMaximum(dataset, series);
     }
 
-
     /**
      * Get maximum Y Value of a given series in a dataset.
      * The value is stored for later use if queried the first time.
      */
-    public double getMaximum(XYDataset dataset, int series) {
-        Integer key = Integer.valueOf(series);
-        Double  old = seriesMaximum.get(key);
+    private double getMaximum(final XYDataset dataset, final int series) {
+        final Integer key = Integer.valueOf(series);
+        final Double old = this.seriesMaximum.get(key);
 
         if (old != null) {
             return old.doubleValue();
@@ -586,16 +534,15 @@
         double max = -Double.MAX_VALUE;
 
         for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
-            double tmpValue = dataset.getYValue(series, i);
+            final double tmpValue = dataset.getYValue(series, i);
 
             if (tmpValue > max) {
                 max = tmpValue;
             }
         }
 
-        seriesMaximum.put(key, Double.valueOf(max));
+        this.seriesMaximum.put(key, Double.valueOf(max));
 
         return max;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java	Fri Jul 13 11:56:22 2018 +0200
@@ -87,23 +87,26 @@
 
 import java.awt.BasicStroke;
 import java.awt.Color;
-import java.awt.Graphics2D;
 import java.awt.Font;
+import java.awt.Graphics2D;
 import java.awt.Paint;
-import java.awt.geom.Point2D;
 import java.awt.Shape;
 import java.awt.Stroke;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.log4j.Logger;
+import org.dive4elements.river.artifacts.math.Linear;
 import org.jfree.chart.LegendItem;
 import org.jfree.chart.axis.ValueAxis;
 import org.jfree.chart.entity.EntityCollection;
@@ -114,50 +117,44 @@
 import org.jfree.chart.plot.PlotOrientation;
 import org.jfree.chart.plot.PlotRenderingInfo;
 import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.AbstractXYItemRenderer;
+import org.jfree.chart.renderer.xy.XYItemRendererState;
 import org.jfree.chart.urls.XYURLGenerator;
+import org.jfree.data.xy.DefaultXYDataset;
 import org.jfree.data.xy.XYDataset;
-import org.jfree.data.xy.DefaultXYDataset;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
 import org.jfree.io.SerialUtilities;
 import org.jfree.ui.RectangleEdge;
 import org.jfree.util.PaintUtilities;
 import org.jfree.util.PublicCloneable;
 import org.jfree.util.ShapeUtilities;
 
-import org.jfree.chart.renderer.xy.AbstractXYItemRenderer;
-import org.jfree.chart.renderer.xy.XYItemRenderer;
-import org.jfree.chart.renderer.xy.XYItemRendererState;
-
 import gnu.trove.TDoubleArrayList;
 
-import org.dive4elements.river.artifacts.math.Linear;
-
-import java.text.NumberFormat;
-
-import org.apache.log4j.Logger;
-
 /**
  * A renderer for an {@link XYPlot} that highlights the differences between two
- * series.  The example shown here is generated by the
+ * series. The example shown here is generated by the
  * <code>DifferenceChartDemo1.java</code> program included in the JFreeChart
  * demo collection:
- * <br><br>
+ * <br>
+ * <br>
  * <img src="../../../../../images/StableXYDifferenceRendererSample.png"
  * alt="StableXYDifferenceRendererSample.png" />
  */
-public class StableXYDifferenceRenderer extends AbstractXYItemRenderer
-        implements XYItemRenderer, PublicCloneable {
+public class StableXYDifferenceRenderer extends AbstractXYItemRenderer implements PublicCloneable {
 
-    private static Logger log = Logger.getLogger(
-        StableXYDifferenceRenderer.class);
+    private static Logger log = Logger.getLogger(StableXYDifferenceRenderer.class);
 
     public static final int CALCULATE_POSITIVE_AREA = 1;
     public static final int CALCULATE_NEGATIVE_AREA = 2;
-    public static final int CALCULATE_ALL_AREA =
-                            CALCULATE_POSITIVE_AREA | CALCULATE_NEGATIVE_AREA;
+    public static final int CALCULATE_ALL_AREA = CALCULATE_POSITIVE_AREA | CALCULATE_NEGATIVE_AREA;
 
     /** For serialization. */
     private static final long serialVersionUID = -8447915602375584857L;
 
+    private boolean drawArea = true;
+
     /** The paint used to highlight positive differences (y(0) &gt; y(1)). */
     private transient Paint positivePaint;
 
@@ -168,225 +165,173 @@
     private boolean shapesVisible;
 
     /** Display shapes at each point? */
-    protected boolean drawOutline;
+    private boolean drawOutline;
 
     /** Which stroke to draw outline with? */
-    protected Stroke outlineStroke;
+    private Stroke outlineStroke;
 
     /** Which paint to draw outline with? */
-    protected Paint outlinePaint;
+    private Paint outlinePaint;
 
     /** The shape to display in the legend item. */
     private transient Shape legendShape;
 
-    protected boolean drawOriginalSeries;
-
-    /** The color of the label showing the calculated area. */
-    protected Color labelColor;
-
-    /** The background color of the label showing the calculated area. */
-    protected Color labelBGColor;
-
-    /** Font to draw label of calculated area with. */
-    protected Font labelFont;
-
-    /** Template to create i18ned label for area. */
-    protected String areaLabelTamplate;
+    private final boolean drawOriginalSeries;
 
     /** NumberFormat to use for area. */
-    protected NumberFormat areaLabelNumberFormat;
-
-    protected int areaCalculationMode;
+    private NumberFormat areaLabelNumberFormat;
 
-    protected double positiveArea;
-    protected double negativeArea;
+    private int areaCalculationMode;
 
-    /** Whether or not to draw a label in the area. */
-    protected boolean labelArea = true;
+    private double positiveArea;
 
+    private double negativeArea;
+
+    /** The color of the label showing the calculated area. */
+    private Color labelColor;
+
+    /** The background color of the label showing the calculated area. */
+    private Color labelBGColor;
+
+    /** Font to draw label of calculated area with. */
+    private Font labelFont;
+
+    /** Whether or not to draw a label that shows the title of the theme. */
+    private boolean drawTitleLabel = false;
+
+    /** Whether or not to draw a label that shows the area of the polygon. */
+    private boolean drawAreaLabel = false;
+
+    /** Template to create i18ned label for area. */
+    private String areaLabelTamplate;
 
     /** Arithmetic centroid of drawn polygons. */
-    protected Point2D.Double centroid;
-
+    private Point2D.Double centroid;
 
     /** Number of points that contributed to the centroid. */
-    protected int centroidNPoints = 0;
-
+    private int centroidNPoints = 0;
 
     /**
      * This flag controls whether or not the x-coordinates (in Java2D space)
-     * are rounded to integers.  When set to true, this can avoid the vertical
-     * striping that anti-aliasing can generate.  However, the rounding may not
+     * are rounded to integers. When set to true, this can avoid the vertical
+     * striping that anti-aliasing can generate. However, the rounding may not
      * be appropriate for output in high resolution formats (for example,
      * vector graphics formats such as SVG and PDF).
      *
      * @since 1.0.4
      */
-    private boolean roundXCoordinates;
+    private final boolean roundXCoordinates;
+
+    /** Holds the minimal x value in screen coordinates, will updated during the draw operation */
+    private transient double minimumScreenX = Double.POSITIVE_INFINITY;
+
+    /** Holds the y value in screen coordinates at the minimum x value **/
+    private transient double minimumScreenX_Y = Double.POSITIVE_INFINITY;
 
     /**
      * Creates a new renderer with default attributes.
      */
     public StableXYDifferenceRenderer() {
-        this(Color.green, Color.red, false /*,  null */);
-    }
-
-    public StableXYDifferenceRenderer(Paint positivePaint, Paint negativePaint,
-                                boolean shapes) {
-        this(positivePaint, negativePaint, shapes, CALCULATE_ALL_AREA);
+        this(Color.green, Color.red, false, CALCULATE_ALL_AREA);
     }
 
     /**
      * Creates a new renderer.
      *
-     * @param positivePaint  the highlight color for positive differences
-     *                       (<code>null</code> not permitted).
-     * @param negativePaint  the highlight color for negative differences
-     *                       (<code>null</code> not permitted).
-     * @param shapes  draw shapes?
+     * @param positivePaint
+     *            the highlight color for positive differences
+     *            (<code>null</code> not permitted).
+     * @param negativePaint
+     *            the highlight color for negative differences
+     *            (<code>null</code> not permitted).
+     * @param shapes
+     *            draw shapes?
      */
-    public StableXYDifferenceRenderer(Paint positivePaint, Paint negativePaint,
-                                boolean shapes, int areaCalculationMode) {
+    private StableXYDifferenceRenderer(final Paint positivePaint, final Paint negativePaint, final boolean shapes, final int areaCalculationMode) {
         if (positivePaint == null) {
-            throw new IllegalArgumentException(
-                    "Null 'positivePaint' argument.");
+            throw new IllegalArgumentException("Null 'positivePaint' argument.");
         }
         if (negativePaint == null) {
-            throw new IllegalArgumentException(
-                    "Null 'negativePaint' argument.");
+            throw new IllegalArgumentException("Null 'negativePaint' argument.");
         }
         this.positivePaint = positivePaint;
         this.negativePaint = negativePaint;
         this.shapesVisible = shapes;
-        this.legendShape   = new Rectangle2D.Double(-3.0, -3.0, 10.0, 10.0);
+        this.legendShape = new Rectangle2D.Double(-3.0, -3.0, 10.0, 10.0);
         this.roundXCoordinates = false;
-        this.drawOutline   = true;
+        this.drawOutline = true;
         this.outlineStroke = new BasicStroke(1);
-        this.outlinePaint  = Color.black;
+        this.outlinePaint = Color.black;
         this.drawOriginalSeries = false;
         this.areaCalculationMode = areaCalculationMode;
-        this.labelBGColor  = null;
-        this.centroid      = new Point2D.Double(0,0);
+        this.labelBGColor = null;
+        this.centroid = new Point2D.Double(0, 0);
     }
 
-    public int getAreaCalculationMode() {
-        return areaCalculationMode;
-    }
-
-    public void setAreaCalculationMode(int areaCalculationMode) {
+    public void setAreaCalculationMode(final int areaCalculationMode) {
         this.areaCalculationMode = areaCalculationMode;
     }
 
-
     /** Set template to use to create area label (e.g. 'Area=%dm2'). */
-    public void setAreaLabelTemplate(String areaTemplate) {
+    public void setAreaLabelTemplate(final String areaTemplate) {
         this.areaLabelTamplate = areaTemplate;
     }
 
-
-    public void setAreaLabelNumberFormat(NumberFormat nf) {
+    public void setAreaLabelNumberFormat(final NumberFormat nf) {
         this.areaLabelNumberFormat = nf;
     }
 
-
-    public boolean isLabelArea() {
-        return this.labelArea;
+    public void setShowAreaLabel(final boolean doDrawAreaLabel) {
+        this.drawAreaLabel = doDrawAreaLabel;
     }
 
-    public void setLabelArea(boolean label) {
-        this.labelArea = label;
+    public void setShowTitleLabel(final boolean doDrawTitleLabel) {
+        this.drawTitleLabel = doDrawTitleLabel;
     }
 
-
     /** Set font to paint label with. */
-    public void setLabelFont(Font font) {
+    public void setLabelFont(final Font font) {
         this.labelFont = font;
     }
 
-
-    /** Get font with which label is painted. */
-    public Font getLabelFont() {
-        return this.labelFont;
-    }
-
-
     /** Set color with which to paint label. */
-    public void setLabelColor(Color color) {
+    public void setLabelColor(final Color color) {
         this.labelColor = color;
     }
 
-
-    /** Get color with which label is painted. */
-    public Color getLabelColor() {
-        return this.labelColor;
-    }
-
-
     /** Set color with which to paint label bg. */
-    public void setLabelBGColor(Color color) {
+    public void setLabelBGColor(final Color color) {
         this.labelBGColor = color;
     }
 
-
-    /** Get color with which label is painted. */
-    public Color getLabelBGColor() {
-        return this.labelBGColor;
-    }
-
-
-    public double getCalculatedArea() {
-        return positiveArea + negativeArea;
-    }
-
     /**
      * Sets color that is used if drawOutline is true.
      */
-    public void setOutlinePaint(Paint outlinePaint) {
+    @Override
+    public void setOutlinePaint(final Paint outlinePaint) {
         this.outlinePaint = outlinePaint;
     }
 
-
-    /**
-     * Gets color which is used if drawOutline is true.
-     */
-    public Paint getOutlinePaint() {
-        return this.outlinePaint;
-    }
-
-
     /**
      * Sets Stroke that is used if drawOutline is true.
      */
-    public void setOutlineStroke(Stroke stroke) {
+    @Override
+    public void setOutlineStroke(final Stroke stroke) {
         this.outlineStroke = stroke;
     }
 
-
-    /**
-     * Returns Stroke that is used if drawOutline is true.
-     */
-    public Stroke getOutlineStroke() {
-        return this.outlineStroke;
-    }
-
-
     /**
      * Whether or not to draw the 'Shape' of the area (in contrast to
      * shapes at data items).
      */
-    public void setDrawOutline(boolean doDrawOutline) {
+    public void setDrawOutline(final boolean doDrawOutline) {
         this.drawOutline = doDrawOutline;
     }
 
-
-    /**
-     * Returns whether or not to draw the shape of the outline.
-     */
-    public boolean getDrawOutline() {
-        return this.drawOutline;
+    public void setDrawArea(final boolean doDrawArea) {
+        this.drawArea = doDrawArea;
     }
 
-
     /**
      * Returns the paint used to highlight positive differences.
      *
@@ -394,7 +339,7 @@
      *
      * @see #setPositivePaint(Paint)
      */
-    public Paint getPositivePaint() {
+    private Paint getPositivePaint() {
         return this.positivePaint;
     }
 
@@ -402,14 +347,12 @@
      * Sets the paint used to highlight positive differences and sends a
      * {@link RendererChangeEvent} to all registered listeners.
      *
-     * @param paint  the paint (<code>null</code> not permitted).
+     * @param paint
+     *            the paint (<code>null</code> not permitted).
      *
      * @see #getPositivePaint()
      */
-    public void setPositivePaint(Paint paint) {
-        if (paint == null) {
-            throw new IllegalArgumentException("Null 'paint' argument.");
-        }
+    public void setPositivePaint(final Paint paint) {
         this.positivePaint = paint;
         fireChangeEvent();
     }
@@ -421,21 +364,19 @@
      *
      * @see #setNegativePaint(Paint)
      */
-    public Paint getNegativePaint() {
+    private Paint getNegativePaint() {
         return this.negativePaint;
     }
 
     /**
      * Sets the paint used to highlight negative differences.
      *
-     * @param paint  the paint (<code>null</code> not permitted).
+     * @param paint
+     *            the paint (<code>null</code> not permitted).
      *
      * @see #getNegativePaint()
      */
-    public void setNegativePaint(Paint paint) {
-        if (paint == null) {
-            throw new IllegalArgumentException("Null 'paint' argument.");
-        }
+    public void setNegativePaint(final Paint paint) {
         this.negativePaint = paint;
         notifyListeners(new RendererChangeEvent(this));
     }
@@ -448,7 +389,7 @@
      *
      * @see #setShapesVisible(boolean)
      */
-    public boolean getShapesVisible() {
+    private boolean getShapesVisible() {
         return this.shapesVisible;
     }
 
@@ -457,11 +398,12 @@
      * data value, and sends a {@link RendererChangeEvent} to all registered
      * listeners.
      *
-     * @param flag  the flag.
+     * @param flag
+     *            the flag.
      *
      * @see #getShapesVisible()
      */
-    public void setShapesVisible(boolean flag) {
+    public void setShapesVisible(final boolean flag) {
         this.shapesVisible = flag;
         fireChangeEvent();
     }
@@ -473,80 +415,36 @@
      *
      * @see #setLegendLine(Shape)
      */
-    public Shape getLegendLine() {
+    private Shape getLegendLine() {
         return this.legendShape;
     }
 
     /**
-     * Sets the shape used as a line in each legend item and sends a
-     * {@link RendererChangeEvent} to all registered listeners.
-     *
-     * @param line  the line (<code>null</code> not permitted).
-     *
-     * @see #getLegendLine()
-     */
-    public void setLegendLine(Shape line) {
-        if (line == null) {
-            throw new IllegalArgumentException("Null 'line' argument.");
-        }
-        this.legendShape = line;
-        fireChangeEvent();
-    }
-
-    /**
-     * Returns the flag that controls whether or not the x-coordinates (in
-     * Java2D space) are rounded to integer values.
-     *
-     * @return The flag.
-     *
-     * @since 1.0.4
-     *
-     * @see #setRoundXCoordinates(boolean)
-     */
-    public boolean getRoundXCoordinates() {
-        return this.roundXCoordinates;
-    }
-
-    /**
-     * Sets the flag that controls whether or not the x-coordinates (in
-     * Java2D space) are rounded to integer values, and sends a
-     * {@link RendererChangeEvent} to all registered listeners.
-     *
-     * @param round  the new flag value.
-     *
-     * @since 1.0.4
-     *
-     * @see #getRoundXCoordinates()
-     */
-    public void setRoundXCoordinates(boolean round) {
-        this.roundXCoordinates = round;
-        fireChangeEvent();
-    }
-
-    /**
-     * Initialises the renderer and returns a state object that should be
-     * passed to subsequent calls to the drawItem() method.  This method will
+     * Initializes the renderer and returns a state object that should be
+     * passed to subsequent calls to the drawItem() method. This method will
      * be called before the first item is rendered, giving the renderer an
-     * opportunity to initialise any state information it wants to maintain.
+     * opportunity to initialize any state information it wants to maintain.
      * The renderer can do nothing if it chooses.
      *
-     * @param g2  the graphics device.
-     * @param dataArea  the (visible) area inside the axes.
-     * @param plot  the plot.
-     * @param data  the data.
-     * @param info  an optional info collection object to return data back to
-     *              the caller.
+     * @param g2
+     *            the graphics device.
+     * @param dataArea
+     *            the (visible) area inside the axes.
+     * @param plot
+     *            the plot.
+     * @param data
+     *            the data.
+     * @param info
+     *            an optional info collection object to return data back to
+     *            the caller.
      *
      * @return A state object.
      */
-    public XYItemRendererState initialise(Graphics2D g2,
-                                          Rectangle2D dataArea,
-                                          XYPlot plot,
-                                          XYDataset data,
-                                          PlotRenderingInfo info) {
+    @Override
+    public XYItemRendererState initialise(final Graphics2D g2, final Rectangle2D dataArea, final XYPlot plot, final XYDataset data,
+            final PlotRenderingInfo info) {
 
-        XYItemRendererState state = super.initialise(g2, dataArea, plot, data,
-                info);
+        final XYItemRendererState state = super.initialise(g2, dataArea, plot, data, info);
         state.setProcessVisibleItemsOnly(false);
         return state;
     }
@@ -557,55 +455,42 @@
      *
      * @return The number of passes required by the renderer.
      */
+    @Override
     public int getPassCount() {
         return 2;
     }
 
-
     /**
      * Adds x/y data to series.
      */
-    private static final void addSeries(
-        DefaultXYDataset ds,
-        Comparable       key,
-        TDoubleArrayList xs,
-        TDoubleArrayList ys
-    ) {
-        ds.addSeries(
-            key,
-            new double [][] {
-                xs.toNativeArray(),
-                ys.toNativeArray()
-            });
+    private static final void addSeries(final DefaultXYDataset ds, final Comparable key, final TDoubleArrayList xs, final TDoubleArrayList ys) {
+        ds.addSeries(key, new double[][] { xs.toNativeArray(), ys.toNativeArray() });
     }
 
-    protected static List<XYDataset> splitByNaNsOneSeries(
-        XYDataset dataset
-    ) {
-        List<XYDataset> datasets = new ArrayList<XYDataset>();
+    private static List<XYDataset> splitByNaNsOneSeries(final XYDataset dataset) {
+        final List<XYDataset> datasets = new ArrayList<>();
 
-        int N = dataset.getItemCount(0);
-        TDoubleArrayList xs = new TDoubleArrayList(N);
-        TDoubleArrayList ys = new TDoubleArrayList(N);
+        final int N = dataset.getItemCount(0);
+        final TDoubleArrayList xs = new TDoubleArrayList(N);
+        final TDoubleArrayList ys = new TDoubleArrayList(N);
         for (int i = 0; i < N; ++i) {
-            double x = dataset.getXValue(0, i);
-            double y = dataset.getYValue(0, i);
+            final double x = dataset.getXValue(0, i);
+            final double y = dataset.getYValue(0, i);
             if (Double.isNaN(x) || Double.isNaN(y)) {
                 if (!xs.isEmpty()) {
-                    DefaultXYDataset ds = new DefaultXYDataset();
+                    final DefaultXYDataset ds = new DefaultXYDataset();
                     addSeries(ds, dataset.getSeriesKey(0), xs, ys);
                     datasets.add(ds);
                     xs.resetQuick();
                     ys.resetQuick();
                 }
-            }
-            else {
+            } else {
                 xs.add(x);
                 ys.add(y);
             }
         }
         if (!xs.isEmpty()) {
-            DefaultXYDataset ds = new DefaultXYDataset();
+            final DefaultXYDataset ds = new DefaultXYDataset();
             addSeries(ds, dataset.getSeriesKey(0), xs, ys);
             datasets.add(ds);
         }
@@ -613,30 +498,30 @@
         return datasets;
     }
 
-    private static final boolean add(TDoubleArrayList xs, double x) {
-        int N = xs.size();
-        if (N == 0 || xs.getQuick(N-1) < x) {
+    private static final boolean add(final TDoubleArrayList xs, final double x) {
+        final int N = xs.size();
+        if (N == 0 || xs.getQuick(N - 1) < x) {
             xs.add(x);
             return true;
         }
         return false;
     }
 
-    protected static boolean hasNaN(XYDataset dataset) {
-        int N = dataset.getItemCount(0);
-        int M = dataset.getItemCount(1);
+    private static boolean hasNaN(final XYDataset dataset) {
+        final int N = dataset.getItemCount(0);
+        final int M = dataset.getItemCount(1);
 
         for (int i = 0; i < N; ++i) {
-            double x = dataset.getXValue(0, i);
-            double y = dataset.getYValue(0, i);
+            final double x = dataset.getXValue(0, i);
+            final double y = dataset.getYValue(0, i);
             if (Double.isNaN(x) || Double.isNaN(y)) {
                 return true;
             }
         }
 
         for (int j = 0; j < M; ++j) {
-            double x = dataset.getXValue(1, j);
-            double y = dataset.getYValue(1, j);
+            final double x = dataset.getXValue(1, j);
+            final double y = dataset.getYValue(1, j);
             if (Double.isNaN(x) || Double.isNaN(y)) {
                 return true;
             }
@@ -644,76 +529,73 @@
         return false;
     }
 
+    private static List<XYDataset> splitByNaNsTwoSeries(final XYDataset dataset) {
+        final boolean debug = log.isDebugEnabled();
 
-    protected static List<XYDataset> splitByNaNsTwoSeries(
-        XYDataset dataset
-    ) {
-        boolean debug = log.isDebugEnabled();
-
-        List<XYDataset> datasets = new ArrayList<XYDataset>();
+        final List<XYDataset> datasets = new ArrayList<>();
 
         if (!hasNaN(dataset)) {
             datasets.add(dataset);
             return datasets;
         }
 
-        int N = dataset.getItemCount(0);
-        int M = dataset.getItemCount(1);
+        final int N = dataset.getItemCount(0);
+        final int M = dataset.getItemCount(1);
 
         int i = 0, j = 0;
         // ignore leading NaNs
         for (; i < N; ++i) {
-            double x = dataset.getXValue(0, i);
-            double y = dataset.getYValue(0, i);
+            final double x = dataset.getXValue(0, i);
+            final double y = dataset.getYValue(0, i);
             if (!Double.isNaN(x) && !Double.isNaN(y)) {
                 break;
             }
         }
 
         for (; j < M; ++j) {
-            double x = dataset.getXValue(1, j);
-            double y = dataset.getYValue(1, j);
+            final double x = dataset.getXValue(1, j);
+            final double y = dataset.getYValue(1, j);
             if (!Double.isNaN(x) && !Double.isNaN(y)) {
                 break;
             }
         }
 
-        TDoubleArrayList six = new TDoubleArrayList();
-        TDoubleArrayList siy = new TDoubleArrayList();
-        TDoubleArrayList sjx = new TDoubleArrayList();
-        TDoubleArrayList sjy = new TDoubleArrayList();
+        final TDoubleArrayList six = new TDoubleArrayList();
+        final TDoubleArrayList siy = new TDoubleArrayList();
+        final TDoubleArrayList sjx = new TDoubleArrayList();
+        final TDoubleArrayList sjy = new TDoubleArrayList();
 
         while (i < N && j < M) {
-            int ni = i+1;
-            for (; ni < N && !Double.isNaN(dataset.getXValue(0, ni)); ++ni);
-            for (; ni < N &&  Double.isNaN(dataset.getXValue(0, ni)); ++ni);
+            int ni = i + 1;
+            for (; ni < N && !Double.isNaN(dataset.getXValue(0, ni)); ++ni)
+                ;
+            for (; ni < N && Double.isNaN(dataset.getXValue(0, ni)); ++ni)
+                ;
 
-            int nj = j+1;
-            for (; nj < M && !Double.isNaN(dataset.getXValue(1, nj)); ++nj);
-            for (; nj < M &&  Double.isNaN(dataset.getXValue(1, nj)); ++nj);
+            int nj = j + 1;
+            for (; nj < M && !Double.isNaN(dataset.getXValue(1, nj)); ++nj)
+                ;
+            for (; nj < M && Double.isNaN(dataset.getXValue(1, nj)); ++nj)
+                ;
 
             if (ni == N && nj == M) { // no more splits
                 log.debug("no more splits ....");
                 for (; i < ni; ++i) {
-                    double x = dataset.getXValue(0, i);
-                    double y = dataset.getYValue(0, i);
-                    if (!Double.isNaN(x)
-                    &&  !Double.isNaN(y)
-                    &&  add(six, x)) {
+                    final double x = dataset.getXValue(0, i);
+                    final double y = dataset.getYValue(0, i);
+                    if (!Double.isNaN(x) && !Double.isNaN(y) && add(six, x)) {
                         siy.add(y);
                     }
                 }
                 for (; j < nj; ++j) {
-                    double x = dataset.getXValue(1, j);
-                    double y = dataset.getYValue(1, j);
-                    if (!Double.isNaN(x)
-                    &&  !Double.isNaN(y)
-                    &&  add(sjx, x)) {
+                    final double x = dataset.getXValue(1, j);
+                    final double y = dataset.getYValue(1, j);
+                    if (!Double.isNaN(x) && !Double.isNaN(y) && add(sjx, x)) {
                         sjy.add(y);
                     }
                 }
                 if (!six.isEmpty() && !sjx.isEmpty()) {
-                    DefaultXYDataset ds = new DefaultXYDataset();
+                    final DefaultXYDataset ds = new DefaultXYDataset();
                     addSeries(ds, dataset.getSeriesKey(0), six, siy);
                     addSeries(ds, dataset.getSeriesKey(1), sjx, sjy);
                     datasets.add(ds);
@@ -726,15 +608,11 @@
                 log.debug("nj: " + nj + " " + M);
             }
 
-            double xni = ni < N
-                ? dataset.getXValue(0, ni)
-                : Double.MAX_VALUE;
+            final double xni = ni < N ? dataset.getXValue(0, ni) : Double.MAX_VALUE;
 
-            double xnj = nj < M
-                ? dataset.getXValue(1, nj)
-                : Double.MAX_VALUE;
+            final double xnj = nj < M ? dataset.getXValue(1, nj) : Double.MAX_VALUE;
 
-            double xns = Math.min(xni, xnj);
+            final double xns = Math.min(xni, xnj);
 
             double pushxi = Double.NaN;
             double pushyi = Double.NaN;
@@ -742,8 +620,8 @@
             double pushyj = Double.NaN;
 
             for (; i < ni; ++i) {
-                double x = dataset.getXValue(0, i);
-                double y = dataset.getYValue(0, i);
+                final double x = dataset.getXValue(0, i);
+                final double y = dataset.getYValue(0, i);
                 if (Double.isNaN(x) || Double.isNaN(y)) {
                     continue;
                 }
@@ -757,19 +635,16 @@
                     if (add(six, x)) {
                         siy.add(y);
                     }
-                    pushxi = x; pushyi = y;
-                }
-                else { // x > xns: intersection
+                    pushxi = x;
+                    pushyi = y;
+                } else { // x > xns: intersection
                     if (debug) {
                         log.debug("xns: " + xns);
                         log.debug("x/y: " + x + " / " + y);
                     }
-                    int SIX = six.size();
+                    final int SIX = six.size();
                     if (SIX > 0) { // should always be true
-                        double yns = Linear.linear(
-                            xns,
-                            six.getQuick(SIX-1), x,
-                            siy.getQuick(SIX-1), y);
+                        final double yns = Linear.linear(xns, six.getQuick(SIX - 1), x, siy.getQuick(SIX - 1), y);
                         if (debug) {
                             log.debug("intersection at: " + yns);
                         }
@@ -784,8 +659,8 @@
             }
 
             for (; j < nj; ++j) {
-                double x = dataset.getXValue(1, j);
-                double y = dataset.getYValue(1, j);
+                final double x = dataset.getXValue(1, j);
+                final double y = dataset.getYValue(1, j);
                 if (Double.isNaN(x) || Double.isNaN(y)) {
                     continue;
                 }
@@ -799,36 +674,36 @@
                     if (add(sjx, x)) {
                         sjy.add(y);
                     }
-                    pushxj = x; pushyj = y;
-                }
-                else { // x > xns: intersection
-                    int SJX = sjx.size();
+                    pushxj = x;
+                    pushyj = y;
+                } else { // x > xns: intersection
+                    final int SJX = sjx.size();
                     if (SJX > 0) { // should always be true
-                        double yns = Linear.linear(
-                            xns,
-                            sjx.getQuick(SJX-1), x,
-                            sjy.getQuick(SJX-1), y);
+                        final double yns = Linear.linear(xns, sjx.getQuick(SJX - 1), x, sjy.getQuick(SJX - 1), y);
                         if (debug) {
                             log.debug("intersection at: " + yns);
                         }
                         if (add(sjx, xns)) {
                             sjy.add(yns);
                         }
-                        pushxj = xns; pushyj = yns;
+                        pushxj = xns;
+                        pushyj = yns;
                     }
                 }
                 break; // Split point reached.
             }
 
             if (!six.isEmpty() && !sjx.isEmpty()) {
-                DefaultXYDataset ds = new DefaultXYDataset();
+                final DefaultXYDataset ds = new DefaultXYDataset();
                 addSeries(ds, dataset.getSeriesKey(0), six, siy);
                 addSeries(ds, dataset.getSeriesKey(1), sjx, sjy);
                 datasets.add(ds);
             }
 
-            six.resetQuick(); siy.resetQuick();
-            sjx.resetQuick(); sjy.resetQuick();
+            six.resetQuick();
+            siy.resetQuick();
+            sjx.resetQuick();
+            sjy.resetQuick();
 
             // Push split points.
             if (!Double.isNaN(pushxi)) {
@@ -844,28 +719,24 @@
 
         // Copy the rest.
         for (; i < N; ++i) {
-            double x = dataset.getXValue(0, i);
-            double y = dataset.getXValue(0, i);
-            if (!Double.isNaN(x)
-            &&  !Double.isNaN(y)
-            &&  add(six, x)) {
+            final double x = dataset.getXValue(0, i);
+            final double y = dataset.getXValue(0, i);
+            if (!Double.isNaN(x) && !Double.isNaN(y) && add(six, x)) {
                 siy.add(y);
             }
         }
 
         for (; j < M; ++j) {
-            double x = dataset.getXValue(1, j);
-            double y = dataset.getXValue(1, j);
-            if (!Double.isNaN(x)
-            &&  !Double.isNaN(y)
-            &&  add(sjx, x)) {
+            final double x = dataset.getXValue(1, j);
+            final double y = dataset.getXValue(1, j);
+            if (!Double.isNaN(x) && !Double.isNaN(y) && add(sjx, x)) {
                 sjy.add(y);
             }
         }
 
         // Build final dataset.
         if (!six.isEmpty() && !sjx.isEmpty()) {
-            DefaultXYDataset ds = new DefaultXYDataset();
+            final DefaultXYDataset ds = new DefaultXYDataset();
             addSeries(ds, dataset.getSeriesKey(0), six, siy);
             addSeries(ds, dataset.getSeriesKey(1), sjx, sjy);
             datasets.add(ds);
@@ -876,241 +747,194 @@
         }
 
         /*
-        log.debug("Begin dump datasets: ");
-        log.debug("Original");
-        i=0;
-        dumpDataset(dataset, "Original" );
-        for (XYDataset set: datasets) {
-            dumpDataset(dataset, "New: " + i++);
-        }
-        log.debug("End dump datasets: ");
-        */
+         * log.debug("Begin dump datasets: ");
+         * log.debug("Original");
+         * i=0;
+         * dumpDataset(dataset, "Original" );
+         * for (XYDataset set: datasets) {
+         * dumpDataset(dataset, "New: " + i++);
+         * }
+         * log.debug("End dump datasets: ");
+         */
 
         return datasets;
     }
 
     /*
-    public static void dumpDataset(XYDataset dataset, String msg) {
-        log.debug("Begin dump Dataset: " + msg);
-
-        int N = dataset.getItemCount(0);
-        int M = dataset.getItemCount(1);
+     * public static void dumpDataset(XYDataset dataset, String msg) {
+     * log.debug("Begin dump Dataset: " + msg);
+     * int N = dataset.getItemCount(0);
+     * int M = dataset.getItemCount(1);
+     * int i = 0, j = 0;
+     * for (; i < N; ++i) {
+     * double x = dataset.getXValue(0, i);
+     * double y = dataset.getYValue(0, i);
+     * log.debug("0 " + i + " X: "+ x + "Y: "+ y);
+     * }
+     * for (; j < M; ++j) {
+     * double x = dataset.getXValue(1, j);
+     * double y = dataset.getYValue(1, j);
+     * log.debug("1 " + i + " X: "+ x + "Y: "+ y);
+     * }
+     * log.debug("End dump Dataset: " + msg);
+     * }
+     */
 
-        int i = 0, j = 0;
-        for (; i < N; ++i) {
-            double x = dataset.getXValue(0, i);
-            double y = dataset.getYValue(0, i);
-            log.debug("0 " + i + " X: "+ x + "Y: "+ y);
-        }
-
-        for (; j < M; ++j) {
-            double x = dataset.getXValue(1, j);
-            double y = dataset.getYValue(1, j);
-            log.debug("1 " + i + " X: "+ x + "Y: "+ y);
-        }
-        log.debug("End dump Dataset: " + msg);
-    }
-    */
-
-
-    public static List<XYDataset> splitByNaNs(XYDataset dataset)  {
+    private static List<XYDataset> splitByNaNs(final XYDataset dataset) {
 
         switch (dataset.getSeriesCount()) {
-            case 0:
-                return Collections.<XYDataset>emptyList();
-            case 1:
-                return splitByNaNsOneSeries(dataset);
-            default: // two or more
-                return splitByNaNsTwoSeries(dataset);
+        case 0:
+            return Collections.<XYDataset>emptyList();
+        case 1:
+            return splitByNaNsOneSeries(dataset);
+        default: // two or more
+            return splitByNaNsTwoSeries(dataset);
         }
     }
 
-
     /**
      * Draws the visual representation of a single data item.
      *
-     * @param g2  the graphics device.
-     * @param state  the renderer state.
-     * @param dataArea  the area within which the data is being drawn.
-     * @param info  collects information about the drawing.
-     * @param plot  the plot (can be used to obtain standard color
-     *              information etc).
-     * @param domainAxis  the domain (horizontal) axis.
-     * @param rangeAxis  the range (vertical) axis.
-     * @param dataset  the dataset.
-     * @param series  the series index (zero-based).
-     * @param item  the item index (zero-based).
-     * @param crosshairState  crosshair information for the plot
-     *                        (<code>null</code> permitted).
-     * @param pass  the pass index.
+     * @param g2
+     *            the graphics device.
+     * @param state
+     *            the renderer state.
+     * @param dataArea
+     *            the area within which the data is being drawn.
+     * @param info
+     *            collects information about the drawing.
+     * @param plot
+     *            the plot (can be used to obtain standard color
+     *            information etc).
+     * @param domainAxis
+     *            the domain (horizontal) axis.
+     * @param rangeAxis
+     *            the range (vertical) axis.
+     * @param dataset
+     *            the dataset.
+     * @param series
+     *            the series index (zero-based).
+     * @param item
+     *            the item index (zero-based).
+     * @param crosshairState
+     *            crosshair information for the plot
+     *            (<code>null</code> permitted).
+     * @param pass
+     *            the pass index.
      */
-    public void drawItem(Graphics2D g2,
-                         XYItemRendererState state,
-                         Rectangle2D dataArea,
-                         PlotRenderingInfo info,
-                         XYPlot plot,
-                         ValueAxis domainAxis,
-                         ValueAxis rangeAxis,
-                         XYDataset dataset,
-                         int series,
-                         int item,
-                         CrosshairState crosshairState,
-                         int pass) {
+    @Override
+    public void drawItem(final Graphics2D g2, final XYItemRendererState state, final Rectangle2D dataArea, final PlotRenderingInfo info, final XYPlot plot,
+            final ValueAxis domainAxis, final ValueAxis rangeAxis, final XYDataset dataset, final int series, final int item,
+            final CrosshairState crosshairState, final int pass) {
+
         switch (pass) {
-            case 0:
-                for (XYDataset ds: splitByNaNs(dataset)) {
-                    drawItemPass0(g2, dataArea, info,
-                        plot, domainAxis, rangeAxis,
-                        ds, series, item, crosshairState);
-                }
-                break;
-            case 1:
-                drawItemPass1(g2, dataArea, info,
-                    plot, domainAxis, rangeAxis,
-                    dataset, series, item, crosshairState);
-        }
-
-        // Find geometric middle, calculate area and paint
-        // a string with it here.
-        if (pass == 1
-            && this.labelArea
-            && areaLabelNumberFormat != null
-            && areaLabelTamplate != null
-        ) {
-            double center_x = centroid.getX();
-            double center_y = centroid.getY();
-            center_x = domainAxis.valueToJava2D(center_x, dataArea,
-                plot.getDomainAxisEdge());
-            center_y = rangeAxis.valueToJava2D(center_y, dataArea,
-                plot.getRangeAxisEdge());
-
-            // Respect text-extend if text should appear really centered.
-
-            float area = 0f;
-            if (areaCalculationMode == CALCULATE_POSITIVE_AREA
-               || areaCalculationMode == CALCULATE_ALL_AREA) {
-                area += Math.abs(positiveArea);
+        case 0:
+            for (final XYDataset ds : splitByNaNs(dataset)) {
+                drawItemPass0(g2, dataArea, info, plot, domainAxis, rangeAxis, ds, series, item, crosshairState);
             }
-            if (areaCalculationMode == CALCULATE_NEGATIVE_AREA
-               || areaCalculationMode == CALCULATE_ALL_AREA) {
-                area += Math.abs(negativeArea);
-            }
-            if (area != 0f) {
-                Color oldColor = g2.getColor();
-                Font oldFont = g2.getFont();
-                g2.setFont(labelFont);
-                String labelText = String.format(this.areaLabelTamplate,
-                    areaLabelNumberFormat.format(area));
-                if (labelBGColor != null) {
-                    EnhancedLineAndShapeRenderer.drawTextBox(g2, labelText,
-                        (float)center_x, (float)center_y, labelBGColor);
-                }
-                g2.setColor(labelColor);
-                g2.drawString(labelText, (float)center_x, (float)center_y);
-                g2.setFont(oldFont);
-                g2.setColor(oldColor);
-            }
+            break;
+        case 1:
+            drawItemPass1(g2, dataArea, info, plot, domainAxis, rangeAxis, dataset, series, item, crosshairState);
+            break;
         }
     }
 
     /**
      * Draws the visual representation of a single data item, first pass.
      *
-     * @param x_graphics  the graphics device.
-     * @param x_dataArea  the area within which the data is being drawn.
-     * @param x_info  collects information about the drawing.
-     * @param x_plot  the plot (can be used to obtain standard color
-     *                information etc).
-     * @param x_domainAxis  the domain (horizontal) axis.
-     * @param x_rangeAxis  the range (vertical) axis.
-     * @param x_dataset  the dataset.
-     * @param x_series  the series index (zero-based).
-     * @param x_item  the item index (zero-based).
-     * @param x_crosshairState  crosshair information for the plot
-     *                          (<code>null</code> permitted).
+     * @param x_graphics
+     *            the graphics device.
+     * @param x_dataArea
+     *            the area within which the data is being drawn.
+     * @param x_info
+     *            collects information about the drawing.
+     * @param x_plot
+     *            the plot (can be used to obtain standard color
+     *            information etc).
+     * @param x_domainAxis
+     *            the domain (horizontal) axis.
+     * @param x_rangeAxis
+     *            the range (vertical) axis.
+     * @param x_dataset
+     *            the dataset.
+     * @param x_series
+     *            the series index (zero-based).
+     * @param x_item
+     *            the item index (zero-based).
+     * @param x_crosshairState
+     *            crosshair information for the plot
+     *            (<code>null</code> permitted).
      */
-    protected void drawItemPass0(Graphics2D x_graphics,
-                                 Rectangle2D x_dataArea,
-                                 PlotRenderingInfo x_info,
-                                 XYPlot x_plot,
-                                 ValueAxis x_domainAxis,
-                                 ValueAxis x_rangeAxis,
-                                 XYDataset x_dataset,
-                                 int x_series,
-                                 int x_item,
-                                 CrosshairState x_crosshairState) {
+    private void drawItemPass0(final Graphics2D x_graphics, final Rectangle2D x_dataArea, final PlotRenderingInfo x_info, final XYPlot x_plot,
+            final ValueAxis x_domainAxis, final ValueAxis x_rangeAxis, final XYDataset x_dataset, final int x_series, final int x_item,
+            final CrosshairState x_crosshairState) {
 
-        if (!((0 == x_series) && (0 == x_item))) {
+        if (x_series != 0 || x_item != 0)
             return;
-        }
 
-        boolean b_impliedZeroSubtrahend = (1 == x_dataset.getSeriesCount());
+        final boolean b_impliedZeroSubtrahend = (1 == x_dataset.getSeriesCount());
 
         // check if either series is a degenerate case (i.e. less than 2 points)
-        if (isEitherSeriesDegenerate(x_dataset, b_impliedZeroSubtrahend)) {
+        if (isEitherSeriesDegenerate(x_dataset, b_impliedZeroSubtrahend))
             return;
-        }
 
         // check if series are disjoint (i.e. domain-spans do not overlap)
-        if (!b_impliedZeroSubtrahend && areSeriesDisjoint(x_dataset)) {
+        if (!b_impliedZeroSubtrahend && areSeriesDisjoint(x_dataset))
             return;
-        }
 
         // polygon definitions
-        LinkedList l_minuendXs    = new LinkedList();
-        LinkedList l_minuendYs    = new LinkedList();
-        LinkedList l_subtrahendXs = new LinkedList();
-        LinkedList l_subtrahendYs = new LinkedList();
-        LinkedList l_polygonXs    = new LinkedList();
-        LinkedList l_polygonYs    = new LinkedList();
+        final List<Double> l_minuendXs = new LinkedList<>();
+        final List<Double> l_minuendYs = new LinkedList<>();
+        final List<Double> l_subtrahendXs = new LinkedList<>();
+        final List<Double> l_subtrahendYs = new LinkedList<>();
+        final List<Double> l_polygonXs = new LinkedList<>();
+        final List<Double> l_polygonYs = new LinkedList<>();
 
         // state
-        int l_minuendItem      = 0;
-        int l_minuendItemCount = x_dataset.getItemCount(0);
-        Double l_minuendCurX   = null;
-        Double l_minuendNextX  = null;
-        Double l_minuendCurY   = null;
-        Double l_minuendNextY  = null;
-        double l_minuendMaxY   = Double.NEGATIVE_INFINITY;
-        double l_minuendMinY   = Double.POSITIVE_INFINITY;
+        int l_minuendItem = 0;
+        final int l_minuendItemCount = x_dataset.getItemCount(0);
+        Double l_minuendCurX = null;
+        Double l_minuendNextX = null;
+        Double l_minuendCurY = null;
+        Double l_minuendNextY = null;
+        double l_minuendMaxY = Double.NEGATIVE_INFINITY;
+        double l_minuendMinY = Double.POSITIVE_INFINITY;
 
-        int l_subtrahendItem      = 0;
+        int l_subtrahendItem = 0;
         int l_subtrahendItemCount = 0; // actual value set below
-        Double l_subtrahendCurX   = null;
-        Double l_subtrahendNextX  = null;
-        Double l_subtrahendCurY   = null;
-        Double l_subtrahendNextY  = null;
-        double l_subtrahendMaxY   = Double.NEGATIVE_INFINITY;
-        double l_subtrahendMinY   = Double.POSITIVE_INFINITY;
+        Double l_subtrahendCurX = null;
+        Double l_subtrahendNextX = null;
+        Double l_subtrahendCurY = null;
+        Double l_subtrahendNextY = null;
+        double l_subtrahendMaxY = Double.NEGATIVE_INFINITY;
+        double l_subtrahendMinY = Double.POSITIVE_INFINITY;
 
         // if a subtrahend is not specified, assume it is zero
         if (b_impliedZeroSubtrahend) {
-            l_subtrahendItem      = 0;
+            l_subtrahendItem = 0;
             l_subtrahendItemCount = 2;
-            l_subtrahendCurX      = new Double(x_dataset.getXValue(0, 0));
-            l_subtrahendNextX     = new Double(x_dataset.getXValue(0,
-                    (l_minuendItemCount - 1)));
-            l_subtrahendCurY      = new Double(0.0);
-            l_subtrahendNextY     = new Double(0.0);
-            l_subtrahendMaxY      = 0.0;
-            l_subtrahendMinY      = 0.0;
+            l_subtrahendCurX = new Double(x_dataset.getXValue(0, 0));
+            l_subtrahendNextX = new Double(x_dataset.getXValue(0, (l_minuendItemCount - 1)));
+            l_subtrahendCurY = new Double(0.0);
+            l_subtrahendNextY = new Double(0.0);
+            l_subtrahendMaxY = 0.0;
+            l_subtrahendMinY = 0.0;
 
             l_subtrahendXs.add(l_subtrahendCurX);
             l_subtrahendYs.add(l_subtrahendCurY);
-        }
-        else {
+        } else {
             l_subtrahendItemCount = x_dataset.getItemCount(1);
         }
 
-        boolean b_minuendDone           = false;
-        boolean b_minuendAdvanced       = true;
-        boolean b_minuendAtIntersect    = false;
-        boolean b_minuendFastForward    = false;
-        boolean b_subtrahendDone        = false;
-        boolean b_subtrahendAdvanced    = true;
+        boolean b_minuendDone = false;
+        boolean b_minuendAdvanced = true;
+        boolean b_minuendAtIntersect = false;
+        boolean b_minuendFastForward = false;
+        boolean b_subtrahendDone = false;
+        boolean b_subtrahendAdvanced = true;
         boolean b_subtrahendAtIntersect = false;
         boolean b_subtrahendFastForward = false;
-        boolean b_colinear              = false;
+        boolean b_colinear = false;
 
         boolean b_positive;
 
@@ -1129,8 +953,8 @@
             l_x2 = x_dataset.getXValue(0, l_minuendItem + 1);
             l_y2 = x_dataset.getYValue(0, l_minuendItem + 1);
 
-            l_minuendCurX  = new Double(l_x1);
-            l_minuendCurY  = new Double(l_y1);
+            l_minuendCurX = new Double(l_x1);
+            l_minuendCurY = new Double(l_y1);
             l_minuendNextX = new Double(l_x2);
             l_minuendNextY = new Double(l_y2);
 
@@ -1139,15 +963,14 @@
                 l_y3 = l_subtrahendCurY.doubleValue();
                 l_x4 = l_subtrahendNextX.doubleValue();
                 l_y4 = l_subtrahendNextY.doubleValue();
-            }
-            else {
+            } else {
                 l_x3 = x_dataset.getXValue(1, l_subtrahendItem);
                 l_y3 = x_dataset.getYValue(1, l_subtrahendItem);
                 l_x4 = x_dataset.getXValue(1, l_subtrahendItem + 1);
                 l_y4 = x_dataset.getYValue(1, l_subtrahendItem + 1);
 
-                l_subtrahendCurX  = new Double(l_x3);
-                l_subtrahendCurY  = new Double(l_y3);
+                l_subtrahendCurX = new Double(l_x3);
+                l_subtrahendCurY = new Double(l_y3);
                 l_subtrahendNextX = new Double(l_x4);
                 l_subtrahendNextY = new Double(l_y4);
             }
@@ -1169,10 +992,9 @@
             // check if initial polygon needs to be clipped
             if ((l_x3 < l_x1) && (l_x1 < l_x4)) {
                 // project onto subtrahend
-                double l_slope   = (l_y4 - l_y3) / (l_x4 - l_x3);
+                final double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3);
                 l_subtrahendCurX = l_minuendCurX;
-                l_subtrahendCurY = new Double((l_slope * l_x1)
-                        + (l_y3 - (l_slope * l_x3)));
+                l_subtrahendCurY = new Double((l_slope * l_x1) + (l_y3 - (l_slope * l_x3)));
 
                 l_subtrahendXs.add(l_subtrahendCurX);
                 l_subtrahendYs.add(l_subtrahendCurY);
@@ -1180,17 +1002,16 @@
 
             if ((l_x1 < l_x3) && (l_x3 < l_x2)) {
                 // project onto minuend
-                double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1);
-                l_minuendCurX  = l_subtrahendCurX;
-                l_minuendCurY  = new Double((l_slope * l_x3)
-                        + (l_y1 - (l_slope * l_x1)));
+                final double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1);
+                l_minuendCurX = l_subtrahendCurX;
+                l_minuendCurY = new Double((l_slope * l_x3) + (l_y1 - (l_slope * l_x1)));
 
                 l_minuendXs.add(l_minuendCurX);
                 l_minuendYs.add(l_minuendCurY);
             }
 
-            l_minuendMaxY    = l_minuendCurY.doubleValue();
-            l_minuendMinY    = l_minuendCurY.doubleValue();
+            l_minuendMaxY = l_minuendCurY.doubleValue();
+            l_minuendMinY = l_minuendCurY.doubleValue();
             l_subtrahendMaxY = l_subtrahendCurY.doubleValue();
             l_subtrahendMinY = l_subtrahendCurY.doubleValue();
 
@@ -1220,8 +1041,7 @@
             }
 
             // never updated the subtrahend if it is implied to be zero
-            if (!b_impliedZeroSubtrahend && !b_subtrahendDone
-                    && !b_subtrahendFastForward && b_subtrahendAdvanced) {
+            if (!b_impliedZeroSubtrahend && !b_subtrahendDone && !b_subtrahendFastForward && b_subtrahendAdvanced) {
                 l_x3 = x_dataset.getXValue(1, l_subtrahendItem);
                 l_y3 = x_dataset.getYValue(1, l_subtrahendItem);
                 l_subtrahendCurX = new Double(l_x3);
@@ -1242,14 +1062,14 @@
             }
 
             // deassert b_*FastForward (only matters for 1st time through loop)
-            b_minuendFastForward    = false;
+            b_minuendFastForward = false;
             b_subtrahendFastForward = false;
 
             Double l_intersectX = null;
             Double l_intersectY = null;
             boolean b_intersect = false;
 
-            b_minuendAtIntersect    = false;
+            b_minuendAtIntersect = false;
             b_subtrahendAtIntersect = false;
 
             // check for intersect
@@ -1257,39 +1077,32 @@
                 // check if line segments are colinear
                 if ((l_x1 == l_x3) && (l_y1 == l_y3)) {
                     b_colinear = true;
-                }
-                else {
+                } else {
                     // the intersect is at the next point for both the minuend
                     // and subtrahend
                     l_intersectX = new Double(l_x2);
                     l_intersectY = new Double(l_y2);
 
-                    b_intersect             = true;
-                    b_minuendAtIntersect    = true;
+                    b_intersect = true;
+                    b_minuendAtIntersect = true;
                     b_subtrahendAtIntersect = true;
-                 }
-            }
-            else {
+                }
+            } else {
                 // compute common denominator
-                double l_denominator = ((l_y4 - l_y3) * (l_x2 - l_x1))
-                        - ((l_x4 - l_x3) * (l_y2 - l_y1));
+                final double l_denominator = ((l_y4 - l_y3) * (l_x2 - l_x1)) - ((l_x4 - l_x3) * (l_y2 - l_y1));
 
                 // compute common deltas
-                double l_deltaY = l_y1 - l_y3;
-                double l_deltaX = l_x1 - l_x3;
+                final double l_deltaY = l_y1 - l_y3;
+                final double l_deltaX = l_x1 - l_x3;
 
                 // compute numerators
-                double l_numeratorA = ((l_x4 - l_x3) * l_deltaY)
-                        - ((l_y4 - l_y3) * l_deltaX);
-                double l_numeratorB = ((l_x2 - l_x1) * l_deltaY)
-                        - ((l_y2 - l_y1) * l_deltaX);
+                final double l_numeratorA = ((l_x4 - l_x3) * l_deltaY) - ((l_y4 - l_y3) * l_deltaX);
+                final double l_numeratorB = ((l_x2 - l_x1) * l_deltaY) - ((l_y2 - l_y1) * l_deltaX);
 
                 // check if line segments are colinear
-                if ((0 == l_numeratorA) && (0 == l_numeratorB)
-                        && (0 == l_denominator)) {
+                if ((0 == l_numeratorA) && (0 == l_numeratorB) && (0 == l_denominator)) {
                     b_colinear = true;
-                }
-                else {
+                } else {
                     // check if previously colinear
                     if (b_colinear) {
                         // clear colinear points and flag
@@ -1303,36 +1116,30 @@
                         b_colinear = false;
 
                         // set new starting point for the polygon
-                        boolean b_useMinuend = ((l_x3 <= l_x1)
-                                && (l_x1 <= l_x4));
-                        l_polygonXs.add(b_useMinuend ? l_minuendCurX
-                                : l_subtrahendCurX);
-                        l_polygonYs.add(b_useMinuend ? l_minuendCurY
-                                : l_subtrahendCurY);
+                        final boolean b_useMinuend = ((l_x3 <= l_x1) && (l_x1 <= l_x4));
+                        l_polygonXs.add(b_useMinuend ? l_minuendCurX : l_subtrahendCurX);
+                        l_polygonYs.add(b_useMinuend ? l_minuendCurY : l_subtrahendCurY);
                     }
 
                     // compute slope components
-                    double l_slopeA = l_numeratorA / l_denominator;
-                    double l_slopeB = l_numeratorB / l_denominator;
+                    final double l_slopeA = l_numeratorA / l_denominator;
+                    final double l_slopeB = l_numeratorB / l_denominator;
 
                     // check if the line segments intersect
-                    if ((0 < l_slopeA) && (l_slopeA <= 1) && (0 < l_slopeB)
-                            && (l_slopeB <= 1)) {
+                    if ((0 < l_slopeA) && (l_slopeA <= 1) && (0 < l_slopeB) && (l_slopeB <= 1)) {
                         // compute the point of intersection
-                        double l_xi = l_x1 + (l_slopeA * (l_x2 - l_x1));
-                        double l_yi = l_y1 + (l_slopeA * (l_y2 - l_y1));
+                        final double l_xi = l_x1 + (l_slopeA * (l_x2 - l_x1));
+                        final double l_yi = l_y1 + (l_slopeA * (l_y2 - l_y1));
 
-                        l_intersectX            = new Double(l_xi);
-                        l_intersectY            = new Double(l_yi);
-                        b_intersect             = true;
-                        b_minuendAtIntersect    = ((l_xi == l_x2)
-                                && (l_yi == l_y2));
-                        b_subtrahendAtIntersect = ((l_xi == l_x4)
-                                && (l_yi == l_y4));
+                        l_intersectX = new Double(l_xi);
+                        l_intersectY = new Double(l_yi);
+                        b_intersect = true;
+                        b_minuendAtIntersect = ((l_xi == l_x2) && (l_yi == l_y2));
+                        b_subtrahendAtIntersect = ((l_xi == l_x4) && (l_yi == l_y4));
 
                         // advance minuend and subtrahend to intesect
-                        l_minuendCurX    = l_intersectX;
-                        l_minuendCurY    = l_intersectY;
+                        l_minuendCurX = l_intersectX;
+                        l_minuendCurY = l_intersectY;
                         l_subtrahendCurX = l_intersectX;
                         l_subtrahendCurY = l_intersectY;
                     }
@@ -1356,10 +1163,8 @@
                 l_polygonYs.addAll(l_subtrahendYs);
 
                 // create an actual polygon
-                b_positive = (l_subtrahendMaxY <= l_minuendMaxY)
-                        && (l_subtrahendMinY <= l_minuendMinY);
-                createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis,
-                        x_rangeAxis, b_positive, l_polygonXs, l_polygonYs);
+                b_positive = (l_subtrahendMaxY <= l_minuendMaxY) && (l_subtrahendMinY <= l_minuendMinY);
+                createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis, x_rangeAxis, b_positive, l_polygonXs, l_polygonYs);
 
                 // clear the point vectors
                 l_minuendXs.clear();
@@ -1370,10 +1175,10 @@
                 l_polygonYs.clear();
 
                 // set the maxY and minY values to intersect y-value
-                double l_y       = l_intersectY.doubleValue();
-                l_minuendMaxY    = l_y;
+                final double l_y = l_intersectY.doubleValue();
+                l_minuendMaxY = l_y;
                 l_subtrahendMaxY = l_y;
-                l_minuendMinY    = l_y;
+                l_minuendMinY = l_y;
                 l_subtrahendMinY = l_y;
 
                 // add interection point to new polygon
@@ -1385,8 +1190,7 @@
             if (l_x2 <= l_x4) {
                 l_minuendItem++;
                 b_minuendAdvanced = true;
-            }
-            else {
+            } else {
                 b_minuendAdvanced = false;
             }
 
@@ -1394,43 +1198,35 @@
             if (l_x4 <= l_x2) {
                 l_subtrahendItem++;
                 b_subtrahendAdvanced = true;
-            }
-            else {
+            } else {
                 b_subtrahendAdvanced = false;
             }
 
-            b_minuendDone    = (l_minuendItem == (l_minuendItemCount - 1));
-            b_subtrahendDone = (l_subtrahendItem == (l_subtrahendItemCount
-                    - 1));
+            b_minuendDone = (l_minuendItem == (l_minuendItemCount - 1));
+            b_subtrahendDone = (l_subtrahendItem == (l_subtrahendItemCount - 1));
         }
 
         // check if the final polygon needs to be clipped
         if (b_minuendDone && (l_x3 < l_x2) && (l_x2 < l_x4)) {
             // project onto subtrahend
-            double l_slope    = (l_y4 - l_y3) / (l_x4 - l_x3);
+            final double l_slope = (l_y4 - l_y3) / (l_x4 - l_x3);
             l_subtrahendNextX = l_minuendNextX;
-            l_subtrahendNextY = new Double((l_slope * l_x2)
-                    + (l_y3 - (l_slope * l_x3)));
+            l_subtrahendNextY = new Double((l_slope * l_x2) + (l_y3 - (l_slope * l_x3)));
         }
 
         if (b_subtrahendDone && (l_x1 < l_x4) && (l_x4 < l_x2)) {
             // project onto minuend
-            double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1);
+            final double l_slope = (l_y2 - l_y1) / (l_x2 - l_x1);
             l_minuendNextX = l_subtrahendNextX;
-            l_minuendNextY = new Double((l_slope * l_x4)
-                    + (l_y1 - (l_slope * l_x1)));
+            l_minuendNextY = new Double((l_slope * l_x4) + (l_y1 - (l_slope * l_x1)));
         }
 
         // consider last point of minuend and subtrahend for determining
         // positivity
-        l_minuendMaxY    = Math.max(l_minuendMaxY,
-                l_minuendNextY.doubleValue());
-        l_subtrahendMaxY = Math.max(l_subtrahendMaxY,
-                l_subtrahendNextY.doubleValue());
-        l_minuendMinY    = Math.min(l_minuendMinY,
-                l_minuendNextY.doubleValue());
-        l_subtrahendMinY = Math.min(l_subtrahendMinY,
-                l_subtrahendNextY.doubleValue());
+        l_minuendMaxY = Math.max(l_minuendMaxY, l_minuendNextY.doubleValue());
+        l_subtrahendMaxY = Math.max(l_subtrahendMaxY, l_subtrahendNextY.doubleValue());
+        l_minuendMinY = Math.min(l_minuendMinY, l_minuendNextY.doubleValue());
+        l_subtrahendMinY = Math.min(l_subtrahendMinY, l_subtrahendNextY.doubleValue());
 
         // add the last point of the minuned and subtrahend
         l_minuendXs.add(l_minuendNextX);
@@ -1450,144 +1246,195 @@
         l_polygonYs.addAll(l_subtrahendYs);
 
         // create an actual polygon
-        b_positive = (l_subtrahendMaxY <= l_minuendMaxY)
-                && (l_subtrahendMinY <= l_minuendMinY);
-        createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis,
-                x_rangeAxis, b_positive, l_polygonXs, l_polygonYs);
+        b_positive = (l_subtrahendMaxY <= l_minuendMaxY) && (l_subtrahendMinY <= l_minuendMinY);
+        createPolygon(x_graphics, x_dataArea, x_plot, x_domainAxis, x_rangeAxis, b_positive, l_polygonXs, l_polygonYs);
+    }
+
+    private void drawItemPass1(final Graphics2D g2, final Rectangle2D dataArea, final PlotRenderingInfo info, final XYPlot plot, final ValueAxis domainAxis,
+            final ValueAxis rangeAxis, final XYDataset dataset, final int series, final int item, final CrosshairState crosshairState) {
+
+        doDrawItemPass1(g2, dataArea, info, plot, domainAxis, rangeAxis, dataset, series, item, crosshairState);
+
+        final int lastSeries = dataset.getSeriesCount() - 1;
+        final int lastItem = dataset.getItemCount(series) - 1;
+        if (series == lastSeries && item == lastItem) {
+            // draw labels: only once per theme!
+            drawAreaLabel(g2, dataArea, plot, domainAxis, rangeAxis);
+            drawTitleLabel(g2, dataArea, info.getOwner().getEntityCollection(), dataset);
+        }
+    }
+
+    private void drawAreaLabel(final Graphics2D g2, final Rectangle2D dataArea, final XYPlot plot, final ValueAxis domainAxis, final ValueAxis rangeAxis) {
+
+        if (!this.drawAreaLabel)
+            return;
+
+        if (this.areaLabelNumberFormat == null || this.areaLabelTamplate == null || this.centroid == null)
+            return;
+
+        // Respect text-extend if text should appear really centered.
+        float area = 0f;
+        if (this.areaCalculationMode == CALCULATE_POSITIVE_AREA || this.areaCalculationMode == CALCULATE_ALL_AREA)
+            area += Math.abs(this.positiveArea);
+        if (this.areaCalculationMode == CALCULATE_NEGATIVE_AREA || this.areaCalculationMode == CALCULATE_ALL_AREA)
+            area += Math.abs(this.negativeArea);
+
+        if (area != 0f) {
+
+            final String labelText = String.format(this.areaLabelTamplate, this.areaLabelNumberFormat.format(area));
+
+            final double center_x = this.centroid.getX();
+            final double center_y = this.centroid.getY();
+
+            final double screenX = domainAxis.valueToJava2D(center_x, dataArea, plot.getDomainAxisEdge());
+            final double screenY = rangeAxis.valueToJava2D(center_y, dataArea, plot.getRangeAxisEdge());
+
+            drawLabel(g2, labelText, screenX, screenY);
+        }
+    }
+
+    private void drawTitleLabel(final Graphics2D g2, final Rectangle2D dataArea, final EntityCollection entities, final XYDataset dataset) {
+
+        if (!this.drawTitleLabel)
+            return;
+
+        if (Double.isInfinite(this.minimumScreenX))
+            return;
+
+        if (dataset instanceof XYSeriesCollection) {
+            final XYSeries xYSeries = ((XYSeriesCollection) dataset).getSeries(0);
+            final String label = (xYSeries instanceof HasLabel) ? ((HasLabel) xYSeries).getLabel() : xYSeries.getKey().toString();
+
+            EnhancedLineAndShapeRenderer.drawLineLabel(g2, dataArea, entities, this.minimumScreenX, this.minimumScreenX_Y, this.labelFont, this.labelColor,
+                    this.labelBGColor != null, this.labelBGColor, label);
+        }
     }
 
     /**
-     * Draws the visual representation of a single data item, second pass.  In
+     * Draws the visual representation of a single data item, second pass. In
      * the second pass, the renderer draws the lines and shapes for the
      * individual points in the two series.
      *
-     * @param x_graphics  the graphics device.
-     * @param x_dataArea  the area within which the data is being drawn.
-     * @param x_info  collects information about the drawing.
-     * @param x_plot  the plot (can be used to obtain standard color
-     *         information etc).
-     * @param x_domainAxis  the domain (horizontal) axis.
-     * @param x_rangeAxis  the range (vertical) axis.
-     * @param x_dataset  the dataset.
-     * @param x_series  the series index (zero-based).
-     * @param x_item  the item index (zero-based).
-     * @param x_crosshairState  crosshair information for the plot
-     *                          (<code>null</code> permitted).
+     * @param x_graphics
+     *            the graphics device.
+     * @param x_dataArea
+     *            the area within which the data is being drawn.
+     * @param x_info
+     *            collects information about the drawing.
+     * @param x_plot
+     *            the plot (can be used to obtain standard color
+     *            information etc).
+     * @param x_domainAxis
+     *            the domain (horizontal) axis.
+     * @param x_rangeAxis
+     *            the range (vertical) axis.
+     * @param x_dataset
+     *            the dataset.
+     * @param x_series
+     *            the series index (zero-based).
+     * @param x_item
+     *            the item index (zero-based).
+     * @param x_crosshairState
+     *            crosshair information for the plot
+     *            (<code>null</code> permitted).
      */
-    protected void drawItemPass1(Graphics2D x_graphics,
-                                 Rectangle2D x_dataArea,
-                                 PlotRenderingInfo x_info,
-                                 XYPlot x_plot,
-                                 ValueAxis x_domainAxis,
-                                 ValueAxis x_rangeAxis,
-                                 XYDataset x_dataset,
-                                 int x_series,
-                                 int x_item,
-                                 CrosshairState x_crosshairState) {
+    private void doDrawItemPass1(final Graphics2D x_graphics, final Rectangle2D x_dataArea, final PlotRenderingInfo x_info, final XYPlot x_plot,
+            final ValueAxis x_domainAxis, final ValueAxis x_rangeAxis, final XYDataset x_dataset, final int x_series, final int x_item,
+            final CrosshairState x_crosshairState) {
 
         Shape l_entityArea = null;
         EntityCollection l_entities = null;
-        if (null != x_info) {
+        if (x_info != null)
             l_entities = x_info.getOwner().getEntityCollection();
-        }
 
-        Paint l_seriesPaint   = getItemPaint(x_series, x_item);
-        Stroke l_seriesStroke = getItemStroke(x_series, x_item);
+        final Paint l_seriesPaint = getItemPaint(x_series, x_item);
+        final Stroke l_seriesStroke = getItemStroke(x_series, x_item);
         x_graphics.setPaint(l_seriesPaint);
         x_graphics.setStroke(l_seriesStroke);
 
-        PlotOrientation l_orientation      = x_plot.getOrientation();
-        RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge();
-        RectangleEdge l_rangeAxisLocation  = x_plot.getRangeAxisEdge();
+        final PlotOrientation l_orientation = x_plot.getOrientation();
+        final RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge();
+        final RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge();
 
-        double l_x0 = x_dataset.getXValue(x_series, x_item);
-        double l_y0 = x_dataset.getYValue(x_series, x_item);
-        double l_x1 = x_domainAxis.valueToJava2D(l_x0, x_dataArea,
-                l_domainAxisLocation);
-        double l_y1 = x_rangeAxis.valueToJava2D(l_y0, x_dataArea,
-                l_rangeAxisLocation);
+        final double l_x0 = x_dataset.getXValue(x_series, x_item);
+        final double l_y0 = x_dataset.getYValue(x_series, x_item);
+        final double l_x1 = x_domainAxis.valueToJava2D(l_x0, x_dataArea, l_domainAxisLocation);
+        final double l_y1 = x_rangeAxis.valueToJava2D(l_y0, x_dataArea, l_rangeAxisLocation);
+
+        /* update minimumScreenX -> used to position title */
+        // REMARK: ignore points with y == 0.0 --> else the label sticks on the zero-line, becaue most area themes start at 0.0
+        if (l_x1 < this.minimumScreenX && Math.abs(l_y1) > 0.01) {
+            this.minimumScreenX = l_x1;
+            this.minimumScreenX_Y = l_y1;
+        }
 
         // These are the shapes of the series items.
         if (getShapesVisible()) {
             Shape l_shape = getItemShape(x_series, x_item);
             if (l_orientation == PlotOrientation.HORIZONTAL) {
-                l_shape = ShapeUtilities.createTranslatedShape(l_shape,
-                        l_y1, l_x1);
-            }
-            else {
-                l_shape = ShapeUtilities.createTranslatedShape(l_shape,
-                        l_x1, l_y1);
+                l_shape = ShapeUtilities.createTranslatedShape(l_shape, l_y1, l_x1);
+            } else {
+                l_shape = ShapeUtilities.createTranslatedShape(l_shape, l_x1, l_y1);
             }
             if (l_shape.intersects(x_dataArea)) {
                 x_graphics.setPaint(getItemPaint(x_series, x_item));
                 x_graphics.fill(l_shape);
-                /* TODO We could draw the shapes of single items here.
-                if (drawOutline) {
-                    x_graphics.setPaint(this.outlinePaint);
-                    x_graphics.setStroke(this.outlineStroke);
-                    x_graphics.draw(l_shape);
-                }
-                */
+                /*
+                 * TODO We could draw the shapes of single items here.
+                 * if (drawOutline) {
+                 * x_graphics.setPaint(this.outlinePaint);
+                 * x_graphics.setStroke(this.outlineStroke);
+                 * x_graphics.draw(l_shape);
+                 * }
+                 */
             }
             l_entityArea = l_shape;
         } // if (getShapesVisible())
 
         // add an entity for the item...
-        if (null != l_entities) {
-            if (null == l_entityArea) {
-                l_entityArea = new Rectangle2D.Double((l_x1 - 2), (l_y1 - 2),
-                        4, 4);
-            }
+        if (l_entities != null) {
+            if (l_entityArea == null)
+                l_entityArea = new Rectangle2D.Double((l_x1 - 2), (l_y1 - 2), 4, 4);
+
             String l_tip = null;
-            XYToolTipGenerator l_tipGenerator = getToolTipGenerator(x_series,
-                    x_item);
+            final XYToolTipGenerator l_tipGenerator = getToolTipGenerator(x_series, x_item);
             if (null != l_tipGenerator) {
-                l_tip = l_tipGenerator.generateToolTip(x_dataset, x_series,
-                        x_item);
+                l_tip = l_tipGenerator.generateToolTip(x_dataset, x_series, x_item);
             }
             String l_url = null;
-            XYURLGenerator l_urlGenerator = getURLGenerator();
+            final XYURLGenerator l_urlGenerator = getURLGenerator();
             if (null != l_urlGenerator) {
-                l_url = l_urlGenerator.generateURL(x_dataset, x_series,
-                        x_item);
+                l_url = l_urlGenerator.generateURL(x_dataset, x_series, x_item);
             }
-            XYItemEntity l_entity = new XYItemEntity(l_entityArea, x_dataset,
-                    x_series, x_item, l_tip, l_url);
+            final XYItemEntity l_entity = new XYItemEntity(l_entityArea, x_dataset, x_series, x_item, l_tip, l_url);
             l_entities.add(l_entity);
         }
 
         // draw the item label if there is one...
-        if (isItemLabelVisible(x_series, x_item)) {
-            drawItemLabel(x_graphics, l_orientation, x_dataset, x_series,
-                          x_item, l_x1, l_y1, (l_y1 < 0.0));
-        }
+        if (isItemLabelVisible(x_series, x_item))
+            drawItemLabel(x_graphics, l_orientation, x_dataset, x_series, x_item, l_x1, l_y1, (l_y1 < 0.0));
 
-        int l_domainAxisIndex = x_plot.getDomainAxisIndex(x_domainAxis);
-        int l_rangeAxisIndex  = x_plot.getRangeAxisIndex(x_rangeAxis);
-        updateCrosshairValues(x_crosshairState, l_x0, l_y0, l_domainAxisIndex,
-                              l_rangeAxisIndex, l_x1, l_y1, l_orientation);
+        final int l_domainAxisIndex = x_plot.getDomainAxisIndex(x_domainAxis);
+        final int l_rangeAxisIndex = x_plot.getRangeAxisIndex(x_rangeAxis);
+        updateCrosshairValues(x_crosshairState, l_x0, l_y0, l_domainAxisIndex, l_rangeAxisIndex, l_x1, l_y1, l_orientation);
 
         if (0 == x_item) {
             return;
         }
 
-        double l_x2 = x_domainAxis.valueToJava2D(x_dataset.getXValue(x_series,
-                (x_item - 1)), x_dataArea, l_domainAxisLocation);
-        double l_y2 = x_rangeAxis.valueToJava2D(x_dataset.getYValue(x_series,
-                (x_item - 1)), x_dataArea, l_rangeAxisLocation);
+        final double l_x2 = x_domainAxis.valueToJava2D(x_dataset.getXValue(x_series, (x_item - 1)), x_dataArea, l_domainAxisLocation);
+        final double l_y2 = x_rangeAxis.valueToJava2D(x_dataset.getYValue(x_series, (x_item - 1)), x_dataArea, l_rangeAxisLocation);
 
         Line2D l_line = null;
-        if (PlotOrientation.HORIZONTAL == l_orientation) {
+        if (PlotOrientation.HORIZONTAL == l_orientation)
             l_line = new Line2D.Double(l_y1, l_x1, l_y2, l_x2);
-        }
-        else if (PlotOrientation.VERTICAL == l_orientation) {
+        else if (PlotOrientation.VERTICAL == l_orientation)
             l_line = new Line2D.Double(l_x1, l_y1, l_x2, l_y2);
-        }
 
         if ((null != l_line) && l_line.intersects(x_dataArea)) {
             x_graphics.setPaint(getItemPaint(x_series, x_item));
             x_graphics.setStroke(getItemStroke(x_series, x_item));
-            if (drawOriginalSeries) {
+            if (this.drawOriginalSeries) {
                 x_graphics.setPaint(this.outlinePaint);
                 x_graphics.setStroke(this.outlineStroke);
                 x_graphics.draw(l_line);
@@ -1596,188 +1443,175 @@
     }
 
     /**
-     * Determines if a dataset is degenerate.  A degenerate dataset is a
+     * Determines if a dataset is degenerate. A degenerate dataset is a
      * dataset where either series has less than two (2) points.
      *
-     * @param x_dataset  the dataset.
-     * @param x_impliedZeroSubtrahend  if false, do not check the subtrahend
+     * @param x_dataset
+     *            the dataset.
+     * @param x_impliedZeroSubtrahend
+     *            if false, do not check the subtrahend
      *
      * @return true if the dataset is degenerate.
      */
-    private boolean isEitherSeriesDegenerate(XYDataset x_dataset,
-            boolean x_impliedZeroSubtrahend) {
+    private boolean isEitherSeriesDegenerate(final XYDataset x_dataset, final boolean x_impliedZeroSubtrahend) {
 
         if (x_impliedZeroSubtrahend) {
             return (x_dataset.getItemCount(0) < 2);
         }
 
-        return ((x_dataset.getItemCount(0) < 2)
-                || (x_dataset.getItemCount(1) < 2));
+        return ((x_dataset.getItemCount(0) < 2) || (x_dataset.getItemCount(1) < 2));
     }
 
     /**
      * Determines if the two (2) series are disjoint.
      * Disjoint series do not overlap in the domain space.
      *
-     * @param x_dataset  the dataset.
+     * @param x_dataset
+     *            the dataset.
      *
      * @return true if the dataset is degenerate.
      */
-    private boolean areSeriesDisjoint(XYDataset x_dataset) {
-
-        int l_minuendItemCount = x_dataset.getItemCount(0);
-        double l_minuendFirst  = x_dataset.getXValue(0, 0);
-        double l_minuendLast   = x_dataset.getXValue(0, l_minuendItemCount - 1);
+    private boolean areSeriesDisjoint(final XYDataset x_dataset) {
 
-        int l_subtrahendItemCount = x_dataset.getItemCount(1);
-        double l_subtrahendFirst  = x_dataset.getXValue(1, 0);
-        double l_subtrahendLast   = x_dataset.getXValue(1,
-                l_subtrahendItemCount - 1);
+        final int l_minuendItemCount = x_dataset.getItemCount(0);
+        final double l_minuendFirst = x_dataset.getXValue(0, 0);
+        final double l_minuendLast = x_dataset.getXValue(0, l_minuendItemCount - 1);
 
-        return ((l_minuendLast < l_subtrahendFirst)
-                || (l_subtrahendLast < l_minuendFirst));
+        final int l_subtrahendItemCount = x_dataset.getItemCount(1);
+        final double l_subtrahendFirst = x_dataset.getXValue(1, 0);
+        final double l_subtrahendLast = x_dataset.getXValue(1, l_subtrahendItemCount - 1);
+
+        return ((l_minuendLast < l_subtrahendFirst) || (l_subtrahendLast < l_minuendFirst));
     }
 
-
-    public void updateCentroid(Object [] xValues, Object [] yValues) {
+    private void updateCentroid(final Object[] xValues, final Object[] yValues) {
         double x = 0d, y = 0d;
 
         for (int i = 0, N = xValues.length; i < N; ++i) {
-            x += ((Double)xValues[i]).doubleValue();
-            y += ((Double)yValues[i]).doubleValue();
+            x += ((Double) xValues[i]).doubleValue();
+            y += ((Double) yValues[i]).doubleValue();
         }
 
         x /= xValues.length;
         y /= yValues.length;
 
-        centroidNPoints++;
-        double factorNew = 1d / centroidNPoints;
-        double factorOld = 1d - factorNew;
+        this.centroidNPoints++;
+        final double factorNew = 1d / this.centroidNPoints;
+        final double factorOld = 1d - factorNew;
 
-        centroid = new Point2D.Double((factorNew * x + factorOld * centroid.x),
-            (factorNew * y + factorOld * centroid.y));
+        this.centroid = new Point2D.Double((factorNew * x + factorOld * this.centroid.x), (factorNew * y + factorOld * this.centroid.y));
     }
 
-
-    public static double calculateArea(Object [] xValues, Object [] yValues) {
+    private static double calculateArea(final Object[] xValues, final Object[] yValues) {
         double area = 0d;
 
         for (int i = 0, N = xValues.length; i < N; ++i) {
-            int k = (i + 1) % N;
-            double xi = ((Double)xValues[i]).doubleValue();
-            double yi = ((Double)yValues[i]).doubleValue();
-            double xk = ((Double)xValues[k]).doubleValue();
-            double yk = ((Double)yValues[k]).doubleValue();
+            final int k = (i + 1) % N;
+            final double xi = ((Double) xValues[i]).doubleValue();
+            final double yi = ((Double) yValues[i]).doubleValue();
+            final double xk = ((Double) xValues[k]).doubleValue();
+            final double yk = ((Double) yValues[k]).doubleValue();
 
-            area += xi*yk;
-            area -= xk*yi;
+            area += xi * yk;
+            area -= xk * yi;
             // TODO centroid calculation here?
         }
 
-        return 0.5d*area;
+        return 0.5d * area;
     }
 
     /**
      * Draws the visual representation of a polygon
      *
-     * @param x_graphics  the graphics device.
-     * @param x_dataArea  the area within which the data is being drawn.
-     * @param x_plot  the plot (can be used to obtain standard color
-     *                information etc).
-     * @param x_domainAxis  the domain (horizontal) axis.
-     * @param x_rangeAxis  the range (vertical) axis.
-     * @param x_positive  indicates if the polygon is positive (true) or
-     *                    negative (false).
-     * @param x_xValues  a linked list of the x values (expects values to be
-     *                   of type Double).
-     * @param x_yValues  a linked list of the y values (expects values to be
-     *                   of type Double).
+     * @param x_graphics
+     *            the graphics device.
+     * @param x_dataArea
+     *            the area within which the data is being drawn.
+     * @param x_plot
+     *            the plot (can be used to obtain standard color
+     *            information etc).
+     * @param x_domainAxis
+     *            the domain (horizontal) axis.
+     * @param x_rangeAxis
+     *            the range (vertical) axis.
+     * @param x_positive
+     *            indicates if the polygon is positive (true) or
+     *            negative (false).
+     * @param x_xValues
+     *            a linked list of the x values (expects values to be
+     *            of type Double).
+     * @param x_yValues
+     *            a linked list of the y values (expects values to be
+     *            of type Double).
      */
-    private void createPolygon (Graphics2D x_graphics,
-                                Rectangle2D x_dataArea,
-                                XYPlot      x_plot,
-                                ValueAxis   x_domainAxis,
-                                ValueAxis   x_rangeAxis,
-                                boolean     x_positive,
-                                LinkedList  x_xValues,
-                                LinkedList  x_yValues) {
+    private void createPolygon(final Graphics2D x_graphics, final Rectangle2D x_dataArea, final XYPlot x_plot, final ValueAxis x_domainAxis,
+            final ValueAxis x_rangeAxis, final boolean x_positive, final List<Double> x_xValues, final List<Double> x_yValues) {
 
-        PlotOrientation l_orientation      = x_plot.getOrientation();
-        RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge();
-        RectangleEdge l_rangeAxisLocation  = x_plot.getRangeAxisEdge();
+        final PlotOrientation l_orientation = x_plot.getOrientation();
+        final RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge();
+        final RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge();
 
-        Object[] l_xValues = x_xValues.toArray();
-        Object[] l_yValues = x_yValues.toArray();
+        final Object[] l_xValues = x_xValues.toArray();
+        final Object[] l_yValues = x_yValues.toArray();
 
-        double area = calculateArea(l_xValues, l_yValues);
-        if (x_positive) positiveArea += area;
-        else            negativeArea += area;
+        final double area = calculateArea(l_xValues, l_yValues);
+        if (x_positive)
+            this.positiveArea += area;
+        else
+            this.negativeArea += area;
         updateCentroid(l_xValues, l_yValues);
 
-        GeneralPath l_path = new GeneralPath();
+        final GeneralPath l_path = new GeneralPath();
 
         if (PlotOrientation.VERTICAL == l_orientation) {
-            double l_x = x_domainAxis.valueToJava2D((
-                    (Double) l_xValues[0]).doubleValue(), x_dataArea,
-                    l_domainAxisLocation);
+            double l_x = x_domainAxis.valueToJava2D(((Double) l_xValues[0]).doubleValue(), x_dataArea, l_domainAxisLocation);
             if (this.roundXCoordinates) {
                 l_x = Math.rint(l_x);
             }
 
-            double l_y = x_rangeAxis.valueToJava2D((
-                    (Double) l_yValues[0]).doubleValue(), x_dataArea,
-                    l_rangeAxisLocation);
+            double l_y = x_rangeAxis.valueToJava2D(((Double) l_yValues[0]).doubleValue(), x_dataArea, l_rangeAxisLocation);
 
             l_path.moveTo((float) l_x, (float) l_y);
             for (int i = 1; i < l_xValues.length; i++) {
-                l_x = x_domainAxis.valueToJava2D((
-                        (Double) l_xValues[i]).doubleValue(), x_dataArea,
-                        l_domainAxisLocation);
+                l_x = x_domainAxis.valueToJava2D(((Double) l_xValues[i]).doubleValue(), x_dataArea, l_domainAxisLocation);
                 if (this.roundXCoordinates) {
                     l_x = Math.rint(l_x);
                 }
 
-                l_y = x_rangeAxis.valueToJava2D((
-                        (Double) l_yValues[i]).doubleValue(), x_dataArea,
-                        l_rangeAxisLocation);
+                l_y = x_rangeAxis.valueToJava2D(((Double) l_yValues[i]).doubleValue(), x_dataArea, l_rangeAxisLocation);
                 l_path.lineTo((float) l_x, (float) l_y);
             }
             l_path.closePath();
-        }
-        else {
-            double l_x = x_domainAxis.valueToJava2D((
-                    (Double) l_xValues[0]).doubleValue(), x_dataArea,
-                    l_domainAxisLocation);
+        } else {
+            double l_x = x_domainAxis.valueToJava2D(((Double) l_xValues[0]).doubleValue(), x_dataArea, l_domainAxisLocation);
             if (this.roundXCoordinates) {
                 l_x = Math.rint(l_x);
             }
 
-            double l_y = x_rangeAxis.valueToJava2D((
-                    (Double) l_yValues[0]).doubleValue(), x_dataArea,
-                    l_rangeAxisLocation);
+            double l_y = x_rangeAxis.valueToJava2D(((Double) l_yValues[0]).doubleValue(), x_dataArea, l_rangeAxisLocation);
 
             l_path.moveTo((float) l_y, (float) l_x);
             for (int i = 1; i < l_xValues.length; i++) {
-                l_x = x_domainAxis.valueToJava2D((
-                        (Double) l_xValues[i]).doubleValue(), x_dataArea,
-                        l_domainAxisLocation);
+                l_x = x_domainAxis.valueToJava2D(((Double) l_xValues[i]).doubleValue(), x_dataArea, l_domainAxisLocation);
                 if (this.roundXCoordinates) {
                     l_x = Math.rint(l_x);
                 }
 
-                l_y = x_rangeAxis.valueToJava2D((
-                        (Double) l_yValues[i]).doubleValue(), x_dataArea,
-                        l_rangeAxisLocation);
+                l_y = x_rangeAxis.valueToJava2D(((Double) l_yValues[i]).doubleValue(), x_dataArea, l_rangeAxisLocation);
                 l_path.lineTo((float) l_y, (float) l_x);
             }
             l_path.closePath();
         }
 
         if (l_path.intersects(x_dataArea)) {
-            x_graphics.setPaint(x_positive ? getPositivePaint()
-                    : getNegativePaint());
-            x_graphics.fill(l_path);
-            if (drawOutline) {
+
+            final Paint paint = x_positive ? getPositivePaint() : getNegativePaint();
+            if (this.drawArea && paint != null) {
+                x_graphics.setPaint(paint);
+                x_graphics.fill(l_path);
+            }
+
+            if (this.drawOutline) {
                 x_graphics.setStroke(this.outlineStroke);
                 x_graphics.setPaint(this.outlinePaint);
                 x_graphics.draw(l_path);
@@ -1786,67 +1620,62 @@
     }
 
     /**
-     * Returns a default legend item for the specified series.  Subclasses
+     * Returns a default legend item for the specified series. Subclasses
      * should override this method to generate customised items.
      *
-     * @param datasetIndex  the dataset index (zero-based).
-     * @param series  the series index (zero-based).
+     * @param datasetIndex
+     *            the dataset index (zero-based).
+     * @param series
+     *            the series index (zero-based).
      *
      * @return A legend item for the series.
      */
-    public LegendItem getLegendItem(int datasetIndex, int series) {
-        LegendItem result = null;
-        XYPlot p = getPlot();
-        if (p != null) {
-            XYDataset dataset = p.getDataset(datasetIndex);
-            if (dataset != null) {
-                if (getItemVisible(series, 0)) {
-                    String label = getLegendItemLabelGenerator().generateLabel(
-                            dataset, series);
-                    String description = label;
-                    String toolTipText = null;
-                    if (getLegendItemToolTipGenerator() != null) {
-                        toolTipText
-                            = getLegendItemToolTipGenerator().generateLabel(
-                                    dataset, series);
-                    }
-                    String urlText = null;
-                    if (getLegendItemURLGenerator() != null) {
-                        urlText = getLegendItemURLGenerator().generateLabel(
-                                dataset, series);
-                    }
-                    // Individualized Paints:
-                    //Paint paint = lookupSeriesPaint(series);
+    @Override
+    public LegendItem getLegendItem(final int datasetIndex, final int series) {
+        final XYPlot p = getPlot();
+        if (p == null)
+            return null;
 
-                    // "Area-Style"- Paint.
-                    Paint paint = getPositivePaint();
-                    Stroke stroke = lookupSeriesStroke(series);
-                    Shape line = getLegendLine();
-                    // Not-filled Shape:
-                    //result = new LegendItem(label, description,
-                    //        toolTipText, urlText, line, stroke, paint);
-
-                    if (drawOutline) {
-                        // TODO Include outline style in legenditem
-                        // (there is a constructor for that)
-                    }
+        final XYDataset dataset = p.getDataset(datasetIndex);
+        if (dataset == null)
+            return null;
 
-                    // Filled Shape ("Area-Style").
-                    result = new LegendItem(label, description,
-                            toolTipText, urlText, line, paint);
-                    result.setLabelFont(lookupLegendTextFont(series));
-                    Paint labelPaint = lookupLegendTextPaint(series);
-                    if (labelPaint != null) {
-                        result.setLabelPaint(labelPaint);
-                    }
-                    result.setDataset(dataset);
-                    result.setDatasetIndex(datasetIndex);
-                    result.setSeriesKey(dataset.getSeriesKey(series));
-                    result.setSeriesIndex(series);
-                }
-            }
+        if (!getItemVisible(series, 0))
+            return null;
 
+        final String label = getLegendItemLabelGenerator().generateLabel(dataset, series);
+        final String description = label;
+        String toolTipText = null;
+        if (getLegendItemToolTipGenerator() != null) {
+            toolTipText = getLegendItemToolTipGenerator().generateLabel(dataset, series);
         }
+        String urlText = null;
+        if (getLegendItemURLGenerator() != null) {
+            urlText = getLegendItemURLGenerator().generateLabel(dataset, series);
+        }
+
+        // "Area-Style"- Paint.
+        final Paint paint = getPositivePaint();
+        final Shape line = getLegendLine();
+
+        // Filled Shape ("Area-Style").
+        final BasicStroke NULL_STROKE = new BasicStroke(0.0f);
+        final Shape NULL_SHAPE = new Line2D.Float();
+
+        final Paint outlPaint = this.drawOutline ? this.outlinePaint : Color.black;
+        final Stroke outlStroke = this.drawOutline ? this.outlineStroke : NULL_STROKE;
+
+        final LegendItem result = new LegendItem(label, description, toolTipText, urlText, true, line, this.drawArea, paint, this.drawOutline, outlPaint,
+                outlStroke, false, NULL_SHAPE, NULL_STROKE, Color.black);
+
+        result.setLabelFont(lookupLegendTextFont(series));
+        final Paint labelPaint = lookupLegendTextPaint(series);
+        if (labelPaint != null)
+            result.setLabelPaint(labelPaint);
+        result.setDataset(dataset);
+        result.setDatasetIndex(datasetIndex);
+        result.setSeriesKey(dataset.getSeriesKey(series));
+        result.setSeriesIndex(series);
 
         return result;
     }
@@ -1854,11 +1683,13 @@
     /**
      * Tests this renderer for equality with an arbitrary object.
      *
-     * @param obj  the object (<code>null</code> permitted).
+     * @param obj
+     *            the object (<code>null</code> permitted).
      *
      * @return A boolean.
      */
-    public boolean equals(Object obj) {
+    @Override
+    public boolean equals(final Object obj) {
         if (obj == this) {
             return true;
         }
@@ -1868,7 +1699,7 @@
         if (!super.equals(obj)) {
             return false;
         }
-        StableXYDifferenceRenderer that = (StableXYDifferenceRenderer) obj;
+        final StableXYDifferenceRenderer that = (StableXYDifferenceRenderer) obj;
         if (!PaintUtilities.equal(this.positivePaint, that.positivePaint)) {
             return false;
         }
@@ -1892,11 +1723,12 @@
      *
      * @return A clone.
      *
-     * @throws CloneNotSupportedException  if the renderer cannot be cloned.
+     * @throws CloneNotSupportedException
+     *             if the renderer cannot be cloned.
      */
+    @Override
     public Object clone() throws CloneNotSupportedException {
-        StableXYDifferenceRenderer clone =
-            (StableXYDifferenceRenderer) super.clone();
+        final StableXYDifferenceRenderer clone = (StableXYDifferenceRenderer) super.clone();
         clone.legendShape = ShapeUtilities.clone(this.legendShape);
         return clone;
     }
@@ -1904,11 +1736,13 @@
     /**
      * Provides serialization support.
      *
-     * @param stream  the output stream.
+     * @param stream
+     *            the output stream.
      *
-     * @throws IOException  if there is an I/O error.
+     * @throws IOException
+     *             if there is an I/O error.
      */
-    private void writeObject(ObjectOutputStream stream) throws IOException {
+    private void writeObject(final ObjectOutputStream stream) throws IOException {
         stream.defaultWriteObject();
         SerialUtilities.writePaint(this.positivePaint, stream);
         SerialUtilities.writePaint(this.negativePaint, stream);
@@ -1918,17 +1752,34 @@
     /**
      * Provides serialization support.
      *
-     * @param stream  the input stream.
+     * @param stream
+     *            the input stream.
      *
-     * @throws IOException  if there is an I/O error.
-     * @throws ClassNotFoundException  if there is a classpath problem.
+     * @throws IOException
+     *             if there is an I/O error.
+     * @throws ClassNotFoundException
+     *             if there is a classpath problem.
      */
-    private void readObject(ObjectInputStream stream)
-        throws IOException, ClassNotFoundException {
+    private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
         stream.defaultReadObject();
         this.positivePaint = SerialUtilities.readPaint(stream);
         this.negativePaint = SerialUtilities.readPaint(stream);
         this.legendShape = SerialUtilities.readShape(stream);
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+    private void drawLabel(final Graphics2D g2, final String labelText, final double screenX, final double screenY) {
+
+        final Color oldColor = g2.getColor();
+        final Font oldFont = g2.getFont();
+
+        g2.setFont(this.labelFont);
+        if (this.labelBGColor != null)
+            EnhancedLineAndShapeRenderer.drawTextBox(g2, labelText, (float) screenX, (float) screenY, this.labelBGColor);
+
+        g2.setColor(this.labelColor);
+        g2.drawString(labelText, (float) screenX, (float) screenY);
+
+        g2.setFont(oldFont);
+        g2.setColor(oldColor);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,11 +10,15 @@
 
 import java.awt.BasicStroke;
 import java.awt.Color;
+import java.awt.Paint;
 import java.awt.Stroke;
-
-import org.jfree.data.xy.XYSeriesCollection;
+import java.awt.TexturePaint;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
 
 import org.dive4elements.river.themes.ThemeDocument;
+import org.jfree.data.xy.XYSeriesCollection;
 
 /**
  * One or more dataseries to draw a polygon (either "open up/downwards", or
@@ -23,26 +27,26 @@
  * The display options can be used to control the z-order and the axis of the
  * dataset.
  */
+// FIXME:  bad abstraction: the only purpose of this derivation is to apply specific styles. This should rather be solved similar to the XYSTyle.
 public class StyledAreaSeriesCollection extends XYSeriesCollection {
     private static final long serialVersionUID = 5274940965666948237L;
 
     /** Mode, how to draw/which areas to fill. */
-    public enum FILL_MODE {UNDER, ABOVE, BETWEEN};
+    public enum FILL_MODE {UNDER, ABOVE, BETWEEN}
 
     /** MODE in use. */
-    protected FILL_MODE mode;
+    private FILL_MODE mode;
 
     /** Theme-document with attributes about actual visual representation. */
-    protected ThemeDocument theme;
-
+    private final ThemeDocument theme;
 
     /**
      * @param theme the theme-document.
      */
-    public StyledAreaSeriesCollection(ThemeDocument theme) {
+    public StyledAreaSeriesCollection(final ThemeDocument theme) {
         this.theme = theme;
         this.mode = FILL_MODE.BETWEEN;
-   }
+    }
 
 
     /** Gets the Fill mode. */
@@ -52,7 +56,7 @@
 
 
     /** Sets the Fill mode. */
-    public void setMode(FILL_MODE fMode) {
+    public void setMode(final FILL_MODE fMode) {
         this.mode = fMode;
     }
 
@@ -64,43 +68,50 @@
      * @return \param renderer
      */
     public StableXYDifferenceRenderer applyTheme(
-        StableXYDifferenceRenderer renderer
-    ) {
+            final StableXYDifferenceRenderer renderer
+            ) {
         applyFillColor(renderer);
-        applyShowShape(renderer);
+        applyShowBorder(renderer);
+        applyShowArea(renderer);
         applyOutlineColor(renderer);
         applyOutlineStyle(renderer);
+        applyShowLine(renderer);
         applyShowAreaLabel(renderer);
-        if (mode == FILL_MODE.UNDER) {
+        applyShowLineLabel(renderer);
+        applyPointStyle(renderer);
+        applyShowMinimumMaximum(renderer);
+        if (this.mode == FILL_MODE.UNDER) {
             renderer.setAreaCalculationMode(
-                StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA);
+                    StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA);
         }
-        else if (mode == FILL_MODE.ABOVE) {
+        else if (this.mode == FILL_MODE.ABOVE) {
             renderer.setAreaCalculationMode(
-                StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA);
+                    StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA);
         }
         else {
             renderer.setAreaCalculationMode(
-                StableXYDifferenceRenderer.CALCULATE_ALL_AREA);
+                    StableXYDifferenceRenderer.CALCULATE_ALL_AREA);
         }
 
         // Apply text style.
-        theme.parseComplexTextStyle().apply(renderer);
+        this.theme.parseComplexTextStyle().apply(renderer);
         return renderer;
     }
 
-
-    protected void applyFillColor(StableXYDifferenceRenderer renderer) {
-        Color paint = theme.parseAreaBackgroundColor();
+    private void applyShowMinimumMaximum(final StableXYDifferenceRenderer renderer) {
 
-        int transparency = theme.parseAreaTransparency();
-        if (transparency > 0 && paint != null) {
-            paint = new Color(
-                        paint.getRed(),
-                        paint.getGreen(),
-                        paint.getBlue(),
-                        (int)((100 - transparency) * 2.55f));
-        }
+        // TODO: nice to have
+
+        // final boolean minimumVisible = this.theme.parseShowMinimum();
+        // renderer.setIsMinimumShapeVisible(minimumVisible);
+        //
+        // final boolean maximumVisible = this.theme.parseShowMaximum();
+        // renderer.setIsMaximumShapeVisible(maximumVisible);
+    }
+
+    private void applyFillColor(final StableXYDifferenceRenderer renderer) {
+
+        Paint paint = parseFillPaint();
 
         if (paint != null && this.getMode() == FILL_MODE.ABOVE) {
             renderer.setPositivePaint(paint);
@@ -113,42 +124,78 @@
         else {
             if (paint == null)
                 paint = new Color(177, 117, 102);
+
             renderer.setPositivePaint(paint);
             renderer.setNegativePaint(paint);
         }
     }
 
+    private Paint parseFillPaint() {
+        final Color paint = this.theme.parseAreaBackgroundColor();
+        final int transparency = this.theme.parseAreaTransparency();
 
-    protected void applyShowShape(StableXYDifferenceRenderer renderer) {
-        boolean show = theme.parseAreaShowBorder();
+        final Color alphaPaint = withAlpha(paint, transparency);
+
+        final AreaFillPattern pattern = this.theme.parseAreaBackgroundPattern();
+
+        if( pattern == null || pattern == AreaFillPattern.patternFill )
+            return alphaPaint;
+
+        final BufferedImage image = pattern.getImage(alphaPaint);
+
+        final Rectangle2D anchor = new Rectangle2D.Double(0,0, image.getWidth(), image.getHeight());
+        return new TexturePaint(image, anchor);
+    }
+
+    private Color withAlpha(final Color color, final int transparency) {
+
+        if (transparency <= 0 || color == null)
+            return color;
+
+        return new Color(
+                color.getRed(),
+                color.getGreen(),
+                color.getBlue(),
+                (int)((100 - transparency) * 2.55f));
+    }
+
+    private void applyShowBorder(final StableXYDifferenceRenderer renderer) {
+        final boolean show = this.theme.parseAreaShowBorder();
         renderer.setDrawOutline(show);
     }
 
+    private void applyShowArea(final StableXYDifferenceRenderer renderer) {
 
-    protected void applyShowLine(StableXYDifferenceRenderer renderer) {
-        boolean show = theme.parseShowLine();
+        final boolean showArea = this.theme.parseShowArea();
+        renderer.setDrawArea(showArea);
+    }
+
+    private void applyShowLine(final StableXYDifferenceRenderer renderer) {
+        /* FIXME: strange: this will enable/disable showing the 'point' shapes at each vertex. */
+        /* FIXME: this will also now be overridden by the option 'showpoints' */
+        final boolean show = this.theme.parseShowLine();
         renderer.setShapesVisible(show);
     }
 
-
-    protected void applyOutlineColor(StableXYDifferenceRenderer renderer) {
-        Color c = theme.parseLineColorField();
+    private void applyOutlineColor(final StableXYDifferenceRenderer renderer) {
+        final Color c = this.theme.parseLineColorField();
         renderer.setOutlinePaint(c);
     }
 
-    protected void applyOutlineWidth(StableXYDifferenceRenderer renderer) {
-        // int size = theme.parseLineWidth();
-        // XXX: Why is this not set?
+    private void applyShowAreaLabel(final StableXYDifferenceRenderer renderer) {
+        renderer.setShowAreaLabel(this.theme.parseShowAreaLabel());
     }
 
-    /** Inform renderer whether it should draw a label. */
-    protected void applyShowAreaLabel(StableXYDifferenceRenderer renderer) {
-        renderer.setLabelArea(theme.parseShowAreaLabel());
+    private void applyShowLineLabel(final StableXYDifferenceRenderer renderer) {
+        // REMARK: using 'showlinelabel' to activate labeling the line with the title of the theme. This is the same behaviour
+        // as for line-themes.
+        final boolean showLabelLine = this.theme.parseShowLineLabel();
+        renderer.setShowTitleLabel(showLabelLine);
     }
 
-    protected void applyOutlineStyle(StableXYDifferenceRenderer renderer) {
-        float[] dashes = theme.parseLineStyle();
-        int size       = theme.parseLineWidth();
+    private void applyOutlineStyle(final StableXYDifferenceRenderer renderer) {
+        final float[] dashes = this.theme.parseLineStyle();
+        final int size       = this.theme.parseLineWidth();
 
         Stroke stroke = null;
 
@@ -157,14 +204,39 @@
         }
         else {
             stroke = new BasicStroke(Integer.valueOf(size),
-                BasicStroke.CAP_BUTT,
-                BasicStroke.JOIN_ROUND,
-                1.0f,
-                dashes,
-                0.0f);
+                    BasicStroke.CAP_BUTT,
+                    BasicStroke.JOIN_ROUND,
+                    1.0f,
+                    dashes,
+                    0.0f);
         }
 
         renderer.setOutlineStroke(stroke);
     }
+
+    private void applyPointStyle(final StableXYDifferenceRenderer renderer) {
+
+        final boolean showPoints = this.theme.parseShowPoints();
+        renderer.setShapesVisible(showPoints);
+
+        if( showPoints )
+        {
+            final int size = this.theme.parsePointWidth();
+            final int dim  = 2 * size;
+
+            final Ellipse2D pointShape = new Ellipse2D.Double(-size, -size, dim, dim);
+            final Color pointColor = this.theme.parsePointColor();
+
+            renderer.setSeriesPaint(0, pointColor);
+            renderer.setSeriesPaint(1, pointColor);
+
+            renderer.setSeriesShape(0, pointShape);
+            renderer.setSeriesShape(1, pointShape);
+        }
+    }
+
+    public boolean shouldCalculateRange() {
+        return this.theme.parseCalculateRange();
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java	Fri Jul 13 11:56:22 2018 +0200
@@ -146,6 +146,7 @@
 
 
     @Override
+    // FIXME: bad! method with undocumented side-effects; given metadata will be changed inline
     public void putMetaData(Map<String, String> metaData,
         Artifact artifact,
         CallContext context) {
@@ -155,6 +156,7 @@
         String unit = "";
         if (river != null) {
             rivername = river.getName();
+            // FIXME: this will always return the wst unit, regardless if the series is a water level or not!
             unit      = river.getWstUnit().getName();
         }
         if (metaData.containsKey("X")) {
--- a/artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java	Fri Jul 13 11:56:22 2018 +0200
@@ -13,6 +13,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.river.artifacts.model.MapserverStyle;
@@ -21,6 +22,7 @@
 import org.dive4elements.river.artifacts.model.MapserverStyle.Label;
 import org.dive4elements.river.artifacts.model.MapserverStyle.Style;
 import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.jfree.AreaFillPattern;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -102,6 +104,8 @@
 
     public final static String AREA_BACKGROUND_COLOR = "areabgcolor";
 
+    private static final String AREA_BACKGROUND_PATTERN = "areabgpattern";
+
     public final static String SYMBOL = "symbol";
 
     public final static String SHOW_MINIMUM = "showminimum";
@@ -120,6 +124,9 @@
 
     public final static String USE_FILL_PAINT = "usefillpaint";
 
+    /* boolean parameter if the range of this theme should be considered when auto-zooming. Only works for area-series at the moment */
+    private static final String CALCULATE_RANGE = "calculateRange";
+
     private Map<String, String> values;
 
     public ThemeDocument() {
@@ -608,7 +615,7 @@
         return parseColor(lineColorStr);
     }
 
-
+    // FIXME: check, this is defined in default.xml, but never used. Instead the StyledAreaSeriesCollection used lineColor etc
     public Color parseAreaLineColorField() {
         String lineColorStr = getAreaLineColorString();
         if (log.isDebugEnabled()) {
@@ -812,5 +819,29 @@
     private String getAreaShowBorderString() {
         return getValue(AREA_SHOW_BORDER);
     }
+    
+    
+    public boolean parseCalculateRange() {
+        return parseBoolean(getCalculateRangeString(), false);
+    }
+
+    
+    private String getCalculateRangeString() {
+        return getValue(CALCULATE_RANGE);
+    }
+
+    public AreaFillPattern parseAreaBackgroundPattern() {
+        final String patternName = getValue(AREA_BACKGROUND_PATTERN);
+        if( StringUtils.isBlank(patternName) )
+            return null;
+        
+        try {
+            return AreaFillPattern.valueOf(patternName);
+        }
+        catch (Exception e) {
+            log.error(String.format("%s: invalid pattern name: %s", AREA_BACKGROUND_PATTERN, patternName), e);
+            return null;
+        }
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,16 +9,15 @@
 package org.dive4elements.river.utils;
 
 import java.text.DateFormat;
+import java.text.DecimalFormat;
 import java.text.NumberFormat;
 import java.text.SimpleDateFormat;
-import java.text.DecimalFormat;
 import java.util.Locale;
 
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.river.artifacts.resources.Resources;
 
-
 /** Helper to access static i18n Formatters. */
 public final class Formatter {
 
@@ -29,18 +28,16 @@
     // WATERLEVEL FORMATTER CONSTANTS
     public static final int WATERLEVEL_KM_MIN_DIGITS = 3;
     public static final int WATERLEVEL_KM_MAX_DIGITS = 3;
-    public static final int WATERLEVEL_W_MIN_DIGITS  = 0;
-    public static final int WATERLEVEL_W_MAX_DIGITS  = 2;
-    public static final int WATERLEVEL_Q_MIN_DIGITS  = 0;
-    public static final int WATERLEVEL_Q_MAX_DIGITS  = 2;
-
+    public static final int WATERLEVEL_W_MIN_DIGITS = 0;
+    public static final int WATERLEVEL_W_MAX_DIGITS = 2;
+    public static final int WATERLEVEL_Q_MIN_DIGITS = 0;
+    public static final int WATERLEVEL_Q_MAX_DIGITS = 2;
 
     // COMPUTED DISCHARGE CURVE FORMATTER CONSTANTS
-    public static final int COMPUTED_DISCHARGE_W_MIN_DIGITS  = 2;
-    public static final int COMPUTED_DISCHARGE_W_MAX_DIGITS  = 2;
-    public static final int COMPUTED_DISCHARGE_Q_MIN_DIGITS  = 0;
-    public static final int COMPUTED_DISCHARGE_Q_MAX_DIGITS  = 2;
-
+    public static final int COMPUTED_DISCHARGE_W_MIN_DIGITS = 2;
+    public static final int COMPUTED_DISCHARGE_W_MAX_DIGITS = 2;
+    public static final int COMPUTED_DISCHARGE_Q_MIN_DIGITS = 0;
+    public static final int COMPUTED_DISCHARGE_Q_MAX_DIGITS = 2;
 
     // HISTORICAL DISCHARGE CURVE FORMATTER CONSTANTS
     public static final int HISTORICAL_DISCHARGE_W_MIN_DIGITS = 0;
@@ -48,7 +45,6 @@
     public static final int HISTORICAL_DISCHARGE_Q_MIN_DIGITS = 0;
     public static final int HISTORICAL_DISCHARGE_Q_MAX_DIGITS = 2;
 
-
     // DURATION CURVE FORMATTER CONSTANTS
     public static final int DURATION_W_MIN_DIGITS = 0;
     public static final int DURATION_W_MAX_DIGITS = 2;
@@ -57,36 +53,34 @@
     public static final int DURATION_D_MIN_DIGITS = 0;
     public static final int DURATION_D_MAX_DIGITS = 0;
 
-
     // FLOW VELOCITY FORMATTER CONSTANTS
-    public static final int FLOW_VELOCITY_KM_MIN_DIGITS     = 3;
-    public static final int FLOW_VELOCITY_KM_MAX_DIGITS     = 3;
+    public static final int FLOW_VELOCITY_KM_MIN_DIGITS = 3;
+    public static final int FLOW_VELOCITY_KM_MAX_DIGITS = 3;
     public static final int FLOW_VELOCITY_VALUES_MIN_DIGITS = 2;
     public static final int FLOW_VELOCITY_VALUES_MAX_DIGITS = 2;
-    public static final int FLOW_VELOCITY_Q_MIN_DIGITS      = 0;
-    public static final int FLOW_VELOCITY_Q_MAX_DIGITS      = 2;
-
+    public static final int FLOW_VELOCITY_Q_MIN_DIGITS = 0;
+    public static final int FLOW_VELOCITY_Q_MAX_DIGITS = 2;
 
     // MIDDLE BED HEIGHT FORMATTER CONSTANTS
-    public static final int MIDDLE_BED_HEIGHT_KM_MIN_DIGITS             = 3;
-    public static final int MIDDLE_BED_HEIGHT_KM_MAX_DIGITS             = 3;
-    public static final int MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS         = 3;
-    public static final int MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS         = 3;
-    public static final int MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS         = 3;
-    public static final int MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS         = 3;
-    public static final int MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS        = 2;
-    public static final int MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS        = 2;
+    public static final int MIDDLE_BED_HEIGHT_KM_MIN_DIGITS = 3;
+    public static final int MIDDLE_BED_HEIGHT_KM_MAX_DIGITS = 3;
+    public static final int MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS = 3;
+    public static final int MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS = 3;
+    public static final int MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS = 3;
+    public static final int MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS = 3;
+    public static final int MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS = 2;
+    public static final int MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS = 2;
     public static final int MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MIN_DIGITS = 0;
     public static final int MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MAX_DIGITS = 0;
-    public static final int MIDDLE_BED_HEIGHT_WIDTH_MIN_DIGITS          = 3;
-    public static final int MIDDLE_BED_HEIGHT_WIDTH_MAX_DIGITS          = 3;
+    public static final int MIDDLE_BED_HEIGHT_WIDTH_MIN_DIGITS = 3;
+    public static final int MIDDLE_BED_HEIGHT_WIDTH_MAX_DIGITS = 3;
 
     public static final int FIX_DELTA_W_KM_MIN_DIGITS = 3;
     public static final int FIX_DELTA_W_KM_MAX_DIGITS = 3;
     public static final int FIX_DELTA_W_DELTA_W_MIN_DIGITS = 3;
     public static final int FIX_DELTA_W_DELTA_W_MAX_DIGITS = 3;
-    public static final int FIX_DELTA_W_DELTA_Q_MIN_DIGITS  = 0;
-    public static final int FIX_DELTA_W_DELTA_Q_MAX_DIGITS  = 2;
+    public static final int FIX_DELTA_W_DELTA_Q_MIN_DIGITS = 0;
+    public static final int FIX_DELTA_W_DELTA_Q_MAX_DIGITS = 2;
 
     public static final int VARIANCE_MIN_DIGITS = 3;
     public static final int VARIANCE_MAX_DIGITS = 3;
@@ -94,26 +88,30 @@
     // SQ Relation
     public static final int SQ_RELATION_KM_MIN_DIGITS = 2;
     public static final int SQ_RELATION_KM_MAX_DIGITS = 2;
-    public static final int SQ_RELATION_A_MAX_DIGITS  = 2;
-    public static final int SQ_RELATION_A_MIN_DIGITS  = 2;
-    public static final int SQ_RELATION_B_MAX_DIGITS  = 3;
-    public static final int SQ_RELATION_B_MIN_DIGITS  = 3;
+    public static final int SQ_RELATION_A_MAX_DIGITS = 2;
+    public static final int SQ_RELATION_A_MIN_DIGITS = 2;
+    public static final int SQ_RELATION_B_MAX_DIGITS = 3;
+    public static final int SQ_RELATION_B_MIN_DIGITS = 3;
 
     // OTHER
-    public static final int CSV_DIAGRAM_DATA_MAX_DIGITS  = 3;
-    public static final int CSV_DIAGRAM_DATA_MIN_DIGITS  = 3;
+    public static final int CSV_DIAGRAM_DATA_MAX_DIGITS = 3;
+    public static final int CSV_DIAGRAM_DATA_MIN_DIGITS = 3;
 
     /**
      * Creates a localized NumberFormatter with given range of decimal digits.
-     * @param m CallMeta to find the locale.
-     * @param min minimum number of decimal ("fraction") digits.
-     * @param max maximum number of decimal ("fraction") digits.
+     *
+     * @param m
+     *            CallMeta to find the locale.
+     * @param min
+     *            minimum number of decimal ("fraction") digits.
+     * @param max
+     *            maximum number of decimal ("fraction") digits.
      * @return A NumberFormat. Use #format(NUMBER) to get String representation
      *         of NUMBER.
      */
-    public static NumberFormat getFormatter(CallMeta m, int min, int max){
-        Locale       locale = Resources.getLocale(m);
-        NumberFormat nf     = NumberFormat.getInstance(locale);
+    public static NumberFormat getFormatter(final CallMeta m, final int min, final int max) {
+        final Locale locale = Resources.getLocale(m);
+        final NumberFormat nf = NumberFormat.getInstance(locale);
 
         nf.setMaximumFractionDigits(max);
         nf.setMinimumFractionDigits(min);
@@ -121,30 +119,30 @@
         return nf;
     }
 
-    public static NumberFormat getFormatter(CallContext c, int min, int max){
+    public static NumberFormat getFormatter(final CallContext c, final int min, final int max) {
         return getFormatter(c.getMeta(), min, max);
     }
 
-
     /**
      * Returns a number formatter with no max or min digits set.
      *
-     * @param c The CallContext.
+     * @param c
+     *            The CallContext.
      *
      * @return a number formatter.
      */
-    public static NumberFormat getRawFormatter(CallContext c) {
-        Locale locale = Resources.getLocale(c.getMeta());
+    public static NumberFormat getRawFormatter(final CallContext c) {
+        final Locale locale = Resources.getLocale(c.getMeta());
         return NumberFormat.getInstance(locale);
     }
 
     /**
      * Returns a formatter in engineering notation.
      */
-    public static NumberFormat getEngFormatter(CallContext c) {
-        NumberFormat nf = getRawFormatter(c);
+    public static NumberFormat getEngFormatter(final CallContext c) {
+        final NumberFormat nf = getRawFormatter(c);
         if (nf instanceof DecimalFormat) {
-            DecimalFormat df = (DecimalFormat)nf;
+            final DecimalFormat df = (DecimalFormat) nf;
             df.applyPattern("##0.#####E0");
         }
         return nf;
@@ -153,14 +151,10 @@
     /**
      * Returns a number formatter that uses an exponent after max digits.
      */
-    public static NumberFormat getScientificFormater(
-        CallContext c,
-        int min,
-        int max
-    ) {
-        NumberFormat nf = getRawFormatter(c);
+    public static NumberFormat getScientificFormater(final CallContext c, final int min, final int max) {
+        final NumberFormat nf = getRawFormatter(c);
         if (nf instanceof DecimalFormat) {
-            DecimalFormat df = (DecimalFormat)nf;
+            final DecimalFormat df = (DecimalFormat) nf;
             df.applyPattern("0.0E0");
             df.setMaximumFractionDigits(max);
             df.setMinimumFractionDigits(min);
@@ -168,35 +162,29 @@
         return nf;
     }
 
-
     /**
      * Returns a date formatter with SHORT style.
      */
-    public static DateFormat getShortDateFormat(CallContext cc) {
-        Locale locale = Resources.getLocale(cc.getMeta());
+    public static DateFormat getShortDateFormat(final CallContext cc) {
+        final Locale locale = Resources.getLocale(cc.getMeta());
         return DateFormat.getDateInstance(DateFormat.SHORT, locale);
     }
 
-
     /**
      * Returns a date formatter with MEDIUM style.
      */
-    public static DateFormat getMediumDateFormat(CallContext cc) {
-        Locale locale = Resources.getLocale(cc.getMeta());
+    public static DateFormat getMediumDateFormat(final CallContext cc) {
+        final Locale locale = Resources.getLocale(cc.getMeta());
         return DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
     }
 
-
     /**
      * Returns the number formatter for kilometer values in waterlevel exports.
      *
      * @return the number formatter for kilometer values.
      */
-    public static NumberFormat getWaterlevelKM(CallContext context) {
-        return getFormatter(
-                context,
-                WATERLEVEL_KM_MIN_DIGITS,
-                WATERLEVEL_KM_MAX_DIGITS);
+    public static NumberFormat getWaterlevelKM(final CallContext context) {
+        return getFormatter(context, WATERLEVEL_KM_MIN_DIGITS, WATERLEVEL_KM_MAX_DIGITS);
     }
 
     /**
@@ -205,52 +193,34 @@
      *
      * @return the number formatter for csv data from diagra.
      */
-    public static NumberFormat getCSVFormatter(CallContext context) {
-        return getFormatter(
-                context,
-                CSV_DIAGRAM_DATA_MIN_DIGITS,
-                CSV_DIAGRAM_DATA_MAX_DIGITS);
+    public static NumberFormat getCSVFormatter(final CallContext context) {
+        return getFormatter(context, CSV_DIAGRAM_DATA_MIN_DIGITS, CSV_DIAGRAM_DATA_MAX_DIGITS);
     }
 
-    public static NumberFormat getWaterlevelW(CallMeta meta) {
-        return getFormatter(
-                meta,
-                WATERLEVEL_W_MIN_DIGITS,
-                WATERLEVEL_W_MAX_DIGITS);
+    public static NumberFormat getWaterlevelW(final CallMeta meta) {
+        return getFormatter(meta, WATERLEVEL_W_MIN_DIGITS, WATERLEVEL_W_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for W values in waterlevel exports.
      *
      * @return the number formatter for W values.
      */
-    public static NumberFormat getWaterlevelW(CallContext context) {
-        return getFormatter(
-                context,
-                WATERLEVEL_W_MIN_DIGITS,
-                WATERLEVEL_W_MAX_DIGITS);
+    public static NumberFormat getWaterlevelW(final CallContext context) {
+        return getFormatter(context, WATERLEVEL_W_MIN_DIGITS, WATERLEVEL_W_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for Q values in waterlevel exports.
      *
      * @return the number formatter for Q values.
      */
-    public static NumberFormat getWaterlevelQ(CallContext context) {
-        return getFormatter(
-                context,
-                WATERLEVEL_Q_MIN_DIGITS,
-                WATERLEVEL_Q_MAX_DIGITS);
+    public static NumberFormat getWaterlevelQ(final CallContext context) {
+        return getFormatter(context, WATERLEVEL_Q_MIN_DIGITS, WATERLEVEL_Q_MAX_DIGITS);
     }
 
-
-    public static NumberFormat getWaterlevelQ(CallMeta meta) {
-        return getFormatter(
-                meta,
-                WATERLEVEL_Q_MIN_DIGITS,
-                WATERLEVEL_Q_MAX_DIGITS);
+    public static NumberFormat getWaterlevelQ(final CallMeta meta) {
+        return getFormatter(meta, WATERLEVEL_Q_MIN_DIGITS, WATERLEVEL_Q_MAX_DIGITS);
     }
 
     /**
@@ -259,235 +229,201 @@
      *
      * @return the number formatter for W values.
      */
-    public static NumberFormat getComputedDischargeW(CallContext context) {
-        return getFormatter(
-                context,
-                COMPUTED_DISCHARGE_W_MIN_DIGITS,
-                COMPUTED_DISCHARGE_W_MAX_DIGITS);
+    public static NumberFormat getComputedDischargeW(final CallContext context) {
+        return getFormatter(context, COMPUTED_DISCHARGE_W_MIN_DIGITS, COMPUTED_DISCHARGE_W_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for Q values in exports of computed
      * discharge curves.
      *
      * @return the number formatter for Q values.
      */
-    public static NumberFormat getComputedDischargeQ(CallContext context) {
-        return getFormatter(
-                context,
-                COMPUTED_DISCHARGE_Q_MIN_DIGITS,
-                COMPUTED_DISCHARGE_Q_MAX_DIGITS);
+    public static NumberFormat getComputedDischargeQ(final CallContext context) {
+        return getFormatter(context, COMPUTED_DISCHARGE_Q_MIN_DIGITS, COMPUTED_DISCHARGE_Q_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for W values in exports of historical
      * discharge curves.
      *
      * @return the number formatter for W values.
      */
-    public static NumberFormat getHistoricalDischargeW(CallContext context) {
-        return getFormatter(
-                context,
-                HISTORICAL_DISCHARGE_W_MIN_DIGITS,
-                HISTORICAL_DISCHARGE_W_MAX_DIGITS);
+    public static NumberFormat getHistoricalDischargeW(final CallContext context) {
+        return getFormatter(context, HISTORICAL_DISCHARGE_W_MIN_DIGITS, HISTORICAL_DISCHARGE_W_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for Q values in exports of historical
      * discharge curves.
      *
      * @return the number formatter for Q values.
      */
-    public static NumberFormat getHistoricalDischargeQ(CallContext context) {
-        return getFormatter(
-                context,
-                HISTORICAL_DISCHARGE_Q_MIN_DIGITS,
-                HISTORICAL_DISCHARGE_Q_MAX_DIGITS);
+    public static NumberFormat getHistoricalDischargeQ(final CallContext context) {
+        return getFormatter(context, HISTORICAL_DISCHARGE_Q_MIN_DIGITS, HISTORICAL_DISCHARGE_Q_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for W values in duration curve exports.
      *
      * @return the number formatter for W values.
      */
-    public static NumberFormat getDurationW(CallContext context) {
-        return getFormatter(
-                context,
-                DURATION_W_MIN_DIGITS,
-                DURATION_W_MAX_DIGITS);
+    public static NumberFormat getDurationW(final CallContext context) {
+        return getFormatter(context, DURATION_W_MIN_DIGITS, DURATION_W_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for Q values in duration curve exports.
      *
      * @return the number formatter for W values.
      */
-    public static NumberFormat getDurationQ(CallContext context) {
-        return getFormatter(
-                context,
-                DURATION_Q_MIN_DIGITS,
-                DURATION_Q_MAX_DIGITS);
+    public static NumberFormat getDurationQ(final CallContext context) {
+        return getFormatter(context, DURATION_Q_MIN_DIGITS, DURATION_Q_MAX_DIGITS);
     }
 
-
     /**
      * Returns the number formatter for D values in duration curve exports.
      *
      * @return the number formatter for W values.
      */
-    public static NumberFormat getDurationD(CallContext context) {
-        return getFormatter(
-                context,
-                DURATION_D_MIN_DIGITS,
-                DURATION_D_MAX_DIGITS);
-    }
-
-    public static NumberFormat getCalculationKm(CallMeta meta) {
-        return getFormatter(
-                meta,
-                CALCULATION_REPORT_KM_MIN_DIGITS,
-                CALCULATION_REPORT_KM_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getFlowVelocityKM(CallContext context) {
-        return getFormatter(
-                context,
-                FLOW_VELOCITY_KM_MIN_DIGITS,
-                FLOW_VELOCITY_KM_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getFlowVelocityValues(CallContext context) {
-        return getFormatter(
-                context,
-                FLOW_VELOCITY_VALUES_MIN_DIGITS,
-                FLOW_VELOCITY_VALUES_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getFlowVelocityQ(CallContext context) {
-        return getFormatter(
-                context,
-                FLOW_VELOCITY_Q_MIN_DIGITS,
-                FLOW_VELOCITY_Q_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getMiddleBedHeightKM(CallContext context) {
-        return getFormatter(
-                context,
-                MIDDLE_BED_HEIGHT_KM_MIN_DIGITS,
-                MIDDLE_BED_HEIGHT_KM_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getMiddleBedHeightHeight(CallContext context) {
-        return getFormatter(
-                context,
-                MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS,
-                MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getMiddleBedHeightUncert(CallContext context) {
-        return getFormatter(
-                context,
-                MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS,
-                MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getMiddleBedHeightDataGap(CallContext context) {
-        return getFormatter(
-                context,
-                MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS,
-                MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS);
+    public static NumberFormat getDurationD(final CallContext context) {
+        return getFormatter(context, DURATION_D_MIN_DIGITS, DURATION_D_MAX_DIGITS);
     }
 
-
-    public static NumberFormat getMiddleBedHeightSounding(
-        CallContext context
-    ) {
-        return getFormatter(
-                context,
-                MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MIN_DIGITS,
-                MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MAX_DIGITS);
-    }
-
-
-    public static NumberFormat getFixDeltaWKM(CallContext context) {
-        return getFormatter(
-                context,
-                FIX_DELTA_W_KM_MIN_DIGITS,
-                FIX_DELTA_W_KM_MAX_DIGITS);
-    }
-
-    public static NumberFormat getFixDeltaWDeltaW(CallContext context) {
-        return getFormatter(
-                context,
-                FIX_DELTA_W_DELTA_W_MIN_DIGITS,
-                FIX_DELTA_W_DELTA_W_MAX_DIGITS);
-    }
-
-    public static NumberFormat getFixDeltaWQ(CallContext context) {
-        return getFormatter(
-                context,
-                FIX_DELTA_W_DELTA_Q_MIN_DIGITS,
-                FIX_DELTA_W_DELTA_Q_MAX_DIGITS);
+    public static NumberFormat getCalculationKm(final CallMeta meta) {
+        return getFormatter(meta, CALCULATION_REPORT_KM_MIN_DIGITS, CALCULATION_REPORT_KM_MAX_DIGITS);
     }
 
-    public static NumberFormat getFixDeltaWW(CallContext context) {
-        return getFormatter(
-                context,
-                FIX_DELTA_W_DELTA_W_MIN_DIGITS,
-                FIX_DELTA_W_DELTA_W_MAX_DIGITS);
-    }
-
-    public static NumberFormat getVariance(CallContext context) {
-        return getFormatter(
-                context,
-                VARIANCE_MIN_DIGITS,
-                VARIANCE_MAX_DIGITS);
+    public static NumberFormat getFlowVelocityKM(final CallContext context) {
+        return getFormatter(context, FLOW_VELOCITY_KM_MIN_DIGITS, FLOW_VELOCITY_KM_MAX_DIGITS);
     }
 
-    public static NumberFormat getSQRelationA(CallContext context) {
-        return getScientificFormater(
-                context,
-                SQ_RELATION_A_MIN_DIGITS,
-                SQ_RELATION_A_MAX_DIGITS);
+    public static NumberFormat getFlowVelocityValues(final CallContext context) {
+        return getFormatter(context, FLOW_VELOCITY_VALUES_MIN_DIGITS, FLOW_VELOCITY_VALUES_MAX_DIGITS);
     }
 
-    public static NumberFormat getSQRelationB(CallContext context) {
-        return getFormatter(
-                context,
-                SQ_RELATION_B_MIN_DIGITS,
-                SQ_RELATION_B_MAX_DIGITS);
+    public static NumberFormat getFlowVelocityQ(final CallContext context) {
+        return getFormatter(context, FLOW_VELOCITY_Q_MIN_DIGITS, FLOW_VELOCITY_Q_MAX_DIGITS);
     }
 
-    public static NumberFormat getSQRelationKM(CallContext context) {
-        return getFormatter(
-                context,
-                SQ_RELATION_KM_MIN_DIGITS,
-                SQ_RELATION_KM_MAX_DIGITS);
+    public static NumberFormat getMiddleBedHeightKM(final CallContext context) {
+        return getFormatter(context, MIDDLE_BED_HEIGHT_KM_MIN_DIGITS, MIDDLE_BED_HEIGHT_KM_MAX_DIGITS);
     }
 
-    public static NumberFormat getMeterFormat(CallContext context) {
-        return getFormatter(
-                context,
-                0,
-                2);
+    public static NumberFormat getMiddleBedHeightHeight(final CallContext context) {
+        return getFormatter(context, MIDDLE_BED_HEIGHT_HEIGHT_MIN_DIGITS, MIDDLE_BED_HEIGHT_HEIGHT_MAX_DIGITS);
+    }
+
+    public static NumberFormat getMiddleBedHeightUncert(final CallContext context) {
+        return getFormatter(context, MIDDLE_BED_HEIGHT_UNCERT_MIN_DIGITS, MIDDLE_BED_HEIGHT_UNCERT_MAX_DIGITS);
+    }
+
+    public static NumberFormat getMiddleBedHeightDataGap(final CallContext context) {
+        return getFormatter(context, MIDDLE_BED_HEIGHT_DATAGAP_MIN_DIGITS, MIDDLE_BED_HEIGHT_DATAGAP_MAX_DIGITS);
+    }
+
+    public static NumberFormat getMiddleBedHeightSounding(final CallContext context) {
+        return getFormatter(context, MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MIN_DIGITS, MIDDLE_BED_HEIGHT_SOUNDING_WIDTH_MAX_DIGITS);
+    }
+
+    public static NumberFormat getFixDeltaWKM(final CallContext context) {
+        return getFormatter(context, FIX_DELTA_W_KM_MIN_DIGITS, FIX_DELTA_W_KM_MAX_DIGITS);
+    }
+
+    public static NumberFormat getFixDeltaWDeltaW(final CallContext context) {
+        return getFormatter(context, FIX_DELTA_W_DELTA_W_MIN_DIGITS, FIX_DELTA_W_DELTA_W_MAX_DIGITS);
+    }
+
+    public static NumberFormat getFixDeltaWQ(final CallContext context) {
+        return getFormatter(context, FIX_DELTA_W_DELTA_Q_MIN_DIGITS, FIX_DELTA_W_DELTA_Q_MAX_DIGITS);
+    }
+
+    public static NumberFormat getFixDeltaWW(final CallContext context) {
+        return getFormatter(context, FIX_DELTA_W_DELTA_W_MIN_DIGITS, FIX_DELTA_W_DELTA_W_MAX_DIGITS);
+    }
+
+    public static NumberFormat getVariance(final CallContext context) {
+        return getFormatter(context, VARIANCE_MIN_DIGITS, VARIANCE_MAX_DIGITS);
+    }
+
+    public static NumberFormat getSQRelationA(final CallContext context) {
+        return getScientificFormater(context, SQ_RELATION_A_MIN_DIGITS, SQ_RELATION_A_MAX_DIGITS);
+    }
+
+    public static NumberFormat getSQRelationB(final CallContext context) {
+        return getFormatter(context, SQ_RELATION_B_MIN_DIGITS, SQ_RELATION_B_MAX_DIGITS);
+    }
+
+    public static NumberFormat getSQRelationKM(final CallContext context) {
+        return getFormatter(context, SQ_RELATION_KM_MIN_DIGITS, SQ_RELATION_KM_MAX_DIGITS);
+    }
+
+    public static NumberFormat getMeterFormat(final CallContext context) {
+        return getFormatter(context, 0, 2);
 
     }
 
-    public static DateFormat getDateFormatter(CallMeta m, String pattern) {
-        Locale locale = Resources.getLocale(m);
+    public static DateFormat getDateFormatter(final CallMeta m, final String pattern) {
+        final Locale locale = Resources.getLocale(m);
         return new SimpleDateFormat(pattern, locale);
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+    public static NumberFormat getMeanBedHeight(final CallContext context) {
+        return Formatter.getFormatter(context, 2, 2);
+    }
+
+    public static NumberFormat getTkh(final CallContext context) {
+        return Formatter.getFormatter(context, 1, 1);
+    }
+
+    public static NumberFormat getFlowDepth(final CallContext context) {
+        return Formatter.getFormatter(context, 2, 2);
+    }
+
+    public static NumberFormat getW(final CallContext context) {
+        return Formatter.getFormatter(context, 2, 2);
+    }
+
+    /**
+     * Another waterlevel formatter with fixed digits (always 2)
+     */
+    public static NumberFormat getWaterlevelW2(final CallMeta meta) {
+        return getFormatter(meta, 2, 2);
+    }
+
+    public static NumberFormat getChannelWidth(final CallContext context) {
+        return getFormatter(context.getMeta(), 2, 2);
+    }
+
+    public static NumberFormat getChannelDepth(final CallContext context) {
+        return getFormatter(context.getMeta(), 2, 2);
+    }
+
+    public static NumberFormat getFlowDepthDevelopmentPerYear(final CallContext context) {
+        return getFormatter(context.getMeta(), 2, 2);
+    }
+
+    public static NumberFormat getSalixLine(final CallContext context) {
+        return Formatter.getFormatter(context, 2, 2);
+    }
+
+    public static NumberFormat getUeberflutungsdauer(final CallContext context) {
+        return Formatter.getFormatter(context, 0, 0);
+    }
+
+    public static NumberFormat getInfrastructureHeight(final CallContext context) {
+        return getFormatter(context.getMeta(), 2, 2);
+    }
+
+    public static NumberFormat getIntegerFormatter(final CallContext context) {
+        return getFormatter(context.getMeta(), 0, 0);
+    }
+
+    public static NumberFormat getCollisionCount(final CallContext context) {
+        return getFormatter(context.getMeta(), 0, 0);
+    }
+
+    public static NumberFormat getCollisionGaugeW(final CallContext context) {
+        return getFormatter(context.getMeta(), 0, 2); // cm
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/GaugeIndex.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,52 @@
+/** 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.utils;
+
+import java.util.List;
+
+import org.dive4elements.river.model.Gauge;
+
+/**
+ * Allows performant access to gauges by station.
+ * @author Gernot Belger
+ */
+public class GaugeIndex {
+	private List<Gauge> gauges;
+	
+	private Gauge lastGauge = null;
+
+	public GaugeIndex( List<Gauge> gauges) {
+		this.gauges = gauges;
+	}
+	
+	public Gauge findGauge(double km) {
+
+		// REMARK: this is code copied from WaterlevelExporter, which is honestly not very fast/good.
+		// Instead we need to index by range with an RTree and directly acccess the right gauge.
+		
+		if( lastGauge != null && lastGauge.getRange().contains(km) )
+			return lastGauge;
+		
+		final Gauge gauge = findGauge(km, gauges);
+
+        lastGauge = gauge;
+            
+        return gauge;
+	}
+	
+    private static Gauge findGauge(double km, List<Gauge> gauges) {
+        for (Gauge gauge: gauges) {
+            if (gauge.getRange().contains(km)) {
+                return gauge;
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java	Fri Jul 13 11:56:22 2018 +0200
@@ -591,6 +591,7 @@
         log.debug("Search named main value for: " + value);
 
         for (MainValue mv: mainValues) {
+            // FIXME: no-go! double == comparison... its simply a wonder that this works in release mode, it definitively does not work in debug mode!
             if (mv.getValue().doubleValue() == value) {
                 log.debug("Found named main value: "
                     + mv.getMainValue().getName());
Binary file artifacts/src/main/resources/images/areapatterns/paternCross.png has changed
Binary file artifacts/src/main/resources/images/areapatterns/patternDagonalLeft.png has changed
Binary file artifacts/src/main/resources/images/areapatterns/patternDiagonalRight.png has changed
Binary file artifacts/src/main/resources/images/areapatterns/patternPoints.png has changed
--- a/artifacts/src/main/resources/messages.properties	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/resources/messages.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -13,12 +13,12 @@
 state.winfo.uesk.dgm = Digital Terrain Model
 state.winfo.uesk.profiles = Interpolated Profiles
 state.winfo.uesk.floodplain = Lateral Boundary
-state.winfo.uesk.differences = Differenzen between waterlevel and terrain
+state.winfo.uesk.differences = Differences between waterlevel and terrain
 state.winfo.uesk.scenario = Flood Plain / Scenario
 state.winfo.uesk.dc-hws = HWS
 state.winfo.uesk.user-rgd = User defined shapefiles
 state.winfo.uesk.barriers = Digitized HWS
-state.winfo.waterlevel_pair_select = Chosen differences
+state.winfo.waterlevel_pair_select = Chosen Differences
 state.winfo.historicalq.reference_gauge = Selection of Gauge
 state.winfo.historicalq.timerange = Selection of Evaluation time
 state.winfo.historicalq.mode = Selecion of analyses
@@ -37,7 +37,7 @@
 state.fix.analysis.analysisperiods = Analysis period
 state.fix.analysis.function = Function
 state.fix.analysis.preprocessing = Outliers
-state.fix.preprocess=incorporate in calculation
+state.fix.preprocess=use outlier test
 state.fix.vollmer.function=Function
 state.fix.vollmer.preprocessing = Outliers
 state.fix.vollmer.qs = Input for W/Q data
@@ -55,8 +55,8 @@
 state.minfo.bed.difference_select=Differences
 state.minfo.year=Year
 state.minfo.epoch=Epoch
+state.minfo.bed.location = Location/Distance
 state.minfo.bed.distance = Range selection
-state.minfo.bed.location = Location/Distance
 state.minfo.bed.periods = Periods
 state.minfo.bed.char_diameter = Characteristic Diameter
 state.minfo.bed.error.no_data = No data found for selected range.
@@ -67,14 +67,38 @@
 state.minfo.sediment.load.epochs = Epochs
 state.minfo.sediment.load.period = Years
 state.minfo.sediment.load.off_epochs = off. Epochs
-state.minfo.sediment.load.unit = Unit
+state.minfo.sediment.load.sq_interval = Load-Discharge Relation
+state.minfo.off_epoch = off. Epochs
 state.minfo.sediment.load.t_per_a = (t/a)
 state.minfo.sediment.load.m3_per_a = (m\u00b3/a)
-state.minfo.sediment.load.sq_interval = Load-Discharge Relation
-state.minfo.off_epoch = off. Epochs
+state.minfo.sediment.load.unit = Unit
 state.minfo.t_per_a = t/a
 state.minfo.m3_per_a = m\u00b3/a
 
+state.uinfo.vegetation_zones.table = Einteilung der Vegetationszonen und \u00dcberflutungsdauern (\u00dcFD)
+state.uinfo.salix.supraregional = \u00dcberregional wirkende Eingriffe
+
+state.uinfo.year_totalepoch = Year/Gesamter Zeitraum
+state.uinfo.year_epoch = Year/Epoch
+state.uinfo.load.year_with_soundings = Year
+state.uinfo.load.year= Year 
+state.uinfo.load.epoch=Epoch
+state.uinfo.year=Year
+state.uinfo.epoch=Epoch
+state.uinfo.totalepoch=Langj\u00e4hriges Mittel ({0} - {1})
+
+state.sinfo.year_epoch = Year/Epoch
+state.sinfo.load.year= Year(s)
+state.sinfo.load.epoch=Epoch(s)
+state.sinfo.year=Year
+state.sinfo.epoch=Epoch
+
+state.sinfo.riverside.left = Linkes Ufer
+state.sinfo.riverside.right = Rechtes Ufer
+state.sinfo.riverside.both = Beide Ufer
+riverside.left = left
+riverside.right = right
+
 year=Year
 epoch=Epoch
 off_epoch = off. Epochs
@@ -94,8 +118,8 @@
 calc.historical.discharge.curve = Historical Discharge Curve
 calc.reference.curve = Reference Curve
 calc.extreme.curve = Extreme Curves
-calc.fixation.default = Fixingg
-calc.fixation.vollmer = Generative Waterlevel
+calc.fixation.default = Fixation
+calc.fixation.vollmer = Balanced Waterlevel
 calc.bed.middle = Middle Bed Height
 calc.bed.diff = Bed Height Difference
 calc.bed.quality = Bed Quality
@@ -155,6 +179,11 @@
 main_channel = Main channel
 total_channel = Total channel
 
+chart.cross_section.title = Cross Section for river {0}
+chart.cross_section.subtitle = {0}-km: {1,number,#.###}
+chart.cross_section.xaxis.label = Distance [m]
+chart.cross_section.yaxis.label = W [{0}]
+
 chart.longitudinal.section.title = W-Longitudinal Section
 chart.longitudinal.section.subtitle = Range: {0}-km {1,number,#.###} - {2,number,#.###}
 chart.longitudinal.section.shortsubtitle = {0}
@@ -163,12 +192,6 @@
 chart.longitudinal.section.yaxis.label = W [{0}]
 chart.longitudinal.section.yaxis.second.label = Q [m\u00b3/s]
 chart.longitudinal.annotations.label = {0}.km
-
-chart.cross_section.title = Cross Section for river {0}
-chart.cross_section.subtitle = {0}-km: {1,number,#.###}
-chart.cross_section.xaxis.label = Distance [m]
-chart.cross_section.yaxis.label = W [{0}]
-
 chart.discharge.curve.title = Discharge Curve
 chart.discharge.curve.xaxis.label = Q [m\u00b3/s]
 chart.discharge.curve.yaxis.label = W [{0}]
@@ -188,7 +211,7 @@
 chart.duration.curve.yaxis.label.q = Q [m\u00b3/s]
 chart.duration.curve.curve.w = Waterlevel duration curve for {0} (km: {1})
 chart.duration.curve.curve.q = Discharge duration curve for {0} (km: {1})
-chart.historical.discharge.title = Historical Discharge Curves
+chart.historical.discharge.title = Historical Discharge Curves for Gauge {0}
 chart.historical.discharge.subtitle = Gauge {0} {1,date,medium} - {2,date,medium}
 chart.historical.discharge.xaxis.label = Time
 chart.historical.discharge.yaxis.second.label = Q [m\u00b3/s]
@@ -205,21 +228,20 @@
 chart.reference.curve.y.axis.in.cm = Target Gauge(s) [cm]
 chart.reference.curve.y.axis.in.m = Target Station(s) [NN + m]
 
+chart.fixings.derivedcurve.title = Derived curve
+chart.fixings.analysis.title = Longitudinal section at km {0}
+chart.fixings.wq.title = Fixings Analysis at km {0}
+chart.fixings.wq.yaxis.label = W [{0}]
+
+chart.extreme.wq.yaxis.label = W [{0}]
+
+chart.normalized.reference.curve.title = Reduced Reference Curve
+
 chart.w_differences.title = Differences
 chart.w_differences.subtitle = {0}
 chart.w_differences.yaxis.label = m
 chart.w_differences.yaxis.second.label = W [NN + m]
 
-chart.normalized.reference.curve.title = Reduced Reference Curve
-
-chart.fixings.wq.title = Fixings Analysis at km {0}
-chart.fixings.wq.subtitle=River: {0}; Range: {1,date,short} to {2,date,short}; Reference period: {3,date,short} to {4,date,short}
-chart.fixings.wq.subtitle1={0,date,short} to {1,date,short}
-chart.fixings.analysis.title = Longitudinal section at km {0}
-chart.fixings.wq.yaxis.label = W [{0}]
-
-chart.extreme.wq.yaxis.label = W [{0}]
-
 chart.bedquality.title=Bed Longitudinal Section
 chart.bedquality.xaxis.label={0}-km
 chart.bedquality.yaxis.label.diameter = Diameter [mm]
@@ -259,12 +281,12 @@
 facet.sq_relation.outlier.measurement = bed load data pass {0}
 
 sedimentdensity = sediment density
-coarse = Coarse gravel
 sand = Sand
 fine_middle = Fine/Mid. gravel
 susp_sand = Susp. Sand
 susp_sand_bed = Bed. part Susp.Sand
 suspended_sediment = Sediment
+coarse = Coarse gravel
 total = Total load
 
 chart.sedimentload.ls.title = Sediment load
@@ -283,7 +305,7 @@
 facet.sedimentload.suspended_load = Suspended load (from database) - {0} [{1}]
 facet.sedimentload.calc.total = Total load (calculated) - {0} [{1}]
 facet.sedimentload.calc.bed_load = Bed load (calculated) - {0} [{1}]
-facet.sedimentload.calc.bed_load_susp_sand = bed building load (calculated) - {0} [{1}]
+facet.sedimentload.calc.bed_load_susp_sand = Bed building load (calculated) - {0} [{1}]
 
 minfo.sedimentload.no.data = No sediment load data available
 sedimentload.missing.fraction.coarse = Missing fraction coarse gravel - {0}
@@ -305,17 +327,17 @@
 historical_discharge.mainvalues.w = W Main Values
 facet.flow_velocity.model.mainchannel = Mainchannel {0}
 facet.flow_velocity.model.totalchannel = Totalchannel {0}
-facet.flow_velocity.model.tau = bottom shear stress {0}
+facet.flow_velocity.model.tau = Bottom shear stress {0}
 facet.flow_velocity.model.q = Q {0}
 facet.flow_velocity.mainchannel = v Mainchannel at {0}
+facet.flow_velocity.discharge = Discharge at {0}
 facet.flow_velocity.totalchannel = v Totalchannel at {0}
 facet.flow_velocity.tauchannel = Bottom shear stress Mainchannel at {0}
 facet.flow_velocity.mainchannel.raw = v Mainchannel at {0} (raw)
 facet.flow_velocity.totalchannel.raw = v Totalchannel at {0} (raw)
 facet.flow_velocity.tauchannel.raw = Bottom shear stress Mainchannel at {0} (raw)
-facet.flow_velocity.discharge = Discharge at {0}
+facet.flow_velocity.velocity = V {0}
 facet.flow_velocity.waterlevel = Waterlevel {0}
-facet.flow_velocity.velocity = V {0}
 facet.bedheight_middle.single = Bed Height {0,number,####}
 facet.bedheight_middle.epoch = Bed Height Epoch {0,number,####} - {1,number,####}
 facet.bedquality.bed.porosity.toplayer = Porosity ({0,date} - {1,date}) ({2})
@@ -367,12 +389,13 @@
 chart.beddifference.epoch.title = Bedheight Difference
 chart.beddifference.xaxis.label = {0}-km
 chart.beddifference.yaxis.label.diff = Difference [cm]
-chart.beddifference.yaxis.label.height = Absolute Height [{0}]
+chart.beddifference.yaxis.label.height = Absolute Height [m]
 chart.beddifference.year.title = Bedheight Difference
 chart.beddifference.yaxis.label.morph = Width [m]
-chart.beddifference.yaxis.label.heights = Absolute Height [{0}]
+chart.beddifference.yaxis.label.heights = Absolute Height [m]
 chart.subtitle.radius = Width of sample window for moving average
 
+export_csv_title = Title: 
 export.csv.header.km = km
 export.csv.header.year = year
 
@@ -398,10 +421,10 @@
 export.duration.curve.csv.header.q = Q [m\u00b3/s]
 export.discharge.longitudinal.section.csv.header.km = River-Km
 export.discharge.longitudinal.section.csv.header.w = W [NN + m]
-export.discharge.longitudinal.section.csv.header.cw = W corr. [NN +m]
+export.discharge.longitudinal.section.csv.header.cw = W corr. [NN + m]
 export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s]
-export.discharge.curve.at.header = Computed Discharge Curve for {0} {0}-km: {1}
-export.discharge.curve.at.gauge.header = Discharge Table for {1}/{0} since {2} PNP[{4}] = {3}
+export.discharge.curve.at.gauge.header = Dischargetable for {1}/{0} since {2} datum[{4}] = {3}
+export.discharge.curve.at.header = Computed discharge curve for {0} {0}-km: {1}
 export.historical.discharge.csv.header.timerange = Timerange
 export.historical.discharge.csv.header.waterlevel = Waterlevel [cm]
 export.historical.discharge.csv.header.discharge = Discharge [m\u00b3/s]
@@ -470,7 +493,7 @@
 export.sqrelation.csv.info.param.f = Parameter F: transport of bed load (0.063-125 mm)
 export.sqrelation.csv.info.q = Q: Discharge in [m\u00b3/s] as measured on measurement date
 export.sqrelation.csv.info.s_kg = S: Transport in [kg/s] as measured on measurement date
-export.sqrelation.csv.info.date = Mesurement Date: The date this measurment was made
+export.sqrelation.csv.info.date = Measurement Date: The date this measurment was made
 export.sqrelation.csv.header.parameter = Parameter
 export.sqrelation.csv.header.station = Station
 export.sqrelation.csv.header.km = River-Km
@@ -493,13 +516,13 @@
 export.sqrelation.measurements.pdf.file = /jasper/sqmeasurements_en.jasper
 export.sqrelation.pdf.mode = Load Discharge Relation
 export.minfo.bedquality.km = km
-export.minfo.bedquality.density.toplayer = Density Toplayer
-export.minfo.bedquality.density.sublayer = Density Sublayer
-export.minfo.bedquality.porosity.toplayer = Porosity Toplayer
-export.minfo.bedquality.porosity.sublayer = Porosity Sublayer
-export.minfo.bedquality.diameter.bedload = Bedload Diameter
-export.minfo.bedquality.diameter.toplayer = Bed Diameter Toplayer
-export.minfo.bedquality.diameter.sublayer = Bed Diameter Sublayer
+export.minfo.bedquality.density.toplayer = Density Toplayer [t/m\u00b3]
+export.minfo.bedquality.density.sublayer = Density Sublayer [t/m\u00b3]
+export.minfo.bedquality.porosity.toplayer = Porosity Toplayer [%]
+export.minfo.bedquality.porosity.sublayer = Porosity Sublayer [%]
+export.minfo.bedquality.diameter.bedload = Bedload Diameter [mm]
+export.minfo.bedquality.diameter.toplayer = Bed Diameter Toplayer [mm]
+export.minfo.bedquality.diameter.sublayer = Bed Diameter Sublayer [mm]
 export.minfo.beddifference.km = km
 export.minfo.beddifference.diff = Bedheight Difference [cm]
 export.minfo.beddifference.diff.pair = Difference pair
@@ -584,6 +607,7 @@
 no.segments.found = No segments found.
 no.values.given = No values given.
 cannot.interpolate.w.q = Cannot interpolate W/Q.
+
 manualpoints = Manual Points
 
 no.reference.start.km = No reference start station given.
@@ -641,7 +665,6 @@
 help.state.minfo.sediment.load.unit=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.unit
 help.state.minfo.sq.period=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.period
 
-
 fix.reference.period=Reference period
 fix.reference.period.event=Reference event
 fix.reference.period.event.short=R
@@ -666,15 +689,17 @@
 chart.fix.deltawt.xaxis.label=Date
 chart.fix.deltawt.yaxis.label=\u0394 W(t) [cm]
 
-chart.fixings.derivedcurve.title = Derived curve
+chart.fixings.wq.subtitle=River: {0}; Range: {1,date,short} to {2,date,short}; Reference period: {3,date,short} to {4,date,short}
+chart.fixings.wq.subtitle1={0,date,short} to {1,date,short}
+
+chart.fixings.longitudinalsection.title=\u0394W Longitudinal section
+
 chart.fixings.deltawt.title = Differences from fitted curve at km {0}
 
-chart.fixings.longitudinalsection.title=Longitudinal section
-
 export.fixings.deltawt.csv.header.km=km
 export.fixings.deltawt.csv.header.deltaw=\u0394 W [cm]
 export.fixings.deltawt.csv.header.q=Discharge [m\u00b3/s]
-export.fixings.deltawt.csv.header.w=Waterlevel [m]
+export.fixings.deltawt.csv.header.w=Waterlevel [{0}]
 export.fixings.deltawt.csv.header.t=Date
 export.fixings.deltawt.csv.t.format=yyyy/MM/dd
 export.fixings.deltawt.csv.header.time.range=State
@@ -725,10 +750,13 @@
 static.sq.station = Station
 
 module.winfo = W-INFO
+module.sinfo = S-INFO
+module.uinfo = U-INFO
 module.minfo = M-INFO
 module.fixanalysis = Fix Analysis
 module.new_map = New Map
 module.new_chart = New Chart
+module.bundu = Betrieb und Unterhaltung
 
 load_diameter = Bedload Diameter
 bed_diameter = Bed Diameter
@@ -761,3 +789,421 @@
 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
+
+module.group.ingwerds = INGwerDs
+# empty label, so it does not get a group-frame in the ui 
+module.group.bottom = 
+
+state.sinfo.river = River
+state.sinfo.calculation_mode=Calculation Mode
+
+sinfo_calc_flow_depth=Flie\u00dftiefen
+sinfo_calc_flow_depth.warning.missingQ = {0}: no discharge available, calculation of transport body height not possible
+sinfo_calc_flow_depth.warning.waterlevel_discretisation  = Wasserspiegel {0}: r\u00e4umliche Aufl\u00f6sung betr\u00e4gt mehr als 1000m
+sinfo_calc_flow_depth.warning.year_difference = {0}: Sie verwenden als Differenzenpaar eine Wasserspiegellage aus dem Jahr {1} und eine Peilung aus dem Jahr {2}. Dies kann zu unplausiblen Werten f\u00fchren.
+
+sinfo.bedheightsfinder.nobedheightsforriver = No default bed heights for river {0}
+sinfo.bedheightsfinder.badrange = Invalid range for bed heights {0}.
+sinfo.bedheightsfinder.overlappingrange = Range of bed height {0} overlaps with other ranges.
+sinfo.bedheightsfinder.missingdescription = River {0} has no bed heights with description {1}
+sinfo.bedheightsfinder.configfile.loaderror = Failed to load config file ''{0}'': {1}
+sinfo.bedheightsfinder.notfound = Failed to access sounding with id ''{0}''
+sinfo.bedheightsfinder.empty = The bed heights do not contain any values for the selected calculation range
+
+sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung
+sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe
+sinfo_calc_collision=Grundber\u00fchrungen
+sinfo_calc_transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+sinfo_calc_flood_duration=\u00dcberflutungsdauern Infrastrukturen BWaStr
+
+state.sinfo.infrastructures_inundation = \u00dcberflutungsdauern Infrastrukturen BWaStr (Ergebnis)
+help.state.sinfo.infrastructures_inundation = ${help.url}/OnlineHilfe/SINFO#help.state.infrastructures_inundation
+
+state.sinfo.grounding =Grundber\u00fchrungen (Ergebnis)
+help.state.sinfo.grounding =help.state.sinfo.flowdepthdevlopment_current_select = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.grounding
+
+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.distance = Choose the range
+help.state.sinfo.distance = ${help.url}/OnlineHilfe/help.state.sinfo.distance
+
+state.sinfo.wq = Input for W/Q data
+help.state.sinfo.wq=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.wq
+
+state.sinfo.transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+help.state.sinfo.transport_bodies_heights=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.transport_bodies_heights
+
+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.waterlevel_soundings_minmax_select= Chosen Differences
+help.state.sinfo.waterlevel_soundings_minmax_select=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.waterlevel_soundings_minmax_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
+
+state.sinfo.flow_depth_minmax = minimale/maximale Flie\u00dftiefen
+help.state.sinfo.flow_depth_minmax = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flow_depth_minmax
+
+state.sinfo.flow_depth_development = Flie\u00dftiefenentwicklung
+help.state.sinfo.flow_depth_development = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flow_depth_development
+
+useTransportBodies.option = Transportk\u00f6rperh\u00f6hen miteinbeziehen?
+useTransportBodies.active = Activ
+useTransportBodies.inactive = Inactiv
+
+state.sinfo.flowdepthdevlopment_current_select = Aktuelles Differenzenpaar
+help.state.sinfo.flowdepthdevlopment_current_select = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flowdepthdevlopment_current_select
+
+state.sinfo.flowdepthdevlopment_historical_select = Historisches Differenzenpaar
+help.state.sinfo.flowdepthdevlopment_historical_select = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flowdepthdevlopment_historical_select
+
+state.sinfo.riverside = Auswahl der Uferseite
+state.sinfo.riverside.option1 = Linke Uferseite
+state.sinfo.riverside.option2 = Rechte Uferseite
+state.sinfo.riverside.option3 = Beide Uferseiten
+help.state.sinfo.wspl= ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.riverside
+
+state.sinfo.wqinput = Eingabe f\u00fcr W/Q Daten
+state.sinfo.wqinput.option = wqinput-option
+help.state.sinfo.wqinput = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.wqinput
+
+state.sinfo.wspl = Wasserspiegellagen
+state.sinfo.wspl.option = Wasserspiegellagen zus\u00e4tzlich darstellen?
+state.sinfo.wspl.active = Ja
+state.sinfo.wspl.inactive = Nein
+help.state.sinfo.wspl= ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.wspl
+state.sinfo.grounding.year = Jahr/Zeitraum
+state.sinfo.grounding.year.option1 = Jahr
+state.sinfo.grounding.year.option1 = Zeitraum
+help.state.sinfo.wspl= ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.grounding.year
+
+sinfo.export.flow_depth.csv.meta.header.result = ## {0} - {1} - {2}
+sinfo.export.flow_depth.csv.meta.header.result.label = Calculation Output
+sinfo.export.flow_depth.csv.meta.version = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.version.label = FLYS-Version
+sinfo.export.flow_depth.csv.meta.user = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.user.label = Bearbeiter
+sinfo.export.flow_depth.csv.meta.creation = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.creation.label = Time of creation
+sinfo.export.flow_depth.csv.meta.river = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.river.label = Gew\u00e4sser
+sinfo.export.flow_depth.csv.meta.header.sounding = ##METADATEN PEILUNG
+sinfo.export.flow_depth.csv.meta.header.sounding.year = # Jahr der Peilung: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.type = # Aufnahmeart: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.evaluator = # Auswerter: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.prj = # Lagesystem: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.elevationmodel = # H\u00f6hensystem: {0} 
+sinfo.export.flow_depth.csv.meta.header.sounding.elevationmodel.original = # urspr\u00fcngliches H\u00f6hensystem: {0}
+sinfo.export.flow_depth.csv.meta.header.waterlevel = ##METADATEN WASSERSPIEGELLAGE
+sinfo.export.flow_depth.csv.meta.header.waterlevel.name = # Bezeichnung der Wasserspiegellage: {0} 
+sinfo.export.flow_depth.csv.meta.header.waterlevel.gauge = # Bezugspegel: {0}
+sinfo.export.flow_depth.csv.meta.header.waterlevel.year = # Jahr/Zeitraum der Wasserspiegellage: {0}
+sinfo.export.flow_depth.csv.meta.range = # {0}: {1} - {2}
+sinfo.export.flow_depth.csv.meta.range.label = Range (km)
+sinfo.export.flow_depth.pdf.meta.calculation.label = Angewandte Gleichung
+sinfo.export.flow_depth.pdf.meta.calculation.name = Gill (1971)
+sinfo.export.flow_depth.csv.meta.height_unit.river = # H\u00f6hensystem des Flusses: {0} 
+
+export.flow_depth.csv.header.km = Fluss-km
+sinfo.export.flow_depth.csv.header.flowdepth = Flie\u00dftiefe
+sinfo.export.flow_depth.csv.header.flowdepthTkh = Flie\u00dftiefe mit TKH
+sinfo.export.flow_depth.csv.header.tkh = TKH
+sinfo.export.flow_depth.csv.header.waterlevel = Wasserstand
+sinfo.export.flow_depth.pdf.header.waterlevel = Wasser-stand
+sinfo.export.flow_depth.csv.header.discharge = Q
+sinfo.export.flow_depth.csv.header.label = Bezeichnung
+sinfo.export.flow_depth.csv.header.gauge = Bezugspegel
+sinfo.export.flow_depth.csv.header.mean_bed_height = Mittlere Sohlh\u00f6he
+sinfo.export.flow_depth.csv.header.mean_bed_height.short = Mittlere Sohl-
+sinfo.export.flow_depth.csv.header.sounding = Peilung/Epoche
+sinfo.export.flow_depth.csv.header.location = Lage
+
+sinfo.export.flood_duration.csv.header.riverside = Uferseite
+sinfo.export.flood_duration.csv.header.infrastructure.height = H\u00f6he der Infrastruktur
+sinfo.export.flood_duration.csv.header.duration = \u00dcberflutungsdauer [d/a]
+sinfo.export.flood_duration.csv.header.discharge = \u00dcberflutungsdauerabfluss Q
+sinfo.export.flood_duration.csv.header.infrastructure_type = Infrastrukturtyp
+sinfo.export.flood_duration.pdf.header.duration = \u00dcber-flutungs-dauer [d/a]
+sinfo.export.flood_duration.pdf.header.discharge = \u00dcber-flutungs-dauer-abfluss Q [m\u00b3/s]
+sinfo.export.flood_duration.pdf.header.infrastructure_type = Infra-struktur-typ
+sinfo.export.flood_duration.pdf.header.infrastructure.height = H\u00f6he der Infra-struktur
+
+sinfo.chart.flow_depth.section.title=h-L\u00e4ngsschnitt
+
+sinfo.chart.km.xaxis.label = {0}-km
+sinfo.chart.flow_depth.yaxis.label = Flie\u00dftiefe [m]
+
+sinfo.chart.flow_depth.section.yaxis.label=Flie\u00dftiefe [m]
+sinfo.facet.flow_depth.filtered.description = h ({0})
+sinfo.facet.flow_depth.raw.description = h ({0}) (raw)
+sinfo.facet.flow_depth_with_tkh.filtered.description = h + \u0394d ({0})
+sinfo.facet.flow_depth_with_tkh.raw.description = h + \u0394d ({0}) (raw)
+
+sinfo.chart.flow_depth_minmax.section.title = min/max h-L\u00e4ngsschnitt
+sinfo.facet.flow_depth_min.filtered.description = h-min ({0})
+sinfo.facet.flow_depth_min.raw.description = h-min ({0}) (raw)
+sinfo.facet.flow_depth_max.filtered.description = h-max ({0})
+sinfo.facet.flow_depth_max.raw.description = h-max ({0}) (raw)
+
+sinfo.chart.tkh.section.title=Transportk\u00f6rperh\u00f6hen
+sinfo.chart.tkh.section.yaxis.label = Transportk\u00f6rperh\u00f6hen [cm]
+sinfo.chart.tkh.yaxis.label = Transportk\u00f6rperh\u00f6hen [cm]
+sinfo.facet.tkh.description = \u0394d ({0})
+
+sinfo.export.tkh.calculation.formula = # Berechnungsgrundlage: Gleichung nach GILL (1971)
+sinfo.export.tkh.csv.header.tkh = Transportk\u00f6rperh\u00f6he
+sinfo.export.tkh.csv.header.tkhkind = Einteilung der Gew\u00e4ssersohle
+sinfo.export.tkh.pdf.header.tkhkind = Einteilung der Gew\u00e4sser-sohle
+sinfo.export.tkh.soilkind.mobil = Mobil
+sinfo.export.tkh.soilkind.starr = Starr
+
+sinfo.chart.tkh_velocity.section.yaxis.label = Flie\u00dfgeschwindigkeit [m/s]
+sinfo.chart.tkh_velocity.yaxis.label = Flie\u00dfgeschwindigkeit [m/s]
+sinfo.facet.tkh_velocity.description = Flie\u00dfgeschwindigkeit ({0})
+
+sinfo.chart.tkh_tau.section.yaxis.label = Sohlschubspannung [N/m\u00b2]
+sinfo.chart.tkh_tau.yaxis.label = Sohlschubspannung [N/m\u00b2]
+sinfo.facet.tkh_tau.description = Sohlschubspannung ({0})
+
+sinfo.chart.tkh_d50.section.yaxis.label = Sohlbeschaffenheit D50 [mm]
+sinfo.chart.tkh_d50.yaxis.label = Sohlbeschaffenheit D50 [mm]
+sinfo.facet.tkh_d50.description = Sohlbeschaffenheit D50 ({0})
+
+sinfo.chart.flow_depth_development.section.title = Flie\u00dftiefenentwicklung
+sinfo.chart.flow_depth_development.section.yaxis.label = Flie\u00dftiefenentwicklung [cm]
+sinfo.chart.flow_depth.development.yaxis.label = Flie\u00dftiefenentwicklung [cm]
+
+sinfo.chart.flow_depth_development_perYear.section.title = Flie\u00dftiefenentwicklung pro Jahr
+sinfo.chart.flow_depth_development_per_year.section.yaxis.label = Flie\u00dftiefenentwicklung pro Jahr [cm/a]
+sinfo.chart.flow_depth_development_per_year.yaxis.label = Flie\u00dftiefenentwicklung pro Jahr [cm/a]
+sinfo.facet.flow_depth_development_per_year.filtered = \u0394h/t [cm/a]
+sinfo.facet.flow_depth_development_per_year.filtered.description = \u0394h/t ({0})
+sinfo.facet.flow_depth_development_per_year.raw.description = \u0394h/t ({0}) (raw)
+
+sinfo_facet_flow_depth_development.filtered = \u0394h [cm]
+sinfo.facet.flow_depth_development.filtered.description = \u0394h ({0})
+sinfo.facet.flow_depth_development.raw.description = \u0394h ({0}) (raw)
+
+sinfo_facet_waterlevel_difference.filtered = \u0394WSPL [cm]
+sinfo.facet.waterlevel_difference.filtered.description = \u0394WSPL ({0})
+
+sinfo_facet_bedheight_difference.filtered = \u0394WSPL [cm]
+sinfo.facet.bedheight_difference.filtered.description = \u0394MSH ({0})
+
+sinfo_facet_flow_depth_current.filtered = h-aktuell [m]
+sinfo.facet.flow_depth_current.filtered.description =  h-aktuell ({0})
+sinfo.facet.flow_depth_current.raw.description =  h-aktuell ({0}) (raw)
+
+sinfo_facet_flow_depth_historical.filtered = h-historisch [m]
+sinfo.facet.flow_depth_historical.filtered.description = h-historisch ({0})
+sinfo.facet.flow_depth_historical.raw.description = h-historisch ({0}) (raw)
+
+sinfo.flood_duration.header.bezeichnung_index = Bezeichnung{0}
+sinfo.flood_duration.header.pdf.bezeichnung_index = Bezeich-nung{0}
+sinfo.flood_duration.header.duration_index = \u00dcberflutungsdauer WSPL{0} [d/a]
+sinfo.flood_duration.header.fd_per_year_index = \u00dcberflutungsdauer WSPL{0} [d/a]
+sinfo.flood_duration.header.pdf.fd_per_year_index = \u00dcberflu-tungs-dauer WSPL{0} [d/a]
+sinfo.flood_duration.header.w_index = Wasserstand/Wasserspiegellage{0}
+sinfo.flood_duration.header.pdf.w_index = Wasser-stand/ Wasser-spiegel-lage{0} 
+sinfo.flood_duration.header.q_index =  Q{0} [m\u00b3/s]
+
+sinfo.export.flow_depth_minmax.csv.header.min = Minimale Flie\u00dftiefe
+sinfo.export.flow_depth_minmax.csv.header.max = Maximale Flie\u00dftiefe
+
+waterlevelfetcher.missing = Failed to access waterlevel with id ''{0}''
+waterlevelfetcher.empty = The water level {0} does not contain any values for the selected calculation range
+
+bedqualityd50kmvaluefinder.error = Failed to access D50 data, calculation of transport body height not possible: {0}
+bedqualityd50kmvaluefinder.empty = The bed quality (D50) does not contain any values for the selected calculation range and sounding year {0}
+bedqualityd50kmvaluefinder.missing = Bed quality (D50) not available
+
+soilkindkmvaluefinder.empty = no soil kind available for the selected calculation range, calculation of transport body height not possible
+soilkindkmvaluefinder.missing = no soil kind available
+
+flowvelocitymodelkmvaluefinder.empty = no flow velocities available for the selected calculation range, calculation of transport body height not possible
+flowvelocitymodelkmvaluefinder.missing = no flow velocities available, calculation of transport body height not possible
+
+linearInterpolator.maxdistance = spatial discretisation exceeds {0}m, interpolation does not take place
+
+sinfo.export.csv.meta.header.sounding.current = ##METADATEN PEILUNG aktuell
+sinfo.export.csv.meta.header.sounding.historical = ##METADATEN PEILUNG historisch
+sinfo.export.csv.meta.header.waterlevel.current = ##METADATEN WASSERSPIEGELLAGE aktuell
+sinfo.export.csv.meta.header.waterlevel.historical = ##METADATEN WASSERSPIEGELLAGE historisch																			
+sinfo.export.csv.header.channel.width = Sollbreite Fahrrinne
+sinfo.export.csv.header.channel.depth = Solltiefe Fahrrinne
+sinfo.export.csv.header.flowdepth.development = Flie\u00dftiefenentwicklung
+sinfo.export.pdf.header.flowdepth.development = Flie\u00dftiefen-entwicklung
+sinfo.export.csv.header.flowdepth.development.per.year = Flie\u00dftiefenent-wicklung pro Jahr
+sinfo.export.csv.header.waterlevel.difference = \u0394WSPL
+sinfo.export.csv.header.mean_bed_height.difference = \u0394MSH
+sinfo.export.csv.header.flowdepth.current = Flie\u00dftiefe h-aktuell
+sinfo.export.csv.header.flowdepth.historical = Flie\u00dftiefe h-historisch
+
+flowdepthdevelopmentcalculation.missingCurrentYear = Failed to determine date of current watterlevel ({0}), calculation not possible.
+flowdepthdevelopmentcalculation.missingHistoricalYear = Failed to determine date of historical watterlevel ({0}), calculation not possible. 
+
+abstractsinfocalculationresults.emptyResult = {0}: result set is empty, please check the data ranges of the input 
+
+flowdepthdevelopmentcalculation.yearDifferenceCurrent = aktuelles Differenzenpaar
+flowdepthdevelopmentcalculation.yearDifferenceHistorical =  = historisches Differenzenpaar
+
+state.uinfo.inundation.vegetation=Einteilung der Vegetationszonen und \u00dcberflutunsgdauern
+state.uinfo.inundation.use_scenario=Szenariobetrachtung
+state.uinfo.inundation.scenario.regional = Eingabe der \u00c4nderung der Mittelwasserspiegellage (bis zu 5 Werte m\u00f6glich)
+state.uinfo.inundation.scenario = Werte f\u00fcr \u00c4nderung der Sohl- bzw. Mittelwasserlage eingeben
+state.uinfo.use_scenario=Szenariobetrachtung
+useScenario.option = Zus\u00e4tzlich Szenariobetrachtung miteinbeziehen?
+useScenario.active = Activ
+useScenario.inactive = Inactiv
+help.state.uinfo.use_scenario=${help.url}/OnlineHilfe/UINFO#help.state.uinfo.use_scenario
+
+state.uinfo.scenario_type=Auswahl des Szenariotyps
+scenarioType.option1 = Regional wirkende Eingriffe
+scenarioType.option2 = \u00dcberregional wirkende Eingriffe
+scenarioType.option3 = Historische Betrachtung 
+help.state.uinfo.scenario_type=${help.url}/OnlineHilfe/UINFO#help.state.uinfo.scenario_type
+
+state.uinfo.distance_only_part.historical= Teilabschnitt
+state.uinfo.distance_only_part.from_regional= Teilabschnitt
+state.uinfo.distance_only_part = Teilabschnitt
+help.state.uinfo.distance_only_part = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.distance_only_part 
+
+state.uinfo.distance_only = Choose calculation range [km]
+state.uinfo.inundationduration.distance_only = Wahl des Darstellungsbereichs
+help.state.uinfo.distance_only = ${help.url}/OnlineHilfe/UINFO#help.state.uinfo.distance_only
+uinfo_salix_line = Salix-Linie
+uinfo_inundation_duration = \u00dcberflutungsdauern Aue
+uinfo_vegetation_zones = Vegetationszonen
+
+state.uinfo.river = Gew\u00e4sser
+state.uinfo.calculation_mode=Berechnungsart
+
+mainvalue.w = Wasserstand/Wasserspiegellage
+mainvalue.w.description = Wasserstand/Wasserspiegel-lage ({0})
+mainvalue.duration = \u00dcberflutungsdauer
+mainvalue.duration.description = \u00dcberflutungsdauer ({0})
+state.uinfo.salix.historical.km_range_part = Ausgewertete Strecke
+uinfo.salix.sounding= Peilung
+uinfo.salix.soundings= Soundings
+uinfo.export.salix_line.csv.header.scenario_dwspl = \u0394MW [cm]
+uinfo.export.salix_line.csv.header.scenario = Salix-Linie_Szenario [m]
+uinfo.export.salix_line.csv.header.salix_line = Salix-Linie [m]
+uinfo.export.salix_line.csv.header.delta_mw =  (MW-MNW)x(-1) [m] 
+uinfo.export.salix_line.csv.header.hist =  Salix-Linie [m] historisch
+uinfo.export.salix_line.csv.meta.header.evaluator = # Auswerter: {0}
+uinfo.export.salix_line.csv.meta.header.waterlevel.year = # Jahr/Zeitraum der Wasserspiegellage: {0}
+uinfo.export.salix_line.csv.meta.header.waterlevel.gauge = # Bezugspegel: {0}
+uinfo.export.csv.meta.header.salix.regional = ##Regional wirkende Eingriffe 
+uinfo.export.csv.meta.header.salix.regionalextended = ##\u00dcberregional wirkende Eingriffe
+uinfo.export.csv.meta.header.salix.szenariotyp = # Szenariotyp
+uinfo.export.csv.meta.header.salix.teilabschnitt = # Teilabschnitt
+uinfo.export.csv.meta.header.salix.mwspiegellaenderung = # MittelwasserSpiegellagen\u00e4nderung
+uinfo.export.csv.meta.header.salix.historical = ##Historische Betrachtung
+uinfo.export.csv.meta.header.salix.historical.zeitpunkt = # Historischer Zeitpunkt
+uinfo.export.csv.meta.header.salix.historical.zeitart = # Art des Zeitraums 
+uinfo.export.csv.meta.header.veg.name = Vegetationszonen
+uinfo.export.csv.meta.header.veg.dauervon = \u00dcberflutungsdauer von [d/a]
+uinfo.export.csv.meta.header.veg.dauerbis = \u00dcberflutungsdauer bis [d/a]
+uinfo.export.url.inundationduration.inundationduration = \u00dcberflutungsdauer ({0})
+uinfo.export.url.inundationduration.vegetation = Vegetationszonen ({0})
+uinfo.export.url.inundationduration.vegetation_scenario= Vegetationszonen Szenario ({0}, {1}cm)
+uinfo.export.url.inundationduration.scenario = \u00dcberflutungsdauer Szenario ({0}, {1}cm)
+
+predefineddepthevol.total.title = Gesamt: {0}
+predefineddepthevol.peryear.title = J\u00e4hrlich: {0}
+ 
+predefinedchannel.width.title = Sollbreite Fahrrinne
+predefinedchannel.depth.title = Solltiefe Fahrrinne
+
+sinfo.chart.channel_width.section.yaxis.label = Sollbreite Fahrrinne [m]
+sinfo.chart.channel_depth.section.yaxis.label = Solltiefe Fahrrinne [m]
+
+sinfo.export.csv.header.infrastructure.height = Infrastrukturh\u00f6he
+infrastructure.height.title = Geod. H\u00f6he 
+
+sinfo.export.csv.title.collision.detail = Abfluss/Abflusszustand
+sinfo.export.csv.title.collison.overview = H\u00e4ufigkeiten
+sinfo.export.csv.header.collision.count = Anzahl der Grundber\u00fchrungen
+collision.count.title = Grundber\u00fchrungen {0}
+chart.collision_count.section.yaxis.label = H\u00e4ufigkeit
+sinfo.export.csv.header.collision.gaugew = Pegelstand
+collision.gaugew.title = W am Pegel {0}
+sinfo.export.csv.header.discharge.zone = Abflusszustand
+
+sinfo.export.csv.meta.header.years = # Jahr/Zeitraum: {0}
+sinfo.export.csv.header.years = Jahr/Zeitraum
+sinfo.export.csv.meta.date = Datum
+
+sinfo.chart.collision.section.title = Grundber\u00fchrungen
+
+sinfo.chart.flood_duration.section.title = \u00dcberflutungsdauer Infrastrukturen BWaStr
+sinfo.chart.flood_duration.section.yaxis.label = \u00dcberflutungsdauer [d/a]
+sinfo_facet_flood_duration = \u00dcberflutungsdauern
+sinfo_facet_flood_duration.description = \u00dcberflutungsdauern ({0})
+gauge_duration.missing = Keine Dauerzahlen vorhanden am Pegel {0}
+gauge_discharge_table.missing = No discharge table available for gauge {0}
+gauge_main_values.missing = No named main values available for gauge {0}
+wq_base_data.missing = No base waterlevel/discharge available
+sinfo.chart.flood_duration.height.section.title = H\u00f6he Infrastrukturen BWaStr
+sinfo_facet_flood_height = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr
+sinfo_facet_flood_height.description = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr ({0})
+sinfo.chart.flood_duration.curve.section.title = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie
+sinfo.chart.flood_duration.curve.xaxis.label = \u00dcberflutungsdauer [d/a]
+sinfo.chart.flood_duration.curve.w = Wasserstandsdauerlinie
+sinfo.chart.flood_duration.curve.q = Abflussdauerlinie
+
+bundu_bezugswst = Bezugswasserst\u00e4nde
+bundu_analysis = Fixinganalysis
+bundu_vollmer = relocated Waterlevel Calculation 
+
+state.bundu.river = River
+state.bundu.calculation.mode = Calculation Mode
+state.bundu.location = Distance
+state.bundu.period = Period
+state.bundu.gaugerange = Gaugerange
+state.bundu.eventselect = Event selection
+state.bundu.analysis.referenceperiod = Reference period
+state.bundu.analysis.analysisperiods = Analysis period
+state.bundu.analysis.function = Function
+state.bundu.analysis.preprocessing = Outliers
+state.bundu.preprocess=use outlier test
+state.bundu.vollmer.function=Function
+state.bundu.vollmer.preprocessing = Outliers
+state.bundu.vollmer.qs = Input for W/Q data
+state.bundu.yearselect = Bezugsjahr
+state.bundu.fix.auto = Automatische Auswahl 
+state.bundu.fix.manual = Manuelle Auswahl
+state.bundu.fixationchoice = Fixierungen
+
+help.state.bundu.river=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.river
+help.state.bundu.calculation.mode=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.calculation.mode
+help.state.bundu.location=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.location
+help.state.bundu.period=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.period
+help.state.bundu.gaugerange=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.gaugerange
+help.state.bundu.eventselect=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.eventselect
+help.state.bundu.analysis.referenceperiod=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.referenceperiod
+help.state.bundu.analysis.analysisperiods=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.analysisperiods
+help.state.bundu.analysis.function=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.function
+help.state.bundu.analysis.preprocessing=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.preprocessing
+help.state.bundu.analysis.compute=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.compute
+help.state.bundu.vollmer.function=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.function
+help.state.bundu.vollmer.preprocessing=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.preprocessing
+help.state.bundu.vollmer.qs=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.qs
+help.state.bundu.vollmer.compute=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.compute
+
+common.client.ui.selection = Selection
+common.client.ui.from = from
+common.client.ui.to = to
+
+chart.subtitle.metadata = FLYS-Version: {0} - Bearbeiter: {1} - Datum der Erstellung: {2}
+
+state.title.distance_state = Choose calculation range [km]
+state.title.location_distance_state = Choose calculation location(s) / range [km] 
+state.title.distance_part_state = Choose calculation subregion [km] 
+state.title.distance_only_inundationduration_state = Darstellungsbereich w\u00e4hlen [km]
\ No newline at end of file
--- a/artifacts/src/main/resources/messages_de.properties	Fri Feb 09 15:39:49 2018 +0100
+++ b/artifacts/src/main/resources/messages_de.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -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
@@ -55,8 +55,8 @@
 state.minfo.bed.difference_select=Differenzen
 state.minfo.year=Jahr
 state.minfo.epoch=Epoche
+state.minfo.bed.location = Ort(e)/Strecke
 state.minfo.bed.distance = Wahl der Berechnungsstrecke
-state.minfo.bed.location = Ort(e)/Strecke
 state.minfo.bed.periods = Zeitraum/Zeitr\u00e4ume
 state.minfo.bed.char_diameter = Charakteristischer Durchmesser
 state.minfo.bed.error.no_data = F\u00fcr die gew\u00e4hlte Strecke liegen keine Daten vor.
@@ -69,16 +69,39 @@
 state.minfo.sediment.load.off_epochs = Amtl. Epochen
 state.minfo.sediment.load.sq_interval = Transport-Abfluss Beziehung
 state.minfo.off_epoch = Amtl. Epochen
-state.minfo.sediment.load.unit = Einheit
 state.minfo.sediment.load.t_per_a = (t/a)
 state.minfo.sediment.load.m3_per_a = (m\u00b3/a)
+state.minfo.sediment.load.unit = Einheit
 state.minfo.t_per_a = t/a
 state.minfo.m3_per_a = m\u00b3/a
 
+state.uinfo.vegetation_zones.table = Einteilung der Vegetationszonen und \u00dcberflutungsdauern (\u00dcFD)
+state.uinfo.salix.supraregional = \u00dcberregional wirkende Eingriffe
+
+state.uinfo.year_totalepoch = Jahr/Gesamter Zeitraum
+state.uinfo.year_epoch = Jahr/Epoche
+state.uinfo.load.year_with_soundings = Jahr
+state.uinfo.load.year= Jahr 
+state.uinfo.load.epoch=Epoche
+state.uinfo.year=Einzeljahr
+state.uinfo.epoch=Epoche
+state.uinfo.totalepoch=Langj\u00e4hriges Mittel ({0} - {1})
+
+state.sinfo.year_epoch = Jahr/Epoche
+state.sinfo.load.year= Jahr(e)
+state.sinfo.load.epoch=Epoche(n)
+state.sinfo.year=Jahr
+state.sinfo.epoch=Epoche
+
+state.sinfo.riverside.left = Linkes Ufer
+state.sinfo.riverside.right = Rechtes Ufer
+state.sinfo.riverside.both = Beide Ufer
+riverside.left = links
+riverside.right = rechts
 
 year=Jahr
 epoch=Epoche
-off_epoch = Amtl. Epochen
+off_epoch = Amtl. Epoche
 soundings = Peilungen / Epochen
 t_per_a = t/a
 m3_per_a = m\u00b3/a
@@ -95,7 +118,7 @@
 calc.historical.discharge.curve = Hist. Abflusskurven
 calc.reference.curve = Bezugslinie
 calc.extreme.curve = Auslagerung extremer Wasserspiegellagen
-calc.fixation.default = Fixierungsanalyse
+calc.fixation.default = Fixierung
 calc.fixation.vollmer = Ausgelagerte Wasserspiegellage
 calc.bed.middle = Mittlere Sohlh\u00f6he
 calc.bed.diff = Sohlh\u00f6hendifferenz
@@ -200,19 +223,18 @@
 chart.reference.curve.title = Bezugslinie
 chart.reference.curve.subtitle = {0}
 
+chart.reference.curve.x.axis.in.cm = Bezugspegel [cm]
+chart.reference.curve.x.axis.in.m = Bezugsort [NN + m]
+chart.reference.curve.y.axis.in.cm = Zielpegel [cm]
+chart.reference.curve.y.axis.in.m = Zielort(e) [NN + m]
+
 chart.fixings.derivedcurve.title = Ableitungskurve
-chart.fixings.deltawt.title = Abweichungen von der Ausgleichskurve an Kilometer {0}
 chart.fixings.analysis.title = L\u00e4ngsschnitt an Kilometer {0}
 chart.fixings.wq.title = Fixierungsanalyse an Kilometer {0}
 chart.fixings.wq.yaxis.label = W [{0}]
 
 chart.extreme.wq.yaxis.label = W [{0}]
 
-chart.reference.curve.x.axis.in.cm = Bezugspegel [cm]
-chart.reference.curve.x.axis.in.m = Bezugsort [NN + m]
-chart.reference.curve.y.axis.in.cm = Zielpegel [cm]
-chart.reference.curve.y.axis.in.m = Zielort(e) [NN + m]
-
 chart.normalized.reference.curve.title = Reduzierte Bezugslinie
 
 chart.w_differences.title = Differenzen
@@ -259,13 +281,12 @@
 facet.sq_relation.outlier.measurement = Geschiebedaten Durchgang {0}
 
 sedimentdensity = Sedimentdichte
-
-coarse = Grober Kies
 sand = Sand
 fine_middle = Feine/Mittl. Kies
 susp_sand = Susp. Sand
 susp_sand_bed = Bettb. Anteil Susp. Sand
 suspended_sediment = Schwebstoff
+coarse = Grober Kies
 total = Gesamtfracht
 
 chart.sedimentload.ls.title = Sedimentfracht
@@ -286,7 +307,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}
@@ -310,11 +331,11 @@
 facet.flow_velocity.model.q = Q {0}
 facet.flow_velocity.mainchannel = v Hauptgerinne bei {0}
 facet.flow_velocity.totalchannel = v Gesamtgerinne bei {0}
-facet.flow_velocity.discharge = Abfluss bei {0}
 facet.flow_velocity.tauchannel = Sohlschubspannung Hauptgerinne bei {0}
 facet.flow_velocity.mainchannel.raw = v Hauptgerinne bei {0} (Rohdaten)
 facet.flow_velocity.totalchannel.raw = v Gesamtgerinne bei {0} (Rohdaten)
 facet.flow_velocity.tauchannel.raw = Sohlschubspannung Hauptgerinne bei {0} (Rohdaten)
+facet.flow_velocity.discharge = Abfluss bei {0}
 facet.flow_velocity.velocity = V ({0})
 facet.flow_velocity.waterlevel = W ({0})
 facet.bedheight_middle.single = Sohlh\u00f6he {0,number,####}
@@ -340,19 +361,19 @@
 bedquality.missing.porosity.toplayer = Interpolation der Porosit\u00e4t (0,0 m - 0,3 m) auf der Berechnungsstrecke f\u00fcr {0,date} - {1,date} nicht m\u00f6glich.
 bedquality.missing.porosity.sublayer = Interpolation der Porosit\u00e4t (0,1 m - 0,5 m) auf der Berechnungsstrecke f\u00fcr {0,date} - {1,date} nicht m\u00f6glich.
 facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0}
+facet.bedheight.diff.year.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten)
 facet.bedheight.sounding_width = gepeilte Breite ({0})
-facet.bedheight.diff.morph1 = Morph. aktive Breite Minuend
-facet.bedheight.diff.morph2 = Morph. aktive Breite Subtrahend
 facet.bedheight.diff.sounding = gepeilte Breite
 facet.bedheight.diff.height1 = H\u00f6he Minuend {0}
 facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0}
+facet.bedheight.diff.morph1 = Morph. aktive Breite Minuend
+facet.bedheight.diff.morph2 = Morph. aktive Breite Subtrahend
 facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0}
-facet.bedheight.diff.epoch = Sohlh\u00f6hendifferenz {0}
-facet.bedheight.diff.year.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten)
 facet.bedheight.diff.height.raw = {0} (Rohdaten)
 facet.bedheight.diff.height1.raw = H\u00f6he Minuend {0} (Rohdaten)
 facet.bedheight.diff.height2.raw = H\u00f6he Subtrahend {0} (Rohdaten)
 facet.bedheight.diff.absolute.raw = Sohlh\u00f6hendifferenz/Jahr {0} (Rohdaten)
+facet.bedheight.diff.epoch = Sohlh\u00f6hendifferenz {0}
 facet.bedheight.diff.epoch.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten)
 facet.gauge_discharge_curve.river = Gew\u00e4sser
 facet.gauge_discharge_curve.reference_gauge = Pegelnummer
@@ -368,12 +389,13 @@
 chart.beddifference.epoch.title = Sohlh\u00f6hendifferenz
 chart.beddifference.xaxis.label = {0}-km
 chart.beddifference.yaxis.label.diff = Differenz [cm]
-chart.beddifference.yaxis.label.height = Absolute H\u00f6he [m]
+chart.beddifference.yaxis.label.height = Absolute H\u00f6he [{0}]
 chart.beddifference.year.title = Sohlh\u00f6hendifferenz
 chart.beddifference.yaxis.label.morph = Breite [m]
-chart.beddifference.yaxis.label.heights = Absolute H\u00f6he [m]
+chart.beddifference.yaxis.label.heights = Absolute H\u00f6he [{0}]
 chart.subtitle.radius = Fensterbreite f\u00fcr gleitenden Mittelwert
 
+export_csv_title = Titel: 
 export.csv.header.km = km
 export.csv.header.year = Jahr
 
@@ -401,8 +423,8 @@
 export.discharge.longitudinal.section.csv.header.w = W [NN + m]
 export.discharge.longitudinal.section.csv.header.cw = W korr. [NN + m]
 export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s]
+export.discharge.curve.at.gauge.header = Abflusstafel f\u00fcr {1}/{0} ab {2} PNP[{4}] = {3}
 export.discharge.curve.at.header = Berechnete Abflusstafel f\u00fcr {0}, km {1}
-export.discharge.curve.at.gauge.header = Abflusstafel f\u00fcr {1}/{0} ab {2} PNP[{4}] = {3}
 export.historical.discharge.csv.header.timerange = Zeitraum
 export.historical.discharge.csv.header.waterlevel = Wasserstand [cm]
 export.historical.discharge.csv.header.discharge = Abfluss [m\u00b3/s]
@@ -414,7 +436,6 @@
 export.reference_curve.csv.header.w.m = W (m + NHN)
 export.reference_curve.csv.header.w.q = gleichw. Q (m\u00b3/s)
 
-
 export.waterlevel.pdf.mode = Wasserstand
 export.computed.discharge.pdf.mode = Abflusskurve
 export.computed.discharge.pdf.calc.mode = Berechnete Abflusskurve
@@ -513,7 +534,6 @@
 export.minfo.beddifference.gap1 = Datenl\u00fccke Minuend [%]
 export.minfo.beddifference.gap2 = Datenl\u00fccke Subtrahend [%]
 
-
 floodmap.wmsbackground = Hintergrundkarte
 floodmap.riveraxis = Flussachse
 floodmap.uesk = \u00dcSG: {0}-km {1,number,####} - {2,number,####} - {3}
@@ -645,7 +665,6 @@
 help.state.minfo.sediment.load.unit=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.unit
 help.state.minfo.sq.period=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.period
 
-
 fix.reference.period=Bezugszeitraum
 fix.reference.period.event=Bezugsereignis
 fix.reference.period.event.short=B
@@ -673,19 +692,20 @@
 chart.fixings.wq.subtitle=Gew\u00e4sser: {0}; Darstellungszeitraum: {1,date,short} bis {2,date,short}; Bezugszeitraum: {3,date,short} bis {4,date,short}
 chart.fixings.wq.subtitle1={0,date,short} bis {1,date,short}
 
-chart.fixings.longitudinalsection.title=L\u00e4ngsschnitt
+chart.fixings.longitudinalsection.title=\u0394W-L\u00e4ngsschnitt
+
+chart.fixings.deltawt.title = Abweichungen von der Ausgleichskurve an Kilometer {0}
 
 export.fixings.deltawt.csv.header.km=km
 export.fixings.deltawt.csv.header.deltaw=\u0394 W [cm]
 export.fixings.deltawt.csv.header.q=Abfluss [m\u00b3/s]
-export.fixings.deltawt.csv.header.w=Wasserstand [m]
+export.fixings.deltawt.csv.header.w=Wasserstand [{0}]
 export.fixings.deltawt.csv.header.t=Datum
 export.fixings.deltawt.csv.t.format=dd.MM.yyyy
 export.fixings.deltawt.csv.header.time.range=Status
 export.fixings.deltawt.csv.reference=B
 export.fixings.deltawt.csv.analysis=A{0,number,integer}
 
-
 fix.missing.river=Kein Gew\u00e4sser gew\u00e4hlt
 fix.missing.from=Kein Startkilometer gew\u00e4hlt
 fix.missing.to=Kein Endkilometer gew\u00e4hlt
@@ -720,7 +740,7 @@
 fix.km.chart.measured=gemessen
 fix.km.chart.interpolated=interpoliert
 
-fix.export.at.header = Abflusskurve aus der Fixierungsanalyse f\u00fcr {0} {0}-km: {1}
+fix.export.at.header = Abflusstafel aus der Fixierungsanalyse f\u00fcr {0} {0}-km: {1}
 fix.export.at.gauge.header = Abflusstafel aus der Fixierungsanalyse f\u00fcr {0}, Pegel: {1} PNP[{3}] = {2}
 sq.km.chart.label = Feststoffdaten
 sq.km.chart.title = Feststoffdatenbestand SedDB
@@ -730,10 +750,13 @@
 static.sq.station = Messstelle
 
 module.winfo = W-INFO
+module.sinfo = S-INFO
+module.uinfo = U-INFO
 module.minfo = M-INFO
 module.fixanalysis = Fixierungsanalyse
 module.new_map = Neue Karte
 module.new_chart = Neues Diagramm
+module.bundu = Betrieb und Unterhaltung
 
 load_diameter = Geschiebedurchmesser
 bed_diameter = Sohldurchmesser
@@ -766,3 +789,421 @@
 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
+
+module.group.ingwerds = INGwerDs
+# empty label, so it does not get a group-frame in the ui 
+module.group.bottom = 
+
+state.sinfo.river = Gew\u00e4sser
+state.sinfo.calculation_mode=Berechnungsart
+
+sinfo_calc_flow_depth=Flie\u00dftiefen
+sinfo_calc_flow_depth.warning.missingQ = {0}: keine Abflussdaten vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich
+sinfo_calc_flow_depth.warning.waterlevel_discretisation  = Wasserspiegel {0}: r\u00e4umliche Aufl\u00f6sung betr\u00e4gt mehr als 1000m
+sinfo_calc_flow_depth.warning.year_difference = {0}: Sie verwenden als Differenzenpaar eine Wasserspiegellage aus dem Jahr {1} und eine Peilung aus dem Jahr {2}. Dies kann zu unplausiblen Werten f\u00fchren.
+
+sinfo.bedheightsfinder.nobedheightsforriver = F\u00fcr {0} sind keine Standardgel\u00e4ndeh\u00f6hen definiert
+sinfo.bedheightsfinder.badrange = Ung\u00fcltige -range- f\u00fcr Sohlh\u00f6hen {0}.
+sinfo.bedheightsfinder.overlappingrange = -Range- der Sohlh\u00f6hen {0} \u00fcberlappt andere Sohlh\u00f6hen.
+sinfo.bedheightsfinder.missingdescription = Gew\u00e4sser {0} hat keine Sohlh\u00f6he mit Bezeichnung {1}
+sinfo.bedheightsfinder.configfile.loaderror = Fehler beim Laden der Konfigurationsdatei ''{0}'': {1}
+sinfo.bedheightsfinder.notfound = Keine Sohlh\u00f6he mit id ''{0}'' vorhanden
+sinfo.bedheightsfinder.empty = Die Sohlh\u00f6hen enthalten keine Werte f\u00fcr die gew\u00e4hlte Berechnungsstrecke 
+
+sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung
+sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe
+sinfo_calc_collision=Grundber\u00fchrungen
+sinfo_calc_transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+sinfo_calc_flood_duration=\u00dcberflutungsdauern Infrastrukturen BWaStr
+
+state.sinfo.infrastructures_inundation = \u00dcberflutungsdauern Infrastrukturen BWaStr (Ergebnis)
+help.state.sinfo.infrastructures_inundation = ${help.url}/OnlineHilfe/SINFO#help.state.infrastructures_inundation
+
+state.sinfo.grounding =Grundber\u00fchrungen (Ergebnis)
+help.state.sinfo.grounding =help.state.sinfo.flowdepthdevlopment_current_select = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.grounding
+
+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.distance = Wahl der Berechnungsstrecke
+help.state.sinfo.distance = ${help.url}/OnlineHilfe/help.state.sinfo.distance
+
+state.sinfo.wq = Eingabe f\u00fcr W/Q Daten
+help.state.sinfo.wq=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.wq
+
+state.sinfo.transport_bodies_heights=Transportk\u00f6rperh\u00f6hen
+help.state.sinfo.transport_bodies_heights=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.transport_bodies_heights
+
+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.waterlevel_soundings_minmax_select= Ausgew\u00e4hlte Differenzen
+help.state.sinfo.waterlevel_soundings_minmax_select=${help.url}/OnlineHilfe/SINFO#help.state.sinfo.waterlevel_soundings_minmax_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
+
+state.sinfo.flow_depth_minmax = minimale/maximale Flie\u00dftiefen
+help.state.sinfo.flow_depth_minmax = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flow_depth_minmax
+
+state.sinfo.flow_depth_development = Flie\u00dftiefenentwicklung
+help.state.sinfo.flow_depth_development = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flow_depth_development
+
+useTransportBodies.option = Transportk\u00f6rperh\u00f6hen miteinbeziehen?
+useTransportBodies.active = Aktiv
+useTransportBodies.inactive = Inaktiv
+
+state.sinfo.flowdepthdevlopment_current_select = Aktuelles Differenzenpaar
+help.state.sinfo.flowdepthdevlopment_current_select = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flowdepthdevlopment_current_select
+
+state.sinfo.flowdepthdevlopment_historical_select = Historisches Differenzenpaar
+help.state.sinfo.flowdepthdevlopment_historical_select = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.flowdepthdevlopment_historical_select
+
+state.sinfo.riverside = Auswahl der Uferseite
+state.sinfo.riverside.option1 = Linke Uferseite
+state.sinfo.riverside.option2 = Rechte Uferseite
+state.sinfo.riverside.option3 = Beide Uferseiten
+help.state.sinfo.wspl= ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.riverside
+
+state.sinfo.wqinput = Eingabe f\u00fcr W/Q Daten
+state.sinfo.wqinput.option = wqinput-option
+help.state.sinfo.wqinput = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.wqinput
+
+state.sinfo.wspl = Wasserspiegellagen
+state.sinfo.wspl.option = Wasserspiegellagen zus\u00e4tzlich darstellen?
+state.sinfo.wspl.active = Ja
+state.sinfo.wspl.inactive = Nein
+help.state.sinfo.wspl= ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.wspl   
+state.sinfo.grounding.year = Jahr/Zeitraum
+state.sinfo.grounding.year.option1 = Jahr
+state.sinfo.grounding.year.option1 = Zeitraum
+help.state.sinfo.wspl= ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.grounding.year
+
+sinfo.export.flow_depth.csv.meta.header.result = ##{0} - {1} - {2}
+sinfo.export.flow_depth.csv.meta.header.result.label = Ergebnisausgabe
+sinfo.export.flow_depth.csv.meta.version = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.version.label = FLYS-Version
+sinfo.export.flow_depth.csv.meta.user = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.user.label = Bearbeiter
+sinfo.export.flow_depth.csv.meta.creation = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.creation.label = Datum der Erstellung
+sinfo.export.flow_depth.csv.meta.river = # {0}: {1}
+sinfo.export.flow_depth.csv.meta.river.label = Gew\u00e4sser
+sinfo.export.flow_depth.csv.meta.header.sounding = ##METADATEN PEILUNG
+sinfo.export.flow_depth.csv.meta.header.sounding.year = # Jahr der Peilung: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.type = # Aufnahmeart: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.evaluator = # Auswerter: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.prj = # Lagesystem: {0}
+sinfo.export.flow_depth.csv.meta.header.sounding.elevationmodel = # H\u00f6hensystem: {0} 
+sinfo.export.flow_depth.csv.meta.header.sounding.elevationmodel.original = # urspr\u00fcngliches H\u00f6hensystem: {0}
+sinfo.export.flow_depth.csv.meta.header.waterlevel = ##METADATEN WASSERSPIEGELLAGE
+sinfo.export.flow_depth.csv.meta.header.waterlevel.name = # Bezeichnung der Wasserspiegellage: {0} 
+sinfo.export.flow_depth.csv.meta.header.waterlevel.gauge = # Bezugspegel: {0}
+sinfo.export.flow_depth.csv.meta.header.waterlevel.year = # Jahr/Zeitraum der Wasserspiegellage: {0}
+sinfo.export.flow_depth.csv.meta.range = # {0}: {1} - {2}
+sinfo.export.flow_depth.csv.meta.range.label = Bereich (km)
+sinfo.export.flow_depth.pdf.meta.calculation.label = Angewandte Gleichung
+sinfo.export.flow_depth.pdf.meta.calculation.name = Gill (1971)
+sinfo.export.flow_depth.csv.meta.height_unit.river = # H\u00f6hensystem des Flusses: {0} 
+
+export.flow_depth.csv.header.km = Fluss-km
+sinfo.export.flow_depth.csv.header.flowdepth = Flie\u00dftiefe
+sinfo.export.flow_depth.csv.header.flowdepthTkh = Flie\u00dftiefe mit TKH
+sinfo.export.flow_depth.csv.header.tkh = TKH
+sinfo.export.flow_depth.csv.header.waterlevel = Wasserstand
+sinfo.export.flow_depth.pdf.header.waterlevel = Wasser-stand
+sinfo.export.flow_depth.csv.header.discharge = Q
+sinfo.export.flow_depth.csv.header.label = Bezeichnung
+sinfo.export.flow_depth.csv.header.gauge = Bezugspegel
+sinfo.export.flow_depth.csv.header.mean_bed_height = Mittlere Sohlh\u00f6he
+sinfo.export.flow_depth.csv.header.mean_bed_height.short = Mittlere Sohl-
+sinfo.export.flow_depth.csv.header.sounding = Peilung/Epoche
+sinfo.export.flow_depth.csv.header.location = Lage
+
+sinfo.export.flood_duration.csv.header.riverside = Uferseite
+sinfo.export.flood_duration.csv.header.infrastructure.height = H\u00f6he der Infrastruktur
+sinfo.export.flood_duration.csv.header.duration = \u00dcberflutungsdauer [d/a]
+sinfo.export.flood_duration.csv.header.discharge = \u00dcberflutungsdauerabfluss Q
+sinfo.export.flood_duration.csv.header.infrastructure_type = Infrastrukturtyp
+sinfo.export.flood_duration.pdf.header.duration = \u00dcber-flutungs-dauer [d/a]
+sinfo.export.flood_duration.pdf.header.discharge = \u00dcber-flutungs-dauer-abfluss Q [m\u00b3/s]
+sinfo.export.flood_duration.pdf.header.infrastructure_type = Infra-struktur-typ
+sinfo.export.flood_duration.pdf.header.infrastructure.height = H\u00f6he der Infra-struktur
+
+sinfo.chart.flow_depth.section.title=h-L\u00e4ngsschnitt
+
+sinfo.chart.km.xaxis.label = {0}-km
+sinfo.chart.flow_depth.yaxis.label = Flie\u00dftiefe [m]
+
+sinfo.chart.flow_depth.section.yaxis.label=Flie\u00dftiefe [m]
+sinfo.facet.flow_depth.filtered.description = h ({0})
+sinfo.facet.flow_depth.raw.description = h ({0}) (Rohdaten)
+sinfo.facet.flow_depth_with_tkh.filtered.description = h + \u0394d ({0})
+sinfo.facet.flow_depth_with_tkh.raw.description = h + \u0394d ({0}) (Rohdaten)
+
+sinfo.chart.flow_depth_minmax.section.title = min/max h-L\u00e4ngsschnitt
+sinfo.facet.flow_depth_min.filtered.description = h-min ({0})
+sinfo.facet.flow_depth_min.raw.description = h-min ({0}) (Rohdaten)
+sinfo.facet.flow_depth_max.filtered.description = h-max ({0})
+sinfo.facet.flow_depth_max.raw.description = h-max ({0}) (Rohdaten)
+
+sinfo.chart.tkh.section.title=Transportk\u00f6rperh\u00f6hen
+sinfo.chart.tkh.section.yaxis.label = Transportk\u00f6rperh\u00f6hen [cm]
+sinfo.chart.tkh.yaxis.label = Transportk\u00f6rperh\u00f6hen [cm]
+sinfo.facet.tkh.description = \u0394d ({0})
+
+sinfo.export.tkh.calculation.formula = # Berechnungsgrundlage: Gleichung nach GILL (1971)
+sinfo.export.tkh.csv.header.tkh = Transportk\u00f6rperh\u00f6he
+sinfo.export.tkh.csv.header.tkhkind = Einteilung der Gew\u00e4ssersohle
+sinfo.export.tkh.pdf.header.tkhkind = Einteilung der Gew\u00e4sser-sohle
+sinfo.export.tkh.soilkind.mobil = Mobil
+sinfo.export.tkh.soilkind.starr = Starr
+
+sinfo.chart.tkh_velocity.section.yaxis.label = Flie\u00dfgeschwindigkeit [m/s]
+sinfo.chart.tkh_velocity.yaxis.label = Flie\u00dfgeschwindigkeit [m/s]
+sinfo.facet.tkh_velocity.description = Flie\u00dfgeschwindigkeit ({0})
+
+sinfo.chart.tkh_tau.section.yaxis.label = Sohlschubspannung [N/m\u00b2]
+sinfo.chart.tkh_tau.yaxis.label = Sohlschubspannung [N/m\u00b2]
+sinfo.facet.tkh_tau.description = Sohlschubspannung ({0})
+
+sinfo.chart.tkh_d50.section.yaxis.label = Sohlbeschaffenheit D50 [mm]
+sinfo.chart.tkh_d50.yaxis.label = Sohlbeschaffenheit D50 [mm]
+sinfo.facet.tkh_d50.description = Sohlbeschaffenheit D50 ({0})
+
+sinfo.chart.flow_depth_development.section.title = Flie\u00dftiefenentwicklung
+sinfo.chart.flow_depth_development.section.yaxis.label = Flie\u00dftiefenentwicklung [cm]
+sinfo.chart.flow_depth_development.yaxis.label = Flie\u00dftiefenentwicklung [cm]
+
+sinfo.chart.flow_depth_development_perYear.section.title = Flie\u00dftiefenentwicklung pro Jahr
+sinfo.chart.flow_depth_development_per_year.section.yaxis.label = Flie\u00dftiefenentwicklung pro Jahr [cm/a]
+sinfo.chart.flow_depth_development_per_year.yaxis.label = Flie\u00dftiefenentwicklung pro Jahr [cm/a]
+sinfo.facet.flow_depth_development_per_year.filtered = \u0394h/t [cm/a]
+sinfo.facet.flow_depth_development_per_year.filtered.description = \u0394h/t ({0})
+sinfo.facet.flow_depth_development_per_year.raw.description = \u0394h/t ({0}) (Rohdaten)
+
+sinfo_facet_flow_depth_development.filtered = \u0394h [cm]
+sinfo.facet.flow_depth_development.filtered.description = \u0394h ({0})
+sinfo.facet.flow_depth_development.raw.description = \u0394h ({0}) (Rohdaten)
+
+sinfo_facet_waterlevel_difference.filtered = \u0394WSPL [cm]
+sinfo.facet.waterlevel_difference.filtered.description = \u0394WSPL ({0})
+
+sinfo_facet_bedheight_difference.filtered = \u0394WSPL [cm]
+sinfo.facet.bedheight_difference.filtered.description = \u0394MSH ({0})
+
+sinfo_facet_flow_depth_current.filtered = h-aktuell [m]
+sinfo.facet.flow_depth_current.filtered.description =  h-aktuell ({0})
+sinfo.facet.flow_depth_current.raw.description =  h-aktuell ({0}) (Rohdaten)
+
+sinfo_facet_flow_depth_historical.filtered = h-historisch [m]
+sinfo.facet.flow_depth_historical.filtered.description = h-historisch ({0})
+sinfo.facet.flow_depth_historical.raw.description = h-historisch ({0}) (Rohdaten)
+
+sinfo.flood_duration.header.bezeichnung_index = Bezeichnung{0}
+sinfo.flood_duration.header.pdf.bezeichnung_index = Bezeich-nung{0}
+sinfo.flood_duration.header.duration_index = \u00dcberflutungsdauer WSPL{0} [d/a]
+sinfo.flood_duration.header.fd_per_year_index = \u00dcberflutungsdauer WSPL{0} [d/a]
+sinfo.flood_duration.header.pdf.fd_per_year_index = \u00dcberflu-tungs-dauer WSPL{0} [d/a]
+sinfo.flood_duration.header.w_index = Wasserstand/Wasserspiegellage{0}
+sinfo.flood_duration.header.pdf.w_index = Wasser-stand/ Wasser-spiegel-lage{0} 
+sinfo.flood_duration.header.q_index =  Q{0} [m\u00b3/s]
+
+sinfo.export.flow_depth_minmax.csv.header.min = Minimale Flie\u00dftiefe
+sinfo.export.flow_depth_minmax.csv.header.max = Maximale Flie\u00dftiefe
+
+waterlevelfetcher.missing = Fehler beim Zugriff auf Wasserspiegel mit id ''{0}''
+waterlevelfetcher.empty = Der Wasserspiegel ''{0}'' enth\u00e4lt keine Werte f\u00fcr die gew\u00e4hlte Berechnungsstrecke
+
+bedqualityd50kmvaluefinder.error = Fehler beim Zugriff auf die D50 Daten, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich: {0}
+bedqualityd50kmvaluefinder.empty = F\u00fcr das Jahr {0} liegen keine D50-Korndurchmesser f\u00fcr die gew\u00e4hlte Berechnungsstrecke vor
+bedqualityd50kmvaluefinder.missing = Keine D50-Korndurchmesser vorhanden
+
+soilkindkmvaluefinder.empty = Keine Sohlart f\u00fcr die gew\u00e4hlte Berechnungsstrecke vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich
+soilkindkmvaluefinder.missing = keine Sohlart vorhanden
+
+flowvelocitymodelkmvaluefinder.empty = Keine Flie\u00dfgeschwindigkeiten f\u00fcr die gew\u00e4hlte Berechnungsstrecke vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich
+flowvelocitymodelkmvaluefinder.missing = Keine Flie\u00dfgeschwindigkeiten vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich
+
+linearInterpolator.maxdistance = R\u00e4umliche Aufl\u00f6sung gr\u00f6\u00dfer als {0}m, es findet keine Interpolation statt
+
+sinfo.export.csv.meta.header.sounding.current = ##METADATEN PEILUNG aktuell
+sinfo.export.csv.meta.header.sounding.historical = ##METADATEN PEILUNG historisch
+sinfo.export.csv.meta.header.waterlevel.current = ##METADATEN WASSERSPIEGELLAGE aktuell
+sinfo.export.csv.meta.header.waterlevel.historical = ##METADATEN WASSERSPIEGELLAGE historisch
+sinfo.export.csv.header.channel.width = Sollbreite Fahrrinne
+sinfo.export.csv.header.channel.depth = Solltiefe Fahrrinne
+sinfo.export.pdf.header.flowdepth.development = Flie\u00dftiefen-entwicklung
+sinfo.export.csv.header.flowdepth.development = Flie\u00dftiefenentwicklung
+sinfo.export.csv.header.flowdepth.development.per.year = Flie\u00dftiefenent-wicklung pro Jahr
+sinfo.export.csv.header.waterlevel.difference = \u0394WSPL
+sinfo.export.csv.header.mean_bed_height.difference = \u0394MSH
+sinfo.export.csv.header.flowdepth.current = Flie\u00dftiefe h-aktuell
+sinfo.export.csv.header.flowdepth.historical = Flie\u00dftiefe h-historisch
+
+flowdepthdevelopmentcalculation.missingCurrentYear = Datum des aktuellen Wasserspiegels ({0}) konnte nicht ermittelt werden, Berechnung nicht m\u00f6glich.
+flowdepthdevelopmentcalculation.missingHistoricalYear = Datum des historischen Wasserspiegels ({0}) konnte nicht ermittelt werden, Berechnung nicht m\u00f6glich.
+
+abstractsinfocalculationresults.emptyResult = {0}: das Ergebnis enth\u00e4lt keine Daten, \u00fcberpr\u00fcfen Sie die Abdeckung der Eingangsdaten
+
+flowdepthdevelopmentcalculation.yearDifferenceCurrent = aktuelles Differenzenpaar
+flowdepthdevelopmentcalculation.yearDifferenceHistorical =  = historisches Differenzenpaar
+
+state.uinfo.inundation.vegetation=Einteilung der Vegetationszonen und \u00dcberflutunsgdauern
+state.uinfo.inundation.use_scenario=Szenariobetrachtung
+state.uinfo.inundation.scenario.regional = Eingabe der \u00c4nderung der Mittelwasserspiegellage (bis zu 5 Werte m\u00f6glich)
+state.uinfo.inundation.scenario = Werte f\u00fcr \u00c4nderung der Sohl- bzw. Mittelwasserlage eingeben
+state.uinfo.use_scenario=Szenariobetrachtung
+useScenario.option = Zus\u00e4tzlich Szenariobetrachtung miteinbeziehen?
+useScenario.active = Ja
+useScenario.inactive = Nein
+help.state.uinfo.use_scenario=${help.url}/OnlineHilfe/UINFO#help.state.uinfo.use_scenario
+
+state.uinfo.scenario_type=Auswahl des Szenariotyps
+scenarioType.option1 = Regional wirkende Eingriffe
+scenarioType.option2 = \u00dcberregional wirkende Eingriffe
+scenarioType.option3 = Historische Betrachtung 
+help.state.uinfo.scenario_type=${help.url}/OnlineHilfe/UINFO#help.state.uinfo.scenario_type
+
+state.uinfo.distance_only_part.historical= Teilabschnitt
+state.uinfo.distance_only_part.from_regional= Teilabschnitt 
+state.uinfo.distance_only_part = Teilabschnitt
+help.state.uinfo.distance_only_part = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.distance_only_part 
+
+state.uinfo.distance_only = Wahl der Berechnungsstrecke
+state.uinfo.inundationduration.distance_only = Wahl des Darstellungsbereichs
+help.state.uinfo.distance_only = ${help.url}/OnlineHilfe/SINFO#help.state.sinfo.distance_only
+uinfo_salix_line = Salix-Linie
+uinfo_inundation_duration = \u00dcberflutungsdauern Aue
+uinfo_vegetation_zones = Vegetationszonen
+
+state.uinfo.river = Gew\u00e4sser
+state.uinfo.calculation_mode=Berechnungsart
+
+mainvalue.w = Wasserstand/Wasserspiegellage
+mainvalue.w.description = Wasserstand/Wasserspiegel-lage ({0})
+mainvalue.duration = \u00dcberflutungsdauer
+mainvalue.duration.description = \u00dcberflutungsdauer ({0})
+state.uinfo.salix.historical.km_range_part = Ausgewertete Strecke
+uinfo.salix.sounding= Peilung
+uinfo.salix.soundings= Peilungen
+uinfo.export.salix_line.csv.header.scenario_dwspl = \u0394MW [cm]
+uinfo.export.salix_line.csv.header.scenario = Salix-Linie_Szenario [m]
+uinfo.export.salix_line.csv.header.salix_line = Salix-Linie [m]
+uinfo.export.salix_line.csv.header.delta_mw =  (MW-MNW)x(-1) [m] 
+uinfo.export.salix_line.csv.header.hist =  Salix-Linie [m] historisch
+uinfo.export.salix_line.csv.meta.header.evaluator = # Auswerter: {0}
+uinfo.export.salix_line.csv.meta.header.waterlevel.year = # Jahr/Zeitraum der Wasserspiegellage: {0}
+uinfo.export.salix_line.csv.meta.header.waterlevel.gauge = # Bezugspegel: {0}
+uinfo.export.csv.meta.header.salix.regional = ##Regional wirkende Eingriffe 
+uinfo.export.csv.meta.header.salix.regionalextended = ##\u00dcberregional wirkende Eingriffe
+uinfo.export.csv.meta.header.salix.szenariotyp = # Szenariotyp
+uinfo.export.csv.meta.header.salix.teilabschnitt = # Teilabschnitt
+uinfo.export.csv.meta.header.salix.mwspiegellaenderung = # MittelwasserSpiegellagen\u00e4nderung
+uinfo.export.csv.meta.header.salix.historical = ##Historische Betrachtung
+uinfo.export.csv.meta.header.salix.historical.zeitpunkt = # Historischer Zeitpunkt
+uinfo.export.csv.meta.header.salix.historical.zeitart = # Art des Zeitraums 
+uinfo.export.csv.meta.header.veg.name = Vegetationszonen
+uinfo.export.csv.meta.header.veg.dauervon = \u00dcberflutungsdauer von [d/a]
+uinfo.export.csv.meta.header.veg.dauerbis = \u00dcberflutungsdauer bis [d/a]
+uinfo.export.url.inundationduration.inundationduration = \u00dcberflutungsdauer ({0})
+uinfo.export.url.inundationduration.vegetation = Vegetationszonen ({0})
+uinfo.export.url.inundationduration.vegetation_scenario= Vegetationszonen Szenario ({0}, {1}cm)
+uinfo.export.url.inundationduration.scenario = \u00dcberflutungsdauer Szenario ({0}, {1}cm) 
+
+predefineddepthevol.total.title = Gesamt: {0}
+predefineddepthevol.peryear.title = J\u00e4hrlich: {0}
+
+sinfo.chart.channel_width.section.yaxis.label = Sollbreite Fahrrinne [m]
+sinfo.chart.channel_depth.section.yaxis.label = Solltiefe Fahrrinne [m]
+
+predefinedchannel.width.title = Sollbreite Fahrrinne
+predefinedchannel.depth.title = Solltiefe Fahrrinne
+
+sinfo.export.csv.header.infrastructure.height = Infrastrukturh\u00f6he
+infrastructure.height.title = Geod. H\u00f6he 
+
+sinfo.export.csv.title.collision.detail = Abfluss/Abflusszustand
+sinfo.export.csv.title.collison.overview = H\u00e4ufigkeiten
+sinfo.export.csv.header.collision.count = Anzahl der Grundber\u00fchrungen
+collision.count.title = Grundber\u00fchrungen {0}
+chart.collision_count.section.yaxis.label = H\u00e4ufigkeit
+sinfo.export.csv.header.collision.gaugew = Pegelstand
+collision.gaugew.title = W am Pegel {0}
+sinfo.export.csv.header.discharge.zone = Abflusszustand
+
+sinfo.export.csv.meta.header.years = # Jahr/Zeitraum: {0}
+sinfo.export.csv.header.years = Jahr/Zeitraum
+sinfo.export.csv.meta.date = Datum
+
+sinfo.chart.collision.section.title = Grundber\u00fchrungen
+
+sinfo.chart.flood_duration.section.title = \u00dcberflutungsdauer Infrastrukturen BWaStr
+sinfo.chart.flood_duration.section.yaxis.label = \u00dcberflutungsdauer [d/a]
+sinfo_facet_flood_duration = \u00dcberflutungsdauern
+sinfo_facet_flood_duration.description = \u00dcberflutungsdauern ({0})
+gauge_duration.missing = Dauerzahlen fehlen am Pegel {0}
+gauge_discharge_table.missing = Abflusstafel fehlt am Pegel {0}
+gauge_main_values.missing = Hauptwerte fehlen am Pegel {0}
+wq_base_data.missing = W/Q-Daten fehlen oder sind ung\00fcltig
+sinfo.chart.flood_duration.height.section.title = H\u00f6he Infrastrukturen BWaStr
+sinfo_facet_flood_height = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr
+sinfo_facet_flood_height.description = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr ({0})
+sinfo.chart.flood_duration.curve.section.title = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie
+sinfo.chart.flood_duration.curve.xaxis.label = \u00dcberflutungsdauer [d/a]
+sinfo.chart.flood_duration.curve.w = Wasserstandsdauerlinie
+sinfo.chart.flood_duration.curve.q = Abflussdauerlinie
+
+bundu_bezugswst = Bezugswasserst\u00e4nde
+bundu_analysis = Fixierungsanalyse
+bundu_vollmer = ausgelagerte Wasserspiegellage
+
+state.bundu.river = Gew\u00e4sser
+state.bundu.calculation.mode = Berechnungsart
+state.bundu.location = Strecke
+state.bundu.period = Zeitraum
+state.bundu.gaugerange = Abflussklassen
+state.bundu.eventselect = Ereignisauswahl
+state.bundu.analysis.referenceperiod = Bezugszeitraum
+state.bundu.analysis.analysisperiods = Analysezeitr\u00e4ume
+state.bundu.analysis.function = Ausgleichsfunktion
+state.bundu.analysis.preprocessing = Ausrei\u00dfer
+state.bundu.preprocess=Ausrei\u00dfertest durchf\u00fchren
+state.bundu.vollmer.function= Ausgleichsfunktion
+state.bundu.vollmer.preprocessing = Ausrei\u00dfer
+state.bundu.vollmer.qs = Eingabe f\u00fcr W/Q Daten
+state.bundu.yearselect = Bezugsjahr
+state.bundu.fix.auto = Automatische Auswahl 
+state.bundu.fix.manual = Manuelle Auswahl
+state.bundu.fixationchoice = Fixierungen
+
+help.state.bundu.river=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.river
+help.state.bundu.calculation.mode=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.calculation.mode
+help.state.bundu.location=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.location
+help.state.bundu.period=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.period
+help.state.bundu.gaugerange=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.gaugerange
+help.state.bundu.eventselect=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.eventselect
+help.state.bundu.analysis.referenceperiod=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.referenceperiod
+help.state.bundu.analysis.analysisperiods=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.analysisperiods
+help.state.bundu.analysis.function=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.function
+help.state.bundu.analysis.preprocessing=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.preprocessing
+help.state.bundu.analysis.compute=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.analysis.compute
+help.state.bundu.vollmer.function=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.function
+help.state.bundu.vollmer.preprocessing=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.preprocessing
+help.state.bundu.vollmer.qs=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.qs
+help.state.bundu.vollmer.compute=${help.url}/OnlineHilfe/bunduierungsanalyse#help.state.bundu.vollmer.compute
+
+common.client.ui.selection = Auswahl
+common.client.ui.from = von
+common.client.ui.to = bis
+
+chart.subtitle.metadata = FLYS-Version: {0} - Bearbeiter: {1} - Datum der Erstellung: {2}
+
+state.title.distance_state = Berechnungsstrecke w\u00e4hlen [km]
+state.title.location_distance_state = Berechnungsort(e) / strecke w\u00e4hlen [km] 
+state.title.distance_part_state = Teilstrecke w\u00e4hlen [km] 
+state.title.distance_only_inundationduration_state = Darstellungsbereich w\u00e4hlen [km]
\ No newline at end of file
--- a/artifacts/src/main/resources/messages_de_DE.properties	Fri Feb 09 15:39:49 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,765 +0,0 @@
-false=Nein
-true=Ja
-
-state.winfo.river = Gew\u00e4sser
-state.winfo.calculation_mode = Berechnungsart
-state.winfo.location_distance = Wahl des Berechnungsortes/strecke
-state.winfo.wq = Eingabe f\u00fcr W/Q Daten
-state.winfo.wq_adapted = Eingabe f\u00fcr W/Q Daten
-state.winfo.location = Wahl des Berechnungsortes
-state.winfo.distance = Wahl der Berechnungsstrecke
-state.winfo.distance_only = Wahl der Berechnungsstrecke
-state.winfo.uesk.wsp = Wahl der Wasserspiegellage
-state.winfo.uesk.dgm = Digitales Gel\u00e4ndemodell
-state.winfo.uesk.profiles = Interpolierte Profile
-state.winfo.uesk.floodplain = Laterale Begrenzung
-state.winfo.uesk.differences = Differenzen zwischen Wasserspiegellage und Gel\u00e4nde
-state.winfo.uesk.scenario = \u00dcberschwemmungsfl\u00e4che / Szenario
-state.winfo.uesk.dc-hws = Hochwasserschutzanlagen
-state.winfo.uesk.user-rgd = Benutzerdefinierte Shapefiles
-state.winfo.uesk.barriers = Benutzerdefinierte Hochwasserschutzanlagen
-state.winfo.waterlevel_pair_select = Ausgew\u00e4hlte Differenzen
-state.winfo.historicalq.reference_gauge = Wahl des Pegels
-state.winfo.historicalq.timerange = Wahl des Auswertezeitraums
-state.winfo.historicalq.mode = Wahl der Analyseart
-state.winfo.reference.curve.input.start = Bezugsort
-state.winfo.reference.curve.input.end = Zielort(e)
-state.winfo.function_select = Funktion
-state.winfo.extreme.percent = Abstand zum letzten Extremwert in Prozent
-state.winfo.extreme.qinput = Eingabe f\u00fcr Q Daten
-state.fix.river = Gew\u00e4sser
-state.fix.calculation.mode = Berechnungsart
-state.fix.location = Strecke
-state.fix.period = Zeitraum
-state.fix.gaugerange = Abflussklassen
-state.fix.eventselect = Ereignisauswahl
-state.fix.analysis.referenceperiod = Bezugszeitraum
-state.fix.analysis.analysisperiods = Analysezeitr\u00e4ume
-state.fix.analysis.function = Ausgleichsfunktion
-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.qs = Eingabe f\u00fcr W/Q Daten
-
-state.minfo.river = Gew\u00e4sser
-state.minfo.calculation_mode = Berechnungsart
-state.minfo.distance = Wahl der Berechnungsstrecke
-state.minfo.distance_only = Wahl der Berechnungsstrecke
-state.minfo.dischargestate = Abflusszustand und Gerinne
-state.minfo.sq.location=Ort
-state.minfo.sq.period=Zeitraum
-state.minfo.sq.outliers=Toleranz
-state.minfo.sq.outlier-method=Ausrei\u00dfertest
-state.minfo.bed.year_epoch=Jahr/Epoche
-state.minfo.bed.difference_select=Differenzen
-state.minfo.year=Jahr
-state.minfo.epoch=Epoche
-state.minfo.bed.location = Ort(e)/Strecke
-state.minfo.bed.distance = Wahl der Berechnungsstrecke
-state.minfo.bed.periods = Zeitraum/Zeitr\u00e4ume
-state.minfo.bed.char_diameter = Charakteristischer Durchmesser
-state.minfo.bed.error.no_data = F\u00fcr die gew\u00e4hlte Strecke liegen keine Daten vor.
-state.minfo.bed.error.no_data_for_period = F\u00fcr den Zeitraum {0} - {1} liegen keine Daten vor.
-state.minfo.soundings = Wahl der Peilungen
-state.minfo.sediment.load.location = Berechnungsstrecke
-state.minfo.sediment.load.year_epoch = Jahr/Zeitraum
-state.minfo.sediment.load.epochs = Epochen
-state.minfo.sediment.load.period = Jahre
-state.minfo.sediment.load.off_epochs = Amtl. Epochen
-state.minfo.sediment.load.sq_interval = Transport-Abfluss Beziehung
-state.minfo.off_epoch = Amtl. Epochen
-state.minfo.sediment.load.t_per_a = (t/a)
-state.minfo.sediment.load.m3_per_a = (m\u00b3/a)
-state.minfo.sediment.load.unit = Einheit
-state.minfo.t_per_a = t/a
-state.minfo.m3_per_a = m\u00b3/a
-
-year=Jahr
-epoch=Epoche
-off_epoch = Amtl. Epoche
-soundings = Peilungen / Epochen
-t_per_a = t/a
-m3_per_a = m\u00b3/a
-
-historical.mode.w = Wasserstandsanalyse
-historical.mode.q = Abflussanalyse
-
-calc.surface.curve = Wasserstand/Wasserspiegellage
-calc.flood.map = \u00dcberschwemmungsfl\u00e4che
-calc.discharge.curve = Abflusskurve/Abflusstafel
-calc.duration.curve = Dauerlinie
-calc.discharge.longitudinal.section = W f\u00fcr benutzerdefinierten Abflussl\u00e4ngsschnitt
-calc.w.differences = Differenzen
-calc.historical.discharge.curve = Hist. Abflusskurven
-calc.reference.curve = Bezugslinie
-calc.extreme.curve = Auslagerung extremer Wasserspiegellagen
-calc.fixation.default = Fixierung
-calc.fixation.vollmer = Ausgelagerte Wasserspiegellage
-calc.bed.middle = Mittlere Sohlh\u00f6he
-calc.bed.diff = Sohlh\u00f6hendifferenz
-calc.bed.quality = Sohlbeschaffenheit
-calc.sediment.load = Sedimentfracht
-calc.flow.velocity = Flie\u00dfgeschwindigkeit
-calc.sq.relation = Transport-Abfluss Beziehung
-calc.bed.d90 = D90
-calc.bed.d84 = D84
-calc.bed.d80 = D80
-calc.bed.d75 = D75
-calc.bed.d70 = D70
-calc.bed.d60 = D60
-calc.bed.d50 = D50
-calc.bed.d40 = D40
-calc.bed.d30 = D30
-calc.bed.d25 = D25
-calc.bed.d20 = D20
-calc.bed.d16 = D16
-calc.bed.d10 = D10
-calc.bed.dm = dm
-calc.bed.dmin = Dmin
-calc.bed.dmax = Dmax
-calc.bed.dmid = Dmid
-
-calculation.analysis = Fixierungsanalyse
-calculation.vollmer = ausgelagerte Wasserspiegellage
-
-state.chart.river = Gew\u00e4sser
-state.chart.type = Diagrammtyp
-state.chart.km = Kilometer
-
-chart.new.durationcurve = Dauerlinie
-chart.new.computeddischargecurve = Abflusskurve
-chart.new.longitudinal_section = L\u00e4ngsschnitt
-chart.new.w_differences = Differenzen
-chart.new.crosssection = Querprofil
-
-cross_section = Querprofil
-
-reference_curve = Bezugslinie
-reference_curve_normalized = Reduzierte Bezugslinie
-
-scenario.current = Aktuell
-scenario.potentiel = Potenziell
-scenario.scenario = Szenario
-
-floodplain.option = Talaue verwenden?
-floodplain.active = Aktiv
-floodplain.inactive = Inaktiv
-
-outlier.method.grubbs=Grubbs
-outlier.method.std-dev=Standardfehler der Residuen
-
-river = Fluss
-calculation_mode = Berechnungsart
-ld_locations = Ort(e)
-main_channel = Hauptgerinne
-total_channel = Gesamtgerinne
-
-chart.cross_section.title = Querprofildiagramm f\u00fcr Gew\u00e4sser {0}
-chart.cross_section.subtitle = {0}-km: {1,number,#.###}
-chart.cross_section.xaxis.label = Abstand [m]
-chart.cross_section.yaxis.label = W [{0}]
-
-chart.longitudinal.section.title = W-L\u00e4ngsschnitt
-chart.longitudinal.section.subtitle = Bereich: {0}-km {1,number,#.###} - {2,number,#.###}
-chart.longitudinal.section.shortsubtitle = {0}
-chart.longitudinal.section.locsubtitle = {0} km {1,number,#.###}
-chart.longitudinal.section.xaxis.label = {0}-km
-chart.longitudinal.section.yaxis.label = W [{0}]
-chart.longitudinal.section.yaxis.second.label = Q [m\u00b3/s]
-chart.longitudinal.annotations.label = {0}.km
-chart.discharge.curve.title = Abflusskurve
-chart.discharge.curve.xaxis.label = Q [m\u00b3/s]
-chart.discharge.curve.yaxis.label = W [{0}]
-chart.discharge.curve.yaxis.cm.label = W [cm]
-chart.discharge.curve.curve.valid.from = {0} (g\u00fcltig ab {1,date,medium})
-chart.discharge.curve.curve.valid.range = {0} (g\u00fcltig ab {1,date,medium} - {2,date,medium})
-chart.computed.discharge.curve.title = Abflusskurve
-chart.discharge.curve.subtitle = {0}-km: $KM
-chart.discharge.curve.model = Modell-Abflusskurve {0} {1,date,medium} - {2,date,medium}
-chart.discharge.curve.model.nostop = Modell-Abflusskurve {0} {1,date,medium} -
-chart.computed.discharge.curve.yaxis.label = W [{0}]
-chart.computed.discharge.curve.curve.label = Abflusskurve {0} km {1}
-chart.duration.curve.title = Dauerlinie
-chart.duration.curve.subtitle = {0}-km: {1,number,#.###}
-chart.duration.curve.xaxis.label = Unterschreitungsdauer [Tage]
-chart.duration.curve.yaxis.label.w = W [{0}]
-chart.duration.curve.yaxis.label.q = Q [m\u00b3/s]
-chart.duration.curve.curve.w = Wasserstandsdauerline f\u00fcr {0} (km:{1})
-chart.duration.curve.curve.q = Abflussdauerline f\u00fcr {0} (km:{1})
-chart.historical.discharge.title = Historische Abflusskurven
-chart.historical.discharge.subtitle = Pegel {0} {1,date,medium} - {2,date,medium}
-chart.historical.discharge.xaxis.label = Zeit
-chart.historical.discharge.yaxis.second.label = Q [m\u00b3/s]
-chart.historical.discharge.yaxis.label = W [cm]
-chart.historical.discharge.wq.title = Abflusskurven
-chart.historical.discharge.wq.xaxis.label = Q [m\u00b3/s]
-chart.historical.discharge.wq.yaxis.label = W [cm]
-
-chart.reference.curve.title = Bezugslinie
-chart.reference.curve.subtitle = {0}
-
-chart.reference.curve.x.axis.in.cm = Bezugspegel [cm]
-chart.reference.curve.x.axis.in.m = Bezugsort [NN + m]
-chart.reference.curve.y.axis.in.cm = Zielpegel [cm]
-chart.reference.curve.y.axis.in.m = Zielort(e) [NN + m]
-
-chart.fixings.derivedcurve.title = Ableitungskurve
-chart.fixings.analysis.title = L\u00e4ngsschnitt an Kilometer {0}
-chart.fixings.wq.title = Fixierungsanalyse an Kilometer {0}
-chart.fixings.wq.yaxis.label = W [{0}]
-
-chart.extreme.wq.yaxis.label = W [{0}]
-
-chart.normalized.reference.curve.title = Reduzierte Bezugslinie
-
-chart.w_differences.title = Differenzen
-chart.w_differences.subtitle = {0}
-chart.w_differences.yaxis.label = m
-chart.w_differences.yaxis.second.label = W [NN + m]
-
-chart.bedquality.title=Sohlen L\u00e4ngsschnitt
-chart.bedquality.xaxis.label={0}-km
-chart.bedquality.yaxis.label.diameter = Durchmesser [mm]
-chart.bedquality.yaxis.label.porosity=Porosit\u00e4t [%]
-chart.bedquality.yaxis.label.density=Dichte [t/m\u00b3]
-
-chart.bedheight_middle.section.title=Mittlere Sohlh\u00f6he
-chart.bedheight_middle.section.yaxis.label=mittlere Sohlh\u00f6hen [{0}]
-chart.bedheight_middle.sounding.yaxis.label=Gepeilte Breite [m]
-
-meta.bedheight.year = Jahr
-meta.bedheight.type = Aufnahmeart
-meta.bedheight.cur.elevation = H\u00f6hensystem
-meta.bedheight.old.elevation = urspr\u00fcngliches H\u00f6hensystem
-meta.bedheight.range = Strecke
-meta.bedheight.location.system = Lagesystem
-meta.bedheight.evalby = Auswerter
-meta.bedheight.river.elevation = H\u00f6hensystem des Flusses
-
-chart.flow_velocity.section.title=Geschwindigkeit- und Schubspannung
-chart.flow_velocity.section.yaxis.label=Geschwindigkeit v [m/s]
-chart.flow_velocity.section.yaxis.second.label=Sohlschubspannung [N/m\u00b2]
-
-chart.sq_relation.xaxis.label = Abfluss [m\u00b3/s]
-chart.sq_relation.yaxis.label = Transport [kg/s]
-chart.sq_relation_a.title = Feinkornanteil
-chart.sq_relation_b.title = Sand (Suspensionstransport)
-chart.sq_relation_c.title = Sand (Geschiebetransport)
-chart.sq_relation_d.title = Fein- und Mittelkies
-chart.sq_relation_e.title = Grobkornanteil (> Mittelkies)
-chart.sq_relation_f.title = Geschiebetransport gesamt
-facet.sq_relation.curve = Potenziell (Geschiebedaten {0,date} - {1,date})
-facet.sq_relation.measurements = Geschiebedaten {0,date} - {1,date}
-facet.sq_relation.static_data = {0} bis {1}
-facet.sq_relation.outliers = Ausrei\u00dfer Durchgang {0}
-facet.sq_relation.outlier.curve = Potenziell Durchgang {0}
-facet.sq_relation.outlier.measurement = Geschiebedaten Durchgang {0}
-
-sedimentdensity = Sedimentdichte
-sand = Sand
-fine_middle = Feine/Mittl. Kies
-susp_sand = Susp. Sand
-susp_sand_bed = Bettb. Anteil Susp. Sand
-suspended_sediment = Schwebstoff
-coarse = Grober Kies
-total = Gesamtfracht
-
-chart.sedimentload.ls.title = Sedimentfracht
-chart.sedimentload.ls.xaxis.label = km
-chart.sedimentload.ls.yaxis.label.diff = [t/a]
-
-facet.sedimentload.prefix.offcial = Amtliche Epoche:
-facet.sedimentload.coarse = Grober Kies/Steine - {0} [{1}]
-facet.sedimentload.fine_middle = Fein/Mittlerer Kies - {0} [{1}]
-facet.sedimentload.sand = Sand - {0} [{1}]
-facet.sedimentload.susp_sand = suspendierter Sand - {0} [{1}]
-facet.sedimentload.susp_sand_bed = bettbildender Anteil suspendierter Sand - {0} [{1}]
-facet.sedimentload.suspended_sediment = Schwebstoff - {0} [{1}]
-facet.sedimentload.total = Gesamtfracht (Berechnung BfG) - {0} [{1}]
-facet.sedimentload.bed_load = Geschiebefracht (Berechnung BfG) - {0} [{1}]
-facet.sedimentload.suspended_load = Suspensionsfracht (Berechnung BfG) - {0} [{1}]
-facet.sedimentload.calc.total = Gesamtfracht (Berechnung FLYS) - {0} [{1}]
-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
-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}
-sedimentload.missing.fraction.susp_sand = Fehlende Fraktion suspendierter Sand - {0}
-sedimentload.missing.fraction.susp_sand_bed = Fehlende Fraktion bettbildender Anteil suspendierter Sand - {0}
-sedimentload.missing.fraction.suspended_sediment = Fehlende Fraktion Schwebstoff - {0}
-sedimentload.missing.fraction.total = Fehlende Fraktion Gesamtfracht - {0}
-sedimentload.missing.fraction.bed_load = Fehlende Fraktion Geschiebefracht - {0}
-sedimentload.missing.fraction.bed_load_susp_sand = Fehlende Fraktion bettbildende Fracht - {0}
-
-facet.longitudinal_section.annotations = Streckenfavoriten
-facet.discharge_curves.mainvalues.q = Q (Haupt- und Extremwerte)
-facet.discharge_curves.mainvalues.w = W (Haupt- und Extremwerte)
-facet.w_differences = {0} - {1}
-facet.w_differences.raw = {0} - {1} (Rohdaten)
-historical_discharge.mainvalues.q = Q (Haupt- und Extremwerte)
-historical_discharge.mainvalues.w = W (Haupt- und Extremwerte)
-facet.flow_velocity.model.mainchannel = Hauptgerinne {0}
-facet.flow_velocity.model.totalchannel = Gesamtgerinne {0}
-facet.flow_velocity.model.tau = Sohlschubspannung {0}
-facet.flow_velocity.model.q = Q {0}
-facet.flow_velocity.mainchannel = v Hauptgerinne bei {0}
-facet.flow_velocity.totalchannel = v Gesamtgerinne bei {0}
-facet.flow_velocity.tauchannel = Sohlschubspannung Hauptgerinne bei {0}
-facet.flow_velocity.mainchannel.raw = v Hauptgerinne bei {0} (Rohdaten)
-facet.flow_velocity.totalchannel.raw = v Gesamtgerinne bei {0} (Rohdaten)
-facet.flow_velocity.tauchannel.raw =Sohlschubspannung Hauptgerinne bei {0} (Rohdaten)
-facet.flow_velocity.discharge = Abfluss bei {0}
-facet.flow_velocity.velocity = V ({0})
-facet.flow_velocity.waterlevel = W ({0})
-facet.bedheight_middle.single = Sohlh\u00f6he {0,number,####}
-facet.bedheight_middle.epoch = Sohlh\u00f6he Epoche {0,number,####} - {1,number,####}
-facet.bedquality.bed.porosity.toplayer = Porosit\u00e4t ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.porosity.sublayer = Porosit\u00e4t ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.density.toplayer = Dichte ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.density.sublayer = Dichte ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.diameter.toplayer = {0}_Sohle ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.sublayer = {0}_Sohle ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.toplayer.data = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
-facet.bedquality.bed.diameter.sublayer.data = {0} Sohle ({1,date} - {2,date}) ({3}) - Messungen
-facet.bedquality.bed.diameter.bedload.data = {0} Geschiebe - Messungen
-facet.bedquality.bed.diameter.bedload = {0}_Geschiebe
-facet.bedquality.interpol.suffix = - interpoliert
-bedquality.toplayer = 0,0m - 0,3m
-bedquality.sublayer = 0,1m - 0,5m
-bedquality.missing.diameter.bedload = Interpolation Geschiebedurchmesser {0} auf der Berechnungsstrecke f\u00fcr {1,date} - {2,date} nicht m\u00f6glich.
-bedquality.missing.diameter.sublayer = Interpolation Sohldurchmesser {0} (0,0 m - 0,3 m) auf der Berechnungsstrecke f\u00fcr {1,date} - {2,date} nicht m\u00f6glich.
-bedquality.missing.diameter.toplayer = Interpolation Sohldurchmesser {0} (0,1 m - 0,5 m) auf der Berechnungsstrecke f\u00fcr {1,date} - {2,date} nicht m\u00f6glich.
-bedquality.missing.density.toplayer = Interpolation der Dichte (0,0 m - 0,3 m) auf der Berechnungsstrecke f\u00fcr {0,date} - {1,date} nicht m\u00f6glich.
-bedquality.missing.density.sublayer = Interpolation der Dichte (0,1 m - 0,5 m) auf der Berechnungsstrecke f\u00fcr {0,date} - {1,date} nicht m\u00f6glich.
-bedquality.missing.porosity.toplayer = Interpolation der Porosit\u00e4t (0,0 m - 0,3 m) auf der Berechnungsstrecke f\u00fcr {0,date} - {1,date} nicht m\u00f6glich.
-bedquality.missing.porosity.sublayer = Interpolation der Porosit\u00e4t (0,1 m - 0,5 m) auf der Berechnungsstrecke f\u00fcr {0,date} - {1,date} nicht m\u00f6glich.
-facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0}
-facet.bedheight.diff.year.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten)
-facet.bedheight.sounding_width = gepeilte Breite ({0})
-facet.bedheight.diff.sounding = gepeilte Breite
-facet.bedheight.diff.height1 = H\u00f6he Minuend {0}
-facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0}
-facet.bedheight.diff.morph1 = Morph. aktive Breite Minuend
-facet.bedheight.diff.morph2 = Morph. aktive Breite Subtrahend
-facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0}
-facet.bedheight.diff.height.raw = {0} (Rohdaten)
-facet.bedheight.diff.height1.raw = H\u00f6he Minuend {0} (Rohdaten)
-facet.bedheight.diff.height2.raw = H\u00f6he Subtrahend {0} (Rohdaten)
-facet.bedheight.diff.absolute.raw = Sohlh\u00f6hendifferenz/Jahr {0} (Rohdaten)
-facet.bedheight.diff.epoch = Sohlh\u00f6hendifferenz {0}
-facet.bedheight.diff.epoch.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten)
-facet.gauge_discharge_curve.river = Gew\u00e4sser
-facet.gauge_discharge_curve.reference_gauge = Pegelnummer
-facet.gauge_discharge_curve.gauge_name = Pegelname
-facet.gauge_discharge_curve.gauge_location = Pegelort
-facet.morphologic.width = Morphologische Breite
-
-facet.porosity = {0}
-
-chart.beddifference.height.title = Sohlh\u00f6hendifferenz
-chart.beddifference.height.xaxis.label = {0}-km
-chart.beddifference.height.yaxis.label = Differenz [cm/Jahr]
-chart.beddifference.epoch.title = Sohlh\u00f6hendifferenz
-chart.beddifference.xaxis.label = {0}-km
-chart.beddifference.yaxis.label.diff = Differenz [cm]
-chart.beddifference.yaxis.label.height = Absolute H\u00f6he [{0}]
-chart.beddifference.year.title = Sohlh\u00f6hendifferenz
-chart.beddifference.yaxis.label.morph = Breite [m]
-chart.beddifference.yaxis.label.heights = Absolute H\u00f6he [{0}]
-chart.subtitle.radius = Fensterbreite f\u00fcr gleitenden Mittelwert
-
-export.csv.header.km = km
-export.csv.header.year = Jahr
-
-export.waterlevel.csv.header.km = Fluss-Km
-export.waterlevel.csv.header.w = W [{0}]
-export.waterlevel.csv.header.q = Q [m\u00b3/s]
-export.waterlevel.csv.header.q.desc = Bezeichnung
-export.waterlevel.csv.header.location = Lage
-export.waterlevel.csv.header.gauge = Bezugspegel
-export.waterlevel.csv.meta.result = # Ergebnisausgabe - {0} - Wasserstand - FLYS 3
-export.waterlevel.csv.meta.creation = # Datum der Erstellung: {0}
-export.waterlevel.csv.meta.calculationbase = # Berechnungsgrundlage: {0}
-export.waterlevel.csv.meta.river = # Gew\u00e4sser: {0}
-export.waterlevel.csv.meta.range = # Ort/Bereich (km): {0} - {1}
-export.waterlevel.csv.meta.gauge = # Bezugspegel: {0}
-export.waterlevel.csv.meta.q = # Q (m\u00b3/s): {0}
-export.waterlevel.csv.meta.w = # W (NN + m): {0} - {1}
-export.waterlevel.csv.not.in.gauge.range = au\u00dferh. d. Bez.pegels
-export.computed.discharge.curve.csv.header.w = W [{0}]
-export.computed.discharge.curve.csv.header.q = Q [m\u00b3/s]
-export.duration.curve.csv.header.duration = D [Tage]
-export.duration.curve.csv.header.w = W [{0}]
-export.duration.curve.csv.header.q = Q [m\u00b3/s]
-export.discharge.longitudinal.section.csv.header.km = Fluss-Km
-export.discharge.longitudinal.section.csv.header.w = W [NN + m]
-export.discharge.longitudinal.section.csv.header.cw = W korr. [NN + m]
-export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s]
-export.discharge.curve.at.gauge.header = Abflusstafel f\u00fcr {1}/{0} ab {2} PNP[{4}] = {3}
-export.discharge.curve.at.header = Berechnete Abflusstafel f\u00fcr {0}, km {1}
-export.historical.discharge.csv.header.timerange = Zeitraum
-export.historical.discharge.csv.header.waterlevel = Wasserstand [cm]
-export.historical.discharge.csv.header.discharge = Abfluss [m\u00b3/s]
-export.historical.discharge.csv.header.diff.q = \u0394Q zur Bezugskurve[m\u00b3/s]
-export.historical.discharge.csv.header.diff.w = \u0394W zur Bezugskurve[m\u00b3/s]
-export.historical.discharge.csv.header.gaugename = Pegel
-export.reference_curve.csv.header.km = km
-export.reference_curve.csv.header.w.cm = W (cm am Pegel)
-export.reference_curve.csv.header.w.m = W (m + NHN)
-export.reference_curve.csv.header.w.q = gleichw. Q (m\u00b3/s)
-
-export.waterlevel.pdf.mode = Wasserstand
-export.computed.discharge.pdf.mode = Abflusskurve
-export.computed.discharge.pdf.calc.mode = Berechnete Abflusskurve
-export.duration.pdf.mode = Dauerline
-export.wdifferences.pdf.mode = W Differenzen
-export.historical.discharge.pdf.mode = Historischer Abfluss
-export.reference_curve.pdf.mode = Bezugslinie
-export.computed.discharge.pdf.file = /jasper/computed-discharge.jasper
-export.duration.pdf.file = /jasper/duration.jasper
-export.waterlevel.pdf.file = /jasper/waterlevel.jasper
-export.wdifferences.pdf.file = /jasper/wdifferences.jasper
-export.historical.discharge.pdf.file = /jasper/historical-discharge.jasper
-export.reference_curve.pdf.file = /jasper/reference.jasper
-export.reference_curve.pdf.file.gauge = /jasper/reference_gauge.jasper
-export.reference_curve.pdf.file.gauge.end = /jasper/reference_gauge_end.jasper
-export.reference_curve.pdf.file.gauge.start.end = /jasper/reference_gauge_start_end.jasper
-export.flow_velocity.csv.header.km = Fluss-Km
-export.flow_velocity.csv.header.v_total = v Gesamtgerinne [m/s]
-export.flow_velocity.csv.header.v_main = v Hauptgerinne [m/s]
-export.flow_velocity.csv.header.tau_main = Sohlschubspannung Hauptgerinne [N/m\u00b2]
-export.flow_velocity.csv.header.q = Q [m\u00b3/s]
-export.flow_velocity.csv.header.locations = Streckendaten
-export.bedheight_middle.csv.header.km = Fluss-km
-export.bedheight_middle.csv.header.sounding = Peilung / Epoche
-export.bedheight_middle.csv.header.height = gemittelte Sohlh\u00f6he [{0}]
-export.bedheight_middle.csv.header.uncertainty = Unsicherheit [m]
-export.bedheight_middle.csv.header.datagap = Datenl\u00fccke
-export.bedheight_middle.csv.header.soundingwidth = Peilbreite [m]
-export.bedheight_middle.csv.header.locations = Streckendaten
-
-export.sedimentload.csv.header.coarse = Grober Kies/Steine [{0}]
-export.sedimentload.csv.header.fine_middle = Fein/Mittlerer Kies [{0}]
-export.sedimentload.csv.header.sand = Sand [{0}]
-export.sedimentload.csv.header.susp_sand = suspendierter Sand [{0}]
-export.sedimentload.csv.header.susp_sand_bed = bettbildender Anteil suspendierter Sand [{0}]
-export.sedimentload.csv.header.suspended_sediment = Schwebstoff [{0}]
-export.sedimentload.csv.header.total = Gesamtfracht [{0}]
-export.sedimentload.csv.header.bed_load = Geschiebefracht [{0}]
-export.sedimentload.csv.header.bed_load_susp_sand = bettbildende Fracht [{0}]
-
-export.sqrelation.csv.info.coeff.a = a: Transportkurvenkoeffizient
-export.sqrelation.csv.info.coeff.b = b: Transportkurvenexponent
-export.sqrelation.csv.info.qmax = Q max, gemessen: maximal gemessener Abfluss [m\u00b3/s]
-export.sqrelation.csv.info.stderr = Standardfehler: nat\u00fcrlicher Logarithmus der Standardabweichung
-export.sqrelation.csv.info.r2 = r^2: Bestimmtheitsma\u00df
-export.sqrelation.csv.info.ntot = n Gesamt: Anzahl Messwerte
-export.sqrelation.csv.info.noutl = n Ausrei\u00dfer: Anzahl Ausrei\u00dfer
-export.sqrelation.csv.info.cferguson = CFERGUSON: Bias Korrektur nach Ferguson 1986
-export.sqrelation.csv.info.cduan = CDUAN: Bias Korrektur nach Duan 1983
-export.sqrelation.csv.info.param.a = Parameter A: Sedimenttransport von Feinkornanteil (< 0.063 mm)
-export.sqrelation.csv.info.param.b = Parameter B: Sedimenttransport von Sand (Suspensionstransort) (0.063-2 mm)
-export.sqrelation.csv.info.param.c = Parameter C: Sedimenttransport von Sand (Geschiebetransport) (0.063-2 mm)
-export.sqrelation.csv.info.param.d = Parameter D: Sedimenttransport von Fein- und Mittelkies (2-16 mm)
-export.sqrelation.csv.info.param.e = Parameter E: Sedimenttransport von Grobkornanteil (> Mittelkies)(16-125 mm)
-export.sqrelation.csv.info.param.f = Parameter F: Sedimenttransport von Geschiebtransportgesamt (0.063-125 mm)
-export.sqrelation.csv.info.q = Q: Am Messdatum gemessener Abfluss in [m\u00b3/s]
-export.sqrelation.csv.info.s_kg = S: Am Messdatum gemessener Transport in [kg/s]
-export.sqrelation.csv.info.date = Messdatum: Datum dieser Messung
-export.sqrelation.csv.header.parameter = Parameter
-export.sqrelation.csv.header.station = Station
-export.sqrelation.csv.header.km = Fluss-Km
-export.sqrelation.csv.header.function = Funktion
-export.sqrelation.csv.header.gauge = Pegel
-export.sqrelation.csv.header.coeff.a = a
-export.sqrelation.csv.header.coeff.b = b
-export.sqrelation.csv.header.coeff.q = Q
-export.sqrelation.csv.header.coeff.r = r^2
-export.sqrelation.csv.header.n.total = n Gesamt
-export.sqrelation.csv.header.n.outliers = n Ausrei\u00dfer
-export.sqrelation.csv.header.c.duan = C (Duan)
-export.sqrelation.csv.header.c.ferguson = C (Ferguson)
-export.sqrelation.csv.header.sd = Standardfehler
-export.sqrelation.csv.header.qmax = Q max, gemessen [m\u00b3/s]
-export.sqrelation.csv.header.s_kg = S [kg/s]
-export.sqrelation.csv.header.q = Q [m\u00b3/s]
-export.sqrelation.csv.header.date = Messdatum
-export.sqrelation.pdf.file = /jasper/sqrelation.jasper
-export.sqrelation.measurements.pdf.file = /jasper/sqmeasurements.jasper
-export.sqrelation.pdf.mode = Transport-Abfluss Beziehung
-export.minfo.bedquality.km = km
-export.minfo.bedquality.density.toplayer = Sedimentdichte Deckschicht [t/m\u00b3]
-export.minfo.bedquality.density.sublayer = Sedimentdichte Unterschicht [t/m\u00b3]
-export.minfo.bedquality.porosity.toplayer = Porosit\u00e4t Deckschicht [%]
-export.minfo.bedquality.porosity.sublayer = Porosit\u00e4t Unterschicht [%]
-export.minfo.bedquality.diameter.bedload = Geschiebedurchmesser [mm]
-export.minfo.bedquality.diameter.toplayer = Sohldurchmesser Deckschicht [mm]
-export.minfo.bedquality.diameter.sublayer = Sohldurchmesser Unterschicht [mm]
-export.minfo.beddifference.km = Fluss-km
-export.minfo.beddifference.diff = Sohlh\u00f6hendifferenz [cm]
-export.minfo.beddifference.diff.pair = Differenzenpaar
-export.minfo.beddifference.pdf.file = /jasper/beddifference.jasper
-export.minfo.beddifference.pdf.title = Sohlh\u00f6hendifferenz
-export.minfo.beddifference.pdf.mode = Sohlh\u00f6hendifferenz
-export.minfo.beddifference.sounding1 = gepeilte Breite Minuend [m]
-export.minfo.beddifference.sounding2 = gepeilte Breite Subtrahend [m]
-export.minfo.beddifference.gap1 = Datenl\u00fccke Minuend [%]
-export.minfo.beddifference.gap2 = Datenl\u00fccke Subtrahend [%]
-
-floodmap.wmsbackground = Hintergrundkarte
-floodmap.riveraxis = Flussachse
-floodmap.uesk = \u00dcSG: {0}-km {1,number,####} - {2,number,####} - {3}
-floodmap.barriers = Digitalisierte Objekte
-floodmap.kms = Kilometrierung
-floodmap.qps = Querprofilspuren
-floodmap.hws = Hochwasserschutzanlagen
-floodmap.hws.lines.official = HWS-Offiziell
-floodmap.hws.points.official = HWS-Offiziell (Punkte)
-floodmap.catchment = Einzugsgebiet
-floodmap.floodplain = Talaue
-floodmap.lines = Linien
-floodmap.buildings = Bauwerke
-floodmap.fixpoints = Festpunkte
-floodmap.floodmaps = \u00dcberschwemmungsfl\u00e4che
-floodmap.usershape = Benutzerdaten
-floodmap.isobath.class = {0,number,#.#} m bis {1,number,#.#} m
-floodmap.isobath.lastclass = gr\u00f6\u00dfer {0,number,#.#} m
-
-wsplgen.job.queued = WSPLGEN Berechnung befindet sich in Warteschlange.
-wsplgen.job.error = Ein unerwarteter Fehler beim Starten von WSPLGEN ist aufgetreten.
-
-official.line.found = F\u00fcr {0} existiert eine amtlich festgelegte Wasserspiegellage aus dem Jahr {1,date,yyyy} von {2}.
-
-wsp.selected.string = {0}
-
-Mosel = Mosel
-Saar = Saar
-Elbe = Elbe
-
-state.map.river = Gew\u00e4sser
-
-spline.interpolation.failed = Spline interpolation fehlgeschlagen.
-cannot.find.w.for.q = W zu Q = {0,number,#.##} kann nicht ermittelt werden.
-cannot.find.q = Q = {0,number,#.##} konnte nicht gefunden werden.
-no.ws.found = Keine Ws gefunden.
-no.q.found.in.column = In Spalte {0,integer} wurde kein Q gefunden.
-spline.creation.failed = Spline creation failed.
-cannot.find.w.or.q = W oder Q konnten nicht ermittelt werden.
-km.not.found = Passender Kilometer konnte nicht gefunden werden.
-cannot.create.wq.relation = W/Q-Beziehung konnte nicht ermittelt werden.
-cannot.create.index.q.relation = Spaltenindex/Q-Beziehung konnte nicht erstellt werden.
-
-w.w.qkm1.failed = Berechnung von Q f\u00fcr WST-Index {0,number,#.##} fehlgeschlagen.
-w.w.wkm1.failed = Berechnung von W f\u00fcr Q = {0,number,#.##} / WST-Index {1,number,#.##} fehlgeschlagen.
-w.w.qkm2.failed = Berechnung von Q f\u00fcr WST-Index {0,number,#.##} fehlgeschlagen.
-w.w.wkm2.failed = Berechnung von W f\u00fcr Q = {0,number,#.##} / WST-Index {1,number,#.##} fehlgeschlagen.
-
-hist.discharge.no.value.in.ref = {0} {1} nicht in Bezugskurve enthalten
-cannot.find.hist.q.for.w = Konnte zu W = {0,number,#.##} im Zeitraum ({1,date} - {2,date}) keinen Abfluss ermitteln.
-cannot.find.hist.w.for.q = Konnte zu Q = {0,number,#.##} im Zeitraum ({1,date} - {2,date}) keinen Wasserstand ermitteln.
-cannot.find.hist.q.tables = Konnte f\u00fcr den angegebenen Zeitraum keine Abflusstafeln finden.
-cannot.find.hist.q.reftable = Konnte f\u00fcr den gew\u00e4hlten Pegel keine Bezugs-Abflusstafel ermitteln.
-
-more.than.one.q.for.w = Mehr als ein Q f\u00fcr W = {0,number,#.##} gefunden.
-
-extreme_wq_curve = W/Q-Kurve f\u00fcr extreme Werte
-extreme_wq_base_curve = Messbasis f\u00fcr W/Q-Kurve
-
-no.river.selected = Kein Gew\u00e4sser ausgew\u00e4hlt.
-no.gauge.selected = Kein Pegel ausgew\u00e4hlt.
-no.locations.selected = Keine Orte angegeben.
-no.kms.selected = Keine Kilometerstationen angegeben.
-converting.ws.to.qs.failed = Konvertierung von Ws zu Qs fehlgeschlagen.
-no.wst.for.river = Keine zum Gew\u00e4sser passende WST gefunden.
-no.range.found = Kein passender Pegel gefunden.
-no.gauge.found.for.km = Zur gegebenen Kilometerstation {0} existiert kein Pegel.
-cannot.create.segments = Flussabschnitte konnten nicht erzeugt werden.
-cannot.compute.discharge.curve = Die Abflusskurve konnte nicht berechnet werden..
-cannot.find.ds = Dauerzahlen konnten nicht gefunden werden.
-no.segments.found = Keine Flussabschnitte gefunden.
-no.values.given = Keine Werte angegeben.
-cannot.interpolate.w.q = W/Q-Wert konnte nicht interpoliert werden.
-
-manualpoints = Manuelle Punkte
-
-no.reference.start.km = Keine Startkilometerstation angegeben.
-no.reference.end.kms = Keine Endkilometerstation(en) angegeben.
-waterlevels = Wasserst\u00e4nde
-
-help.index=${help.url}/OnlineHilfe
-help.state.winfo=${help.url}/OnlineHilfe/WINFO
-help.state.winfo.river=${help.url}/OnlineHilfe/WINFO#help.state.winfo.river
-help.state.winfo.calculation_mode=${help.url}/OnlineHilfe/WINFO#help.state.winfo.calculation_mode
-help.state.winfo.location=${help.url}/OnlineHilfe/WINFO#help.state.winfo.location
-help.state.winfo.distance_only=${help.url}/OnlineHilfe/WINFO#help.state.winfo.distance_only
-help.state.winfo.distance=${help.url}/OnlineHilfe/WINFO#help.state.winfo.distance
-help.state.winfo.location_distance=${help.url}/OnlineHilfe/WINFO#help.state.winfo.location_distance
-help.state.winfo.wq=${help.url}/OnlineHilfe/WINFO#help.state.winfo.wq
-help.state.winfo.wq_adapted=${help.url}/OnlineHilfe/WINFO#help.state.winfo.wq_adapted
-help.state.winfo.waterlevel_pair_select=${help.url}/OnlineHilfe/WINFO#help.state.winfo.waterlevel_pair_select
-help.state.winfo.reference.curve.input.start=${help.url}/OnlineHilfe/WINFO#help.state.winfo.reference.curve.input.start
-help.state.winfo.reference.curve.input.end=${help.url}/OnlineHilfe/WINFO#help.state.winfo.reference.curve.input.end
-help.state.winfo.uesk.wsp=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.wsp
-help.state.winfo.uesk.dgm=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.dgm
-help.state.winfo.uesk.profiles=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.profiles
-help.state.winfo.uesk.floodplain=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.floodplain
-help.state.winfo.uesk.differences=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.differences
-help.state.winfo.uesk.scenario=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.uesk.dc-hws=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.uesk.user-rgd=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.uesk.barriers=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.historicalq.reference_gauge=${help.url}/OnlineHilfe/WINFO#help.state.winfo.historicalq.reference_gauge
-help.state.winfo.historicalq.timerange=${help.url}/OnlineHilfe/WINFO#help.state.winfo.historicalq.timerange
-help.state.winfo.historicalq.mode=${help.url}/OnlineHilfe/WINFO#help.state.winfo.historicalq.mode
-help.state.winfo.function_select=${help.url}/OnlineHilfe/WINFO#help.state.winfo.function_select
-help.state.winfo.extreme.percent=${help.url}/OnlineHilfe/WINFO#help.state.winfo.extreme.percent
-help.state.winfo.extreme.qinput=${help.url}/OnlineHilfe/WINFO#help.state.winfo.extreme.qinput
-
-help.state.minfo.river=${help.url}/OnlineHilfe/MINFO#help.state.minfo.river
-help.state.minfo.calculation_mode=${help.url}/OnlineHilfe/MINFO#help.state.minfo.calculation_mode
-help.state.minfo.distance_only=${help.url}/OnlineHilfe/MINFO#help.state.minfo.distance_only
-help.state.minfo.distance=${help.url}/OnlineHilfe/MINFO#help.state.minfo.distance
-help.state.minfo.bed.year_epoch=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.year_epoch
-help.state.minfo.sq.location=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.location
-help.state.minfo.bed.location=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.location
-help.state.minfo.dischargestate=${help.url}/OnlineHilfe/MINFO#help.state.minfo.dischargestate
-help.state.minfo.soundings=${help.url}/OnlineHilfe/MINFO#help.state.minfo.soundings
-help.state.minfo.bed.difference_select=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.difference_select
-help.state.minfo.sq.outliermethod=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.outliermethod
-help.state.minfo.sq.outliers=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.outliers
-help.state.minfo.sediment.load.year_epoch=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.year_epoch
-help.state.minfo.sediment.load.location=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.location
-help.state.minfo.bed.periods=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.periods
-help.state.minfo.bed.char_diameter=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.char_diameter
-help.state.minfo.sediment.load.period=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.period
-help.state.minfo.sediment.load.epochs=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.epochs
-help.state.minfo.sediment.load.off_epochs=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.off_epochs
-help.state.minfo.sediment.load.unit=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.unit
-help.state.minfo.sq.period=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.period
-
-
-fix.reference.period=Bezugszeitraum
-fix.reference.period.event=Bezugsereignis
-fix.reference.period.event.short=B
-fix.analysis.short=A
-fix.analysis.periods=Analysezeitr\u00e4ume
-fix.derivative=Ableitung
-fix.outlier=Ausrei\u00dfer
-fix.analysis=Analyseereignis
-fix.deviation=Standardabweichung
-fix.reference.deviation=Standardabweichung Bezugszeitraum
-fix.vollmer.wq.curve=Angepasste Funktion
-fix.vollmer.wq.outliers=Ausrei\u00dfer
-fix.vollmer.wq.events=Ereignisse
-qsectors=Abfluss-Sektoren
-fix.mnq=um MNQ
-fix.mq=um MQ
-fix.mhq=um MHQ
-fix.hq5=um HQ5
-
-chart.fix.deltawt.title=Abweichungen von der Ausgleichskurve an Kilometer {0}
-chart.fix.deltawt.subtitle=Gew\u00e4sser: {0}; Darstellungszeitraum: {1,date,short} bis {2,date,short}; Bezugszeitraum: {3,date,short} bis {4,date,short}
-chart.fix.deltawt.xaxis.label=Datum
-chart.fix.deltawt.yaxis.label=\u0394 W(t) [cm]
-
-chart.fixings.wq.subtitle=Gew\u00e4sser: {0}; Darstellungszeitraum: {1,date,short} bis {2,date,short}; Bezugszeitraum: {3,date,short} bis {4,date,short}
-chart.fixings.wq.subtitle1={0,date,short} bis {1,date,short}
-
-
-chart.fixings.longitudinalsection.title=L\u00e4ngsschnitt
-
-chart.fixings.deltawt.title = Abweichungen von der Ausgleichskurve am Kilometer {0}
-
-export.fixings.deltawt.csv.header.km=km
-export.fixings.deltawt.csv.header.deltaw=\u0394 W [cm]
-export.fixings.deltawt.csv.header.q=Abfluss [m\u00b3/s]
-export.fixings.deltawt.csv.header.w=Wasserstand [m]
-export.fixings.deltawt.csv.header.t=Datum
-export.fixings.deltawt.csv.t.format=dd.MM.yyyy
-export.fixings.deltawt.csv.header.time.range=Status
-export.fixings.deltawt.csv.reference=B
-export.fixings.deltawt.csv.analysis=A{0,number,integer}
-
-fix.missing.river=Kein Gew\u00e4sser gew\u00e4hlt
-fix.missing.from=Kein Startkilometer gew\u00e4hlt
-fix.missing.to=Kein Endkilometer gew\u00e4hlt
-fix.missing.step=Keine Schrittweite angegeben
-fix.missing.function=Unbekannter Funktions-Typ
-fix.missing.events=Liste der Ereignisse fehlt
-fix.missing.reference.period=Kein Bezugszeitraum angegeben
-fix.missing.analysis.periods=Keine Analysezeitr\u00e4ume angegeben
-fix.missing.qstart.sector=Fehlender unterer Abflusssektor
-fix.missing.qend.sector=Fehlender oberer Abflusssektor
-fix.missing.prepocessing=Kein Information \u00fcber Aussrei\u00dfertests vorhanden
-fix.no.overview.available=Keine Daten\u00fcbersicht vorhanden
-fix.invalid.function.name=Unbekannter Funktionsname
-fix.too.less.data.colums=Zuwenig Daten f\u00fcr eine Kurvenanpassung
-fix.fitting.failed=Kurvenanpassung fehlgeschlagen
-fix.invalid.values=Ung\u00fcltige Werte
-fix.cannot.load.data=Daten konnten nicht aus der Datenbank geladen werden
-
-fix.realize.missing.is.q=Kein Q-Wert verf\u00fcgbar
-fix.realize.missing.segments=Werte f\u00fcr Pegelstrecken nicht angegeben
-fix.no.such.river=Gew\u00e4sser nicht gefunden
-fix.cannot.find.segment=Au\u00dferhalb der Pegelg\u00fcltigkeit
-fix.cannot.calculate.function=Funktionsauswerung fehlgeschlagen
-
-fix.km.chart.q.sector.border0=(MNQ + MQ)/2
-fix.km.chart.q.sector.border1=(MQ + MHQ)/2
-fix.km.chart.q.sector.border2=HQ5
-fix.km.chart.label.date=dd.MM.yyyy
-fix.km.chart.title=Fixierungen {0} km {1,number,#.###}
-fix.km.chart.q.axis=Q [m\u00b3/s]
-fix.km.chart.w.axis=W [NN + m]
-fix.km.chart.measured=gemessen
-fix.km.chart.interpolated=interpoliert
-
-fix.export.at.header = Abflusstafel aus der Fixierungsanalyse f\u00fcr {0} {0}-km: {1}
-fix.export.at.gauge.header = Abflusstafel aus der Fixierungsanalyse f\u00fcr {0}, Pegel: {1} PNP[{3}] = {2}
-sq.km.chart.label = Feststoffdaten
-sq.km.chart.title = Feststoffdatenbestand SedDB
-sq.km.chart.km.axis = km
-sq.km.chart.date.axis = Datum
-static.sq.river = Gewaesser
-static.sq.station = Messstelle
-
-module.winfo = W-INFO
-module.minfo = M-INFO
-module.fixanalysis = Fixierungsanalyse
-module.new_map = Neue Karte
-module.new_chart = Neues Diagramm
-
-load_diameter = Geschiebedurchmesser
-bed_diameter = Sohldurchmesser
-
-area.label.template = Fl\u00e4che = %s m\u00b2
-
-gauge.discharge.service.chart.title = Abflusskurven am Pegel {0}
-gauge.discharge.service.chart.x.title = Q [m\u00b3/s]
-gauge.discharge.service.chart.y.title = W [cm]
-gauge.discharge.service.chart.series.title = Abflusskurve {0,date,short} - {1,date,short}
-gauge.discharge.service.chart.series.title.master = Aktuelle Abflusskurve ab {0,date,short}
-
-bed.km.chart.label = Sohldaten
-bed.km.chart.title = Sohldatenbestand SedDB
-bedload.km.chart.label = Geschiebedaten
-bedload.km.chart.title = Geschiebedatenbestand SedDB
-
-help.state.fix.river=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.river
-help.state.fix.calculation.mode=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.calculation.mode
-help.state.fix.location=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.location
-help.state.fix.period=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.period
-help.state.fix.gaugerange=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.gaugerange
-help.state.fix.eventselect=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.eventselect
-help.state.fix.analysis.referenceperiod=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.referenceperiod
-help.state.fix.analysis.analysisperiods=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.analysisperiods
-help.state.fix.analysis.function=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.function
-help.state.fix.analysis.preprocessing=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.preprocessing
-help.state.fix.analysis.compute=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.compute
-help.state.fix.vollmer.function=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.function
-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
--- a/artifacts/src/main/resources/messages_en.properties	Fri Feb 09 15:39:49 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,764 +0,0 @@
-false=Nein
-true=Ja
-
-state.winfo.river = River
-state.winfo.calculation_mode = Calculation Mode
-state.winfo.location_distance = Location or distance selection
-state.winfo.wq = Input for W/Q data
-state.winfo.wq_adapted = Input for W/Q data
-state.winfo.location = Choose the location
-state.winfo.distance = Choose the range
-state.winfo.distance_only = Range selection
-state.winfo.uesk.wsp = Choose the waterlevel
-state.winfo.uesk.dgm = Digital Terrain Model
-state.winfo.uesk.profiles = Interpolated Profiles
-state.winfo.uesk.floodplain = Lateral Boundary
-state.winfo.uesk.differences = Differences between waterlevel and terrain
-state.winfo.uesk.scenario = Flood Plain / Scenario
-state.winfo.uesk.dc-hws = HWS
-state.winfo.uesk.user-rgd = User defined shapefiles
-state.winfo.uesk.barriers = Digitized HWS
-state.winfo.waterlevel_pair_select = Chosen Differences
-state.winfo.historicalq.reference_gauge = Selection of Gauge
-state.winfo.historicalq.timerange = Selection of Evaluation time
-state.winfo.historicalq.mode = Selecion of analyses
-state.winfo.reference.curve.input.start = Chosen Reference
-state.winfo.reference.curve.input.end = Chosen Evaluation
-state.winfo.function_select = Chosen Function
-state.winfo.extreme.percent = Distance to last extreme in percent
-state.winfo.extreme.qinput = Input of Q data
-state.fix.river = River
-state.fix.calculation.mode = Calculation Mode
-state.fix.location = Distance
-state.fix.period = Period
-state.fix.gaugerange = Gaugerange
-state.fix.eventselect = Event selection
-state.fix.analysis.referenceperiod = Reference period
-state.fix.analysis.analysisperiods = Analysis period
-state.fix.analysis.function = Function
-state.fix.analysis.preprocessing = Outliers
-state.fix.preprocess=use outlier test
-state.fix.vollmer.function=Function
-state.fix.vollmer.preprocessing = Outliers
-state.fix.vollmer.qs = Input for W/Q data
-
-state.minfo.river = River
-state.minfo.calculation_mode = Calculation Mode
-state.minfo.distance = Range selection
-state.minfo.distance_only = Range selection
-state.minfo.dischargestate = Selection of discharge state and channel
-state.minfo.sq.location=Location
-state.minfo.sq.period=Periods
-state.minfo.sq.outliers=Tolerance
-state.minfo.sq.outlier-method=Outliertest
-state.minfo.bed.year_epoch=Year/Epoch
-state.minfo.bed.difference_select=Differences
-state.minfo.year=Year
-state.minfo.epoch=Epoch
-state.minfo.bed.location = Location/Distance
-state.minfo.bed.distance = Range selection
-state.minfo.bed.periods = Periods
-state.minfo.bed.char_diameter = Characteristic Diameter
-state.minfo.bed.error.no_data = No data found for selected range.
-state.minfo.bed.error.no_data_for_period = No data found for period: {0} - {1}.
-state.minfo.soundings = Choose Soundings
-state.minfo.sediment.load.location = Range
-state.minfo.sediment.load.year_epoch = Year/Epoch
-state.minfo.sediment.load.epochs = Epochs
-state.minfo.sediment.load.period = Years
-state.minfo.sediment.load.off_epochs = off. Epochs
-state.minfo.sediment.load.unit = Unit
-state.minfo.sediment.load.t_per_a = (t/a)
-state.minfo.sediment.load.m3_per_a = (m\u00b3/a)
-state.minfo.sediment.load.sq_interval = Load-Discharge Relation
-state.minfo.off_epoch = off. Epochs
-state.minfo.t_per_a = t/a
-state.minfo.m3_per_a = m\u00b3/a
-
-year=Year
-epoch=Epoch
-off_epoch = off. Epochs
-soundings = Soundings / Epochs
-t_per_a = t/a
-m3_per_a = m\u00b3/a
-
-historical.mode.w = Waterlevel Analyse
-historical.mode.q = Discharge Analyse
-
-calc.surface.curve = Water Level/Surface Curve
-calc.flood.map = Flood Plain
-calc.discharge.curve = State Discharge Curve/Stage Discharge Relation
-calc.duration.curve = Duration Curve
-calc.discharge.longitudinal.section = W for userdefined Discharge
-calc.w.differences = Differences
-calc.historical.discharge.curve = Historical Discharge Curve
-calc.reference.curve = Reference Curve
-calc.extreme.curve = Extreme Curves
-calc.fixation.default = Fixation
-calc.fixation.vollmer = Balanced Waterlevel
-calc.bed.middle = Middle Bed Height
-calc.bed.diff = Bed Height Difference
-calc.bed.quality = Bed Quality
-calc.sediment.load = Sediment Load
-calc.flow.velocity = Flow Velocity
-calc.sq.relation = Load Discharge Relation
-calc.bed.d90 = D90
-calc.bed.d84 = D84
-calc.bed.d80 = D80
-calc.bed.d75 = D75
-calc.bed.d70 = D70
-calc.bed.d60 = D60
-calc.bed.d50 = D50
-calc.bed.d40 = D40
-calc.bed.d30 = D30
-calc.bed.d25 = D25
-calc.bed.d20 = D20
-calc.bed.d16 = D16
-calc.bed.d10 = D10
-calc.bed.dm = dm
-calc.bed.dmin = Dmin
-calc.bed.dmax = Dmax
-calc.bed.dmid = Dmid
-
-calculation.analysis = Fixinganalysis
-calculation.vollmer = relocated Waterlevel Calculation
-
-state.chart.river = River
-state.chart.type = Charttype
-state.chart.km = Kilometer
-
-chart.new.durationcurve = Duration Curve
-chart.new.computeddischargecurve = Discharge Curve
-chart.new.longitudinal_section = Longitudinal Section
-chart.new.w_differences = Differences
-chart.new.crosssection = Cross Section
-
-cross_section = Cross Section
-
-reference_curve = Reference Curve
-reference_curve_normalized = Normalized Reference Curve
-
-scenario.current = Current
-scenario.potentiel = Potentiel
-scenario.scenario = Scenario
-
-floodplain.option = Use Floodplain?
-floodplain.active = Activ
-floodplain.inactive = Inactiv
-
-outlier.method.grubbs=Grubbs
-outlier.method.std-dev=Residual standard error
-
-river = River
-calculation_mode = Calculation Mode
-ld_locations = Location(s)
-main_channel = Main channel
-total_channel = Total channel
-
-chart.cross_section.title = Cross Section for river {0}
-chart.cross_section.subtitle = {0}-km: {1,number,#.###}
-chart.cross_section.xaxis.label = Distance [m]
-chart.cross_section.yaxis.label = W [{0}]
-
-chart.longitudinal.section.title = W-Longitudinal Section
-chart.longitudinal.section.subtitle = Range: {0}-km {1,number,#.###} - {2,number,#.###}
-chart.longitudinal.section.shortsubtitle = {0}
-chart.longitudinal.section.locsubtitle = {0} km {1,number,#.###}
-chart.longitudinal.section.xaxis.label = {0}-km
-chart.longitudinal.section.yaxis.label = W [{0}]
-chart.longitudinal.section.yaxis.second.label = Q [m\u00b3/s]
-chart.longitudinal.annotations.label = {0}.km
-chart.discharge.curve.title = Discharge Curve
-chart.discharge.curve.xaxis.label = Q [m\u00b3/s]
-chart.discharge.curve.yaxis.label = W [{0}]
-chart.discharge.curve.yaxis.cm.label = W [cm]
-chart.discharge.curve.curve.valid.from = {0} (valid from {1,date,short})
-chart.discharge.curve.curve.valid.range = {0} (valid from {1,date,short} - {2,date,short})
-chart.computed.discharge.curve.title = Discharge Curve
-chart.discharge.curve.subtitle = {0}-km: $KM
-chart.discharge.curve.model = Model discharge curve {0} {1,date,medium} - {2,date,medium}
-chart.discharge.curve.model.nostop = Model discharge curve {0} {1,date,medium} -
-chart.computed.discharge.curve.yaxis.label = W [{0}]
-chart.computed.discharge.curve.curve.label = Discharge Curve {0} km {1}
-chart.duration.curve.title = Duration Curve
-chart.duration.curve.subtitle = {0}-km: {1,number,#.###}
-chart.duration.curve.xaxis.label = Duration of Non-Exceedence [Days]
-chart.duration.curve.yaxis.label.w = W [{0}]
-chart.duration.curve.yaxis.label.q = Q [m\u00b3/s]
-chart.duration.curve.curve.w = Waterlevel duration curve for {0} (km: {1})
-chart.duration.curve.curve.q = Discharge duration curve for {0} (km: {1})
-chart.historical.discharge.title = Historical Discharge Curves for Gauge {0}
-chart.historical.discharge.subtitle = Gauge {0} {1,date,medium} - {2,date,medium}
-chart.historical.discharge.xaxis.label = Time
-chart.historical.discharge.yaxis.second.label = Q [m\u00b3/s]
-chart.historical.discharge.yaxis.label = W [cm]
-chart.historical.discharge.wq.title = Discharge Curves
-chart.historical.discharge.wq.xaxis.label = Q [m\u00b3/s]
-chart.historical.discharge.wq.yaxis.label = W [cm]
-
-chart.reference.curve.title = Reference Curve
-chart.reference.curve.subtitle = {0}
-
-chart.fixings.analysis.title = Longitudinal section at km {0}
-chart.fixings.wq.subtitle=River: {0}; Range: {1,date,short} to {2,date,short}; Reference period: {3,date,short} to {4,date,short}
-chart.fixings.wq.subtitle1={0,date,short} to {1,date,short}
-
-chart.fixings.derivedcurve.title = Derived curve
-chart.fixings.deltawt.title = Differences from fitted curve at km {0}
-chart.fixings.wq.title = Fixings Analysis at km {0}
-chart.fixings.wq.yaxis.label = W [{0}]
-
-chart.extreme.wq.yaxis.label = W [{0}]
-
-chart.reference.curve.x.axis.in.cm = Reference Gauge(s) [cm]
-chart.reference.curve.x.axis.in.m = Reference Station [NN + m]
-chart.reference.curve.y.axis.in.cm = Target Gauge(s) [cm]
-chart.reference.curve.y.axis.in.m = Target Station(s) [NN + m]
-
-chart.normalized.reference.curve.title = Reduced Reference Curve
-
-chart.w_differences.title = Differences
-chart.w_differences.subtitle = {0}
-chart.w_differences.yaxis.label = m
-chart.w_differences.yaxis.second.label = W [NN + m]
-
-chart.bedquality.title=Bed Longitudinal Section
-chart.bedquality.xaxis.label={0}-km
-chart.bedquality.yaxis.label.diameter = Diameter [mm]
-chart.bedquality.yaxis.label.porosity=Porosity [%]
-chart.bedquality.yaxis.label.density=Density [t/m\u00b3]
-
-chart.bedheight_middle.section.title=Middle Bed Height
-chart.bedheight_middle.section.yaxis.label=middle Bed Height [{0}]
-chart.bedheight_middle.sounding.yaxis.label=Sounding Width [m]
-
-meta.bedheight.year = Year
-meta.bedheight.type = Type
-meta.bedheight.cur.elevation = Current elevation model
-meta.bedheight.old.elevation = Old elevation model
-meta.bedheight.range = Range
-meta.bedheight.location.system = Location system
-meta.bedheight.evalby = Evaluated by
-meta.bedheight.river.elevation = River elevation model
-
-chart.flow_velocity.section.title=Geschwindigkeit- und Schubspannung
-chart.flow_velocity.section.yaxis.label=Speed v [m/s]
-chart.flow_velocity.section.yaxis.second.label=Bottom shear stress [N/m\u00b2]
-
-chart.sq_relation.xaxis.label = Discharge [m\u00b3/s]
-chart.sq_relation.yaxis.label = Transport [kg/s]
-chart.sq_relation_a.title = Fine material
-chart.sq_relation_b.title = Sand (suspended)
-chart.sq_relation_c.title = Sand (bed load)
-chart.sq_relation_d.title = Fine/middle gravel
-chart.sq_relation_e.title = Coarse gravel
-chart.sq_relation_f.title = Total bed load
-facet.sq_relation.curve = Potential (bed load {0,date} - {1,date})
-facet.sq_relation.measurements = Bed load {0,date} - {1,date}
-facet.sq_relation.static_data = {0} to {1}
-facet.sq_relation.outliers = Outliers pass {0}
-facet.sq_relation.outlier.curve = Potential pass {0}
-facet.sq_relation.outlier.measurement = bed load data pass {0}
-
-sedimentdensity = sediment density
-coarse = Coarse gravel
-sand = Sand
-fine_middle = Fine/Mid. gravel
-susp_sand = Susp. Sand
-susp_sand_bed = Bed. part Susp.Sand
-suspended_sediment = Sediment
-total = Total load
-
-chart.sedimentload.ls.title = Sediment load
-chart.sedimentload.ls.xaxis.label = km
-chart.sedimentload.ls.yaxis.label.diff = [t/a]
-
-facet.sedimentload.prefix.offcial = Official epoch :
-facet.sedimentload.coarse = Coarse gravel - {0} [{1}]
-facet.sedimentload.fine_middle = Fine/Mid. gravel - {0} [{1}]
-facet.sedimentload.sand = Sand - {0} [{1}]
-facet.sedimentload.susp_sand = Suspended sand - {0} [{1}]
-facet.sedimentload.susp_sand_bed = Bed. part suspended sand - {0} [{1}]
-facet.sedimentload.suspended_sediment = Suspended sediment - {0} [{1}]
-facet.sedimentload.total = Total load (from database) - {0} [{1}]
-facet.sedimentload.bed_load = Bed load (from database) - {0} [{1}]
-facet.sedimentload.suspended_load = Suspended load (from database) - {0} [{1}]
-facet.sedimentload.calc.total = Total load (calculated) - {0} [{1}]
-facet.sedimentload.calc.bed_load = Bed load (calculated) - {0} [{1}]
-facet.sedimentload.calc.bed_load_susp_sand = Bed building load (calculated) - {0} [{1}]
-
-minfo.sedimentload.no.data = No sediment load data available
-sedimentload.missing.fraction.coarse = Missing fraction coarse gravel - {0}
-sedimentload.missing.fraction.fine_middle = Missing fraction fine/mid. gravel - {0}
-sedimentload.missing.fraction.sand = Missing fraction sand - {0}
-sedimentload.missing.fraction.susp_sand = Missing fraction suspended sand - {0}
-sedimentload.missing.fraction.susp_sand_bed = Missing fraction bed. part suspended sand - {0}
-sedimentload.missing.fraction.suspended_sediment = Missing fraction suspended sediment - {0}
-sedimentload.missing.fraction.total = Missing fraction total load - {0}
-sedimentload.missing.fraction.bed_load = Missing fraction bed load - {0}
-sedimentload.missing.fraction.bed_load_susp_sand = Missing fraction bed building load - {0}
-
-facet.longitudinal_section.annotations = POIs
-facet.discharge_curves.mainvalues.q = Q (main values)
-facet.discharge_curves.mainvalues.w = W (main values)
-facet.w_differences = {0} - {1}
-facet.w_differences.raw = {0} - {1} (raw)
-historical_discharge.mainvalues.q = Q Main Values
-historical_discharge.mainvalues.w = W Main Values
-facet.flow_velocity.model.mainchannel = Mainchannel {0}
-facet.flow_velocity.model.totalchannel = Totalchannel {0}
-facet.flow_velocity.model.tau = Bottom shear stress {0}
-facet.flow_velocity.model.q = Q {0}
-facet.flow_velocity.mainchannel = v Mainchannel at {0}
-facet.flow_velocity.discharge = Discharge at {0}
-facet.flow_velocity.totalchannel = v Totalchannel at {0}
-facet.flow_velocity.tauchannel = Bottom shear stress Mainchannel at {0}
-facet.flow_velocity.mainchannel.raw = v Mainchannel at {0} (raw)
-facet.flow_velocity.totalchannel.raw = v Totalchannel at {0} (raw)
-facet.flow_velocity.tauchannel.raw = Bottom shear stress Mainchannel at {0} (raw)
-facet.flow_velocity.velocity = V {0}
-facet.flow_velocity.waterlevel = Waterlevel {0}
-facet.bedheight_middle.single = Bed Height {0,number,####}
-facet.bedheight_middle.epoch = Bed Height Epoch {0,number,####} - {1,number,####}
-facet.bedquality.bed.porosity.toplayer = Porosity ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.porosity.sublayer = Porosity ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.density.toplayer = Density ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.density.sublayer = Density ({0,date} - {1,date}) ({2})
-facet.bedquality.bed.diameter.toplayer = {0}_Bed ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.sublayer = {0}_Bed ({1,date} - {2,date}) ({3})
-facet.bedquality.bed.diameter.toplayer.data = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
-facet.bedquality.bed.diameter.sublayer.data = {0} Bed ({1,date} - {2,date}) ({3}) - measurements
-facet.bedquality.bed.diameter.bedload.data = {0} Bedload - measurements
-facet.bedquality.bed.diameter.bedload = {0}_Bedload
-facet.bedquality.interpol.suffix = - interpolated
-bedquality.toplayer = 0.0m - 0.3m
-bedquality.sublayer = 0.1m - 0.5m
-bedquality.missing.diameter.bedload = Interpolating bedload diameter {0} on this range in {1,date} - {2,date} not possible.
-bedquality.missing.diameter.sublayer = Interpolating bed diameter {0} (0.0 m - 0.3 m) on this range in {1,date} - {2,date} not possible.
-bedquality.missing.diameter.toplayer = Interpolating bed diameter {0} (0.1 m - 0.5 m) on this range in {1,date} - {2,date} not possible.
-bedquality.missing.density.toplayer = Interpolating density (0.0 m - 0.3 m) on this range in {1,date} - {2,date} not possible.
-bedquality.missing.density.sublayer = Interpolating density (0.1 m - 0.5 m) on this range in {1,date} - {2,date} not possible.
-bedquality.missing.porosity.toplayer = Interpolating porosity (0.0 m - 0.3 m) on this range in {1,date} - {2,date} not possible.
-bedquality.missing.porosity.sublayer = Interpolating porosity (0.1 m - 0.5 m) on this range in {1,date} - {2,date} not possible.
-facet.bedheight.diff.year = Bedheight Difference {0}
-facet.bedheight.sounding_width = Sounding Width ({0})
-facet.bedheight.diff.sounding = sounding Width
-facet.bedheight.diff.height1 = Original Height Minuend {0}
-facet.bedheight.diff.height2 = Original Height Subtrahend {0}
-facet.bedheight.diff.morph1 = Morph. active width minuend
-facet.bedheight.diff.morph2 = Morph. active width subtrahend
-facet.bedheight.diff.absolute = Bedheight Difference/Year {0}
-facet.bedheight.diff.epoch = Bedheight Difference {0}
-facet.bedheight.diff.year.raw = Bedheight Difference {0} (raw)
-facet.bedheight.diff.height.raw = {0} (raw)
-facet.bedheight.diff.height1.raw = Original Height Minuend {0} (raw)
-facet.bedheight.diff.height2.raw = Original Height Subtrahend {0} (raw)
-facet.bedheight.diff.absolute.raw = Bedheight Difference/Year {0} (raw)
-facet.bedheight.diff.epoch.raw = BedHeight Difference {0} (raw)
-facet.gauge_discharge_curve.river = Name of the river
-facet.gauge_discharge_curve.reference_gauge = Gauge official number
-facet.gauge_discharge_curve.gauge_name = Name of the gauge
-facet.gauge_discharge_curve.gauge_location = Location of the gauge
-facet.morphologic.width = morphologic Width
-
-facet.porosity = {0}
-
-chart.beddifference.height.title = Bedheight Difference
-chart.beddifference.height.xaxis.label = {0}-km
-chart.beddifference.height.yaxis.label = Difference [cm/year]
-chart.beddifference.epoch.title = Bedheight Difference
-chart.beddifference.xaxis.label = {0}-km
-chart.beddifference.yaxis.label.diff = Difference [cm]
-chart.beddifference.yaxis.label.height = Absolute Height [m]
-chart.beddifference.year.title = Bedheight Difference
-chart.beddifference.yaxis.label.morph = Width [m]
-chart.beddifference.yaxis.label.heights = Absolute Height [m]
-chart.subtitle.radius = Width of sample window for moving average
-
-export.csv.header.km = km
-export.csv.header.year = year
-
-export.waterlevel.csv.header.km = River-Km
-export.waterlevel.csv.header.w = W [{0}]
-export.waterlevel.csv.header.q = Q [m\u00b3/s]
-export.waterlevel.csv.header.q.desc = Description
-export.waterlevel.csv.header.location = Location
-export.waterlevel.csv.header.gauge = Reference Gauge
-export.waterlevel.csv.meta.result = # Calculation Output - {0} - Waterlevel - FLYS 3
-export.waterlevel.csv.meta.creation = # Time of creation: {0}
-export.waterlevel.csv.meta.calculationbase = # Calculation base: {0}
-export.waterlevel.csv.meta.river = # River: {0}
-export.waterlevel.csv.meta.range = # Location/Range (km): {0} - {1}
-export.waterlevel.csv.meta.gauge = # Gauge: {0}
-export.waterlevel.csv.meta.q = # Q (m\u00b3/s): {0}
-export.waterlevel.csv.meta.w = # W (NN + m): {0} - {1}
-export.waterlevel.csv.not.in.gauge.range = Outside selected gauge
-export.computed.discharge.curve.csv.header.w = W [{0}]
-export.computed.discharge.curve.csv.header.q = Q [m\u00b3/s]
-export.duration.curve.csv.header.duration = D [Days]
-export.duration.curve.csv.header.w = W [{0}]
-export.duration.curve.csv.header.q = Q [m\u00b3/s]
-export.discharge.longitudinal.section.csv.header.km = River-Km
-export.discharge.longitudinal.section.csv.header.w = W [NN + m]
-export.discharge.longitudinal.section.csv.header.cw = W corr. [NN + m]
-export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s]
-export.discharge.curve.at.header = Computed discharge curve for {0} {0}-km: {1}
-export.discharge.curve.at.gauge.header = Dischargetable for {1}/{0} since {2} datum[{4}] = {3}
-export.historical.discharge.csv.header.timerange = Timerange
-export.historical.discharge.csv.header.waterlevel = Waterlevel [cm]
-export.historical.discharge.csv.header.discharge = Discharge [m\u00b3/s]
-export.historical.discharge.csv.header.diff.q = \u0394Q to reference[m\u00b3/s]
-export.historical.discharge.csv.header.diff.w = \u0394W to reference[m\u00b3/s]
-export.historical.discharge.csv.header.gaugename = Gauge
-export.reference_curve.csv.header.km = km
-export.reference_curve.csv.header.w.cm = W (cm at Gauge)
-export.reference_curve.csv.header.w.m = W (m + NHN)
-export.reference_curve.csv.header.w.q = equiv. Q (m\u00b3/s)
-
-export.waterlevel.pdf.mode = Waterlevel
-export.computed.discharge.pdf.mode = Dischargecurve
-export.computed.discharge.pdf.calc.mode = Computed Dischargecurve
-export.duration.pdf.mode = Durationcurve
-export.wdifferences.pdf.mode = W Differences
-export.historical.discharge.pdf.mode = Historical Discharge
-export.reference_curve.pdf.mode = Reference Curve
-export.computed.discharge.pdf.file = /jasper/computed-discharge_en.jasper
-export.duration.pdf.file = /jasper/duration_en.jasper
-export.waterlevel.pdf.file = /jasper/waterlevel_en.jasper
-export.wdifferences.pdf.file = /jasper/wdifferences_en.jasper
-export.historical.discharge.pdf.file = /jasper/historical-discharge_en.jasper
-export.reference_curve.pdf.file = /jasper/reference_en.jasper
-export.reference_curve.pdf.file.gauge = /jasper/reference_en_gauge.jasper
-export.reference_curve.pdf.file.gauge.end = /jasper/reference_en_gauge_end.jasper
-export.reference_curve.pdf.file.gauge.start.end = /jasper/reference_en_gauge_start_end.jasper
-export.flow_velocity.csv.header.km = River Km
-export.flow_velocity.csv.header.v_total = v Total Channel
-export.flow_velocity.csv.header.v_main = v Main Channel
-export.flow_velocity.csv.header.tau_main = Bottom shear stress Main Channel
-export.flow_velocity.csv.header.q = Q [m\u00b3/s]
-export.flow_velocity.csv.header.locations = Location
-export.bedheight_middle.csv.header.km = River km
-export.bedheight_middle.csv.header.sounding = Sounding / Epoch
-export.bedheight_middle.csv.header.height = middle Bed Height [{0}]
-export.bedheight_middle.csv.header.uncertainty = Uncertainty [m]
-export.bedheight_middle.csv.header.datagap = Data Gap
-export.bedheight_middle.csv.header.soundingwidth = Sounding Width [m]
-export.bedheight_middle.csv.header.locations = Location
-
-export.sedimentload.csv.header.coarse = Coarse gravel [{0}]
-export.sedimentload.csv.header.fine_middle = Fine/Mid. gravel [{0}]
-export.sedimentload.csv.header.sand = Sand [{0}]
-export.sedimentload.csv.header.susp_sand = Suspended sand [{0}]
-export.sedimentload.csv.header.susp_sand_bed = Bed. part suspended sand [{0}]
-export.sedimentload.csv.header.suspended_sediment = Suspended sediment [{0}]
-export.sedimentload.csv.header.total = Total load [{0}]
-export.sedimentload.csv.header.bed_load = Bed load [{0}]
-export.sedimentload.csv.header.bed_load_susp_sand = Bed building load [{0}]
-
-export.sqrelation.csv.info.coeff.a = a: coefficient of transport curve
-export.sqrelation.csv.info.coeff.b = b: exponent of transport curve
-export.sqrelation.csv.info.qmax = Q max, measured: maximum measured discharge [m\u00b3/s]
-export.sqrelation.csv.info.stderr = standard error: natural logarithm of standard deviation
-export.sqrelation.csv.info.r2 = r^2: coefficient of determination
-export.sqrelation.csv.info.ntot = n total: number of measurements
-export.sqrelation.csv.info.noutl = n outliers: number of outliers
-export.sqrelation.csv.info.cferguson = CFERGUSON: bias correction (Ferguson, 1986)
-export.sqrelation.csv.info.cduan = CDUAN: bias correction (Duan, 1983)
-export.sqrelation.csv.info.param.a = Parameter A: transport of fine material (< 0.063 mm)
-export.sqrelation.csv.info.param.b = Parameter B: transport of suspended sand (0.063-2 mm)
-export.sqrelation.csv.info.param.c = Parameter C: transport of sand (0.063-2 mm)
-export.sqrelation.csv.info.param.d = Parameter D: transport of fine and medium gravel (2-16 mm)
-export.sqrelation.csv.info.param.e = Parameter E: transport of coarse gravel (> Mittelkies)(16-125 mm)
-export.sqrelation.csv.info.param.f = Parameter F: transport of bed load (0.063-125 mm)
-export.sqrelation.csv.info.q = Q: Discharge in [m\u00b3/s] as measured on measurement date
-export.sqrelation.csv.info.s_kg = S: Transport in [kg/s] as measured on measurement date
-export.sqrelation.csv.info.date = Measurement Date: The date this measurment was made
-export.sqrelation.csv.header.parameter = Parameter
-export.sqrelation.csv.header.station = Station
-export.sqrelation.csv.header.km = River-Km
-export.sqrelation.csv.header.function = Function
-export.sqrelation.csv.header.gauge = Gauge
-export.sqrelation.csv.header.coeff.a = a
-export.sqrelation.csv.header.coeff.b = b
-export.sqrelation.csv.header.coeff.q = Q
-export.sqrelation.csv.header.coeff.r = r^2
-export.sqrelation.csv.header.n.total = n total
-export.sqrelation.csv.header.n.outliers = n outliers
-export.sqrelation.csv.header.c.duan = C (Duan)
-export.sqrelation.csv.header.c.ferguson = C (Ferguson)
-export.sqrelation.csv.header.sd = Standard error
-export.sqrelation.csv.header.qmax = Q max, measured [m\u00b3/s]
-export.sqrelation.csv.header.s_kg = S [kg/s]
-export.sqrelation.csv.header.q = Q [m\u00b3/s]
-export.sqrelation.csv.header.date = Measurement date
-export.sqrelation.pdf.file = /jasper/sqrelation_en.jasper
-export.sqrelation.measurements.pdf.file = /jasper/sqmeasurements_en.jasper
-export.sqrelation.pdf.mode = Load Discharge Relation
-export.minfo.bedquality.km = km
-export.minfo.bedquality.density.toplayer = Density Toplayer [t/m\u00b3]
-export.minfo.bedquality.density.sublayer = Density Sublayer [t/m\u00b3]
-export.minfo.bedquality.porosity.toplayer = Porosity Toplayer [%]
-export.minfo.bedquality.porosity.sublayer = Porosity Sublayer [%]
-export.minfo.bedquality.diameter.bedload = Bedload Diameter [mm]
-export.minfo.bedquality.diameter.toplayer = Bed Diameter Toplayer [mm]
-export.minfo.bedquality.diameter.sublayer = Bed Diameter Sublayer [mm]
-export.minfo.beddifference.km = km
-export.minfo.beddifference.diff = Bedheight Difference [cm]
-export.minfo.beddifference.diff.pair = Difference pair
-export.minfo.beddifference.pdf.file = /jasper/beddifference_en.jasper
-export.minfo.beddifference.pdf.title = Bedheight Difference
-export.minfo.beddifference.pdf.mode = Bedheight Difference
-export.minfo.beddifference.sounding1 = Sounding width minuend [m]
-export.minfo.beddifference.sounding2 = Sounding width subtrahend [m]
-export.minfo.beddifference.gap1 = Data gap minuend [%]
-export.minfo.beddifference.gap2 = Data gap subtrahend [%]
-
-floodmap.wmsbackground = Background Map
-floodmap.riveraxis = River Axis
-floodmap.uesk = Floodmap: {0}-km {1,number,####} - {2,number,####} - {3}
-floodmap.barriers = Digitized Objects
-floodmap.kms = Kilometrage
-floodmap.qps = Crosssection Tracks
-floodmap.hws = Flood Control Works
-floodmap.hws.lines.official = Official Flood Control Works
-floodmap.hws.points.official = Official Flood Control Works (points)
-floodmap.catchment = Catchment
-floodmap.floodplain = Floodplain
-floodmap.lines = Lines
-floodmap.buildings = Buildings
-floodmap.fixpoints = Fixpoints
-floodmap.floodmaps = Floodmaps
-floodmap.usershape = User data
-floodmap.isobath.class = {0,number,#.#} m to {1,number,#.#} m
-floodmap.isobath.lastclass = greater {0,number,#.#} m
-
-wsplgen.job.queued = WSPLGEN job in queue.
-wsplgen.job.error = An unexpected error while starting WSPLGEN occured.
-
-official.line.found = Found official line for {0} from year {1,date,yyyy} from {2}.
-
-wsp.selected.string = {0}
-
-Mosel = Mosel
-Saar = Saar
-Elbe = Elbe
-
-state.map.river = River
-
-spline.interpolation.failed = Spline interpolation failed.
-cannot.find.w.for.q = Cannot find W for Q = {0,number,#.##}.
-cannot.find.q = Cannot find Q = {0,number,#.##}.
-no.ws.found = No Ws found.
-no.q.found.in.column = No Q found in {0,integer} column.
-spline.creation.failed = Spline creation failed.
-cannot.find.w.or.q = Cannot find W or Q.
-km.not.found = Cannot find km.
-cannot.create.wq.relation = Cannot create W/Q relation.
-cannot.create.index.q.relation = Cannot create index/Q relation.
-
-w.w.qkm1.failed = Calculating Q for WST index {0,number,#.##} failed.
-w.w.wkm1.failed = Calculating W for Q = {0,number,#.##} /  WST index {1,number,#.##} failed.
-w.w.qkm2.failed = Calculating Q for WST index {0,number,#.##} failed.
-w.w.wkm2.failed = Calculating W for Q = {0,number,#.##} /  WST index {1,number,#.##} failed.
-
-hist.discharge.no.value.in.ref = {0} {1} not in reference table
-cannot.find.hist.q.for.w = Cannot find Q for W = {0,number,#.##} in timerange {1, date} - {2, date}
-cannot.find.hist.w.for.q = Cannot find W for Q = {0,number,#.##} in timerange {1, date} - {2, date}
-cannot.find.hist.q.tables = Cannot find Discharge Tables for given timerange.
-cannot.find.hist.q.reftable = Cannot find reference Discharge Table for specified Gauge.
-
-more.than.one.q.for.w = Found more Qs for W = {0,number,#.##}.
-
-extreme_wq_curve = Curve for extreme WQ
-extreme_wq_base_curve = Measurement basis for extreme WQ
-
-no.river.selected = No river selected.
-no.gauge.selected = No gauge selected.
-no.locations.selected = No locations selected.
-no.kms.selected = No KMs selected.
-converting.ws.to.qs.failed = Converting Ws to Qs failed.
-no.wst.for.river = No WST found for selected river.
-no.range.found = No range found.
-no.gauge.found.for.km = No gauge found for KM {0}.
-cannot.create.segments = Cannot create segments.
-cannot.compute.discharge.curve = Cannot create discharge curve.
-cannot.find.ds = Cannot find Ds.
-no.segments.found = No segments found.
-no.values.given = No values given.
-cannot.interpolate.w.q = Cannot interpolate W/Q.
-
-manualpoints = Manual Points
-
-no.reference.start.km = No reference start station given.
-no.reference.end.kms = No reference end station(s) given.
-waterlevels = Waterlevels
-
-help.index=${help.url}/OnlineHilfe
-help.state.winfo=${help.url}/OnlineHilfe/WINFO
-help.state.winfo.river=${help.url}/OnlineHilfe/WINFO#help.state.winfo.river
-help.state.winfo.calculation_mode=${help.url}/OnlineHilfe/WINFO#help.state.winfo.calculation_mode
-help.state.winfo.location=${help.url}/OnlineHilfe/WINFO#help.state.winfo.location
-help.state.winfo.distance_only=${help.url}/OnlineHilfe/WINFO#help.state.winfo.distance_only
-help.state.winfo.distance=${help.url}/OnlineHilfe/WINFO#help.state.winfo.distance
-help.state.winfo.location_distance=${help.url}/OnlineHilfe/WINFO#help.state.winfo.location_distance
-help.state.winfo.wq=${help.url}/OnlineHilfe/WINFO#help.state.winfo.wq
-help.state.winfo.wq_adapted=${help.url}/OnlineHilfe/WINFO#help.state.winfo.wq_adapted
-help.state.winfo.waterlevel_pair_select=${help.url}/OnlineHilfe/WINFO#help.state.winfo.waterlevel_pair_select
-help.state.winfo.reference.curve.input.start=${help.url}/OnlineHilfe/WINFO#help.state.winfo.reference.curve.input.start
-help.state.winfo.reference.curve.input.end=${help.url}/OnlineHilfe/WINFO#help.state.winfo.reference.curve.input.end
-help.state.winfo.uesk.wsp=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.wsp
-help.state.winfo.uesk.dgm=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.dgm
-help.state.winfo.uesk.profiles=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.profiles
-help.state.winfo.uesk.floodplain=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.floodplain
-help.state.winfo.uesk.differences=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.differences
-help.state.winfo.uesk.scenario=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.uesk.dc-hws=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.uesk.user-rgd=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.uesk.barriers=${help.url}/OnlineHilfe/WINFO#help.state.winfo.uesk.scenario
-help.state.winfo.historicalq.reference_gauge=${help.url}/OnlineHilfe/WINFO#help.state.winfo.historicalq.reference_gauge
-help.state.winfo.historicalq.timerange=${help.url}/OnlineHilfe/WINFO#help.state.winfo.historicalq.timerange
-help.state.winfo.historicalq.mode=${help.url}/OnlineHilfe/WINFO#help.state.winfo.historicalq.mode
-help.state.winfo.function_select=${help.url}/OnlineHilfe/WINFO#help.state.winfo.function_select
-help.state.winfo.extreme.percent=${help.url}/OnlineHilfe/WINFO#help.state.winfo.extreme.percent
-help.state.winfo.extreme.qinput=${help.url}/OnlineHilfe/WINFO#help.state.winfo.extreme.qinput
-
-help.state.minfo.river=${help.url}/OnlineHilfe/MINFO#help.state.minfo.river
-help.state.minfo.calculation_mode=${help.url}/OnlineHilfe/MINFO#help.state.minfo.calculation_mode
-help.state.minfo.distance_only=${help.url}/OnlineHilfe/MINFO#help.state.minfo.distance_only
-help.state.minfo.distance=${help.url}/OnlineHilfe/MINFO#help.state.minfo.distance
-help.state.minfo.bed.year_epoch=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.year_epoch
-help.state.minfo.sq.location=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.location
-help.state.minfo.bed.location=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.location
-help.state.minfo.dischargestate=${help.url}/OnlineHilfe/MINFO#help.state.minfo.dischargestate
-help.state.minfo.soundings=${help.url}/OnlineHilfe/MINFO#help.state.minfo.soundings
-help.state.minfo.bed.difference_select=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.difference_select
-help.state.minfo.sq.outliermethod=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.outliermethod
-help.state.minfo.sq.outliers=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.outliers
-help.state.minfo.sediment.load.year_epoch=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.year_epoch
-help.state.minfo.sediment.load.location=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.location
-help.state.minfo.bed.periods=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.periods
-help.state.minfo.bed.char_diameter=${help.url}/OnlineHilfe/MINFO#help.state.minfo.bed.char_diameter
-help.state.minfo.sediment.load.period=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.period
-help.state.minfo.sediment.load.epochs=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.epochs
-help.state.minfo.sediment.load.off_epochs=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.off_epochs
-help.state.minfo.sediment.load.unit=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sediment.load.unit
-help.state.minfo.sq.period=${help.url}/OnlineHilfe/MINFO#help.state.minfo.sq.period
-
-
-fix.reference.period=Reference period
-fix.reference.period.event=Reference event
-fix.reference.period.event.short=R
-fix.analysis.short=A
-fix.analysis.periods=Analysis periods
-fix.derivative=Derivative
-fix.outlier=Outlier
-fix.analysis=Analysis event
-fix.deviation=Standard deviation
-fix.reference.deviation=Reference deviation
-fix.vollmer.wq.curve=Adjusted function
-fix.vollmer.wq.outliers=Outliers
-fix.vollmer.wq.events=Events
-qsectors=Discharge Sectors
-fix.mnq=arround MNQ
-fix.mq=arraound MQ
-fix.mhq=arround MHQ
-fix.hq5=over HQ5
-
-chart.fix.deltawt.title=Difference from compensating curve at kilometer {0}
-chart.fix.deltawt.subtitle=Water: {0}; Period:  {1,date,short} to {2,date,short}; Reference period: {3,date,short} bis {4,date,short}
-chart.fix.deltawt.xaxis.label=Date
-chart.fix.deltawt.yaxis.label=\u0394 W(t) [cm]
-
-
-chart.fixings.longitudinalsection.title=Longitudinal section
-
-export.fixings.deltawt.csv.header.km=km
-export.fixings.deltawt.csv.header.deltaw=\u0394 W [cm]
-export.fixings.deltawt.csv.header.q=Discharge [m\u00b3/s]
-export.fixings.deltawt.csv.header.w=Waterlevel [m]
-export.fixings.deltawt.csv.header.t=Date
-export.fixings.deltawt.csv.t.format=yyyy/MM/dd
-export.fixings.deltawt.csv.header.time.range=State
-export.fixings.deltawt.csv.reference=R
-export.fixings.deltawt.csv.analysis=A{0,number,integer}
-
-fix.missing.river=Missing river
-fix.missing.from=Missing start km
-fix.missing.to=Missing end km
-fix.missing.step="Missing step width
-fix.missing.function=Missing function type
-fix.missing.events=Missing list of events
-fix.missing.reference.period=Missing reference period
-fix.missing.analysis.periods=Missing analysis periods
-fix.missing.qstart.sector=Missing discharge start sector
-fix.missing.qend.sector=Missing discharge end sector
-fix.missing.prepocessing=Missing info about preprocessing
-fix.no.overview.available=No overview available
-fix.invalid.function.name=Name of function unknown
-fix.too.less.data.colums=Too less data columns for calculation
-fix.fitting.failed=Fitting failed
-fix.invalid.values=Invalid values
-fix.cannot.load.data=Cannot fetch data from database
-
-fix.realize.missing.is.q=No Q value found
-fix.realize.missing.segments=Missing values for gauges
-fix.no.such.river=River not found
-fix.cannot.find.segment=Outside of gauge ranges
-fix.cannot.calculate.function=Evaluation of function failed
-
-fix.km.chart.q.sector.border0=(MNQ + MQ)/2
-fix.km.chart.q.sector.border1=(MQ + MHQ)/2
-fix.km.chart.q.sector.border2=HQ5
-fix.km.chart.label.date=yyyy/MM/dd
-fix.km.chart.title=Fixings {0} km {1,number,#.###}
-fix.km.chart.q.axis=Q [m\u00b3/s]
-fix.km.chart.w.axis=W [NN + m]
-fix.km.chart.measured=measured
-fix.km.chart.interpolated=interpolated
-
-fix.export.at.header = Exported fixings discharge curve for {0} {0}-km: {1}
-fix.export.at.gauge.header = Exported fixings discharge curve for {0}, gauge: {1} datum[{3}] = {2}
-sq.km.chart.label = Measuring Points
-sq.km.chart.title = Measuring Points
-sq.km.chart.km.axis = km
-sq.km.chart.date.axis = Date
-static.sq.river = River
-static.sq.station = Station
-
-module.winfo = W-INFO
-module.minfo = M-INFO
-module.fixanalysis = Fix Analysis
-module.new_map = New Map
-module.new_chart = New Chart
-
-load_diameter = Bedload Diameter
-bed_diameter = Bed Diameter
-
-area.label.template = Area = %s m\u00b3
-
-gauge.discharge.service.chart.title = Discharge Tables at Gauge {0}
-gauge.discharge.service.chart.x.title = Q [m\u00b3/s]
-gauge.discharge.service.chart.y.title = W [cm]
-gauge.discharge.service.chart.series.title = Discharge Curve {0,date,short} - {1,date,short}
-gauge.discharge.service.chart.series.title.master = Current Discharge Curve since {0,date,short}
-
-bed.km.chart.label = Sedimentdata
-bed.km.chart.title = Sedimentdata SedDB
-bedload.km.chart.label = Geschiebedaten
-bedload.km.chart.title = Geschiebedatenbestand SedDB
-
-help.state.fix.river=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.river
-help.state.fix.calculation.mode=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.calculation.mode
-help.state.fix.location=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.location
-help.state.fix.period=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.period
-help.state.fix.gaugerange=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.gaugerange
-help.state.fix.eventselect=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.eventselect
-help.state.fix.analysis.referenceperiod=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.referenceperiod
-help.state.fix.analysis.analysisperiods=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.analysisperiods
-help.state.fix.analysis.function=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.function
-help.state.fix.analysis.preprocessing=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.preprocessing
-help.state.fix.analysis.compute=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.analysis.compute
-help.state.fix.vollmer.function=${help.url}/OnlineHilfe/Fixierungsanalyse#help.state.fix.vollmer.function
-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
--- a/backend/contrib/import_river.sh	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/contrib/import_river.sh	Fri Jul 13 11:56:22 2018 +0200
@@ -63,12 +63,13 @@
    --skip-morpho                   Skip import of morphological data
    --skip-geo                      Skip import of geographic data
    --skip-prf                      Skip import of cross section data
+   --skip-sinfo_uinfo              Skip import of S-INFO and U-INFO data
 EOF
 exit 0
 }
 
 OPTS=`getopt -o ?u:w:h:p:d:l: \
-     -l help,username:,password:,host:,port:,db-name:,log-dir:,skip-hydro,skip-morpho,skip-geo,skip-prf,postgres \
+     -l help,username:,password:,host:,port:,db-name:,log-dir:,skip-hydro,skip-morpho,skip-geo,skip-prf,skip-sinfo_uinfo,postgres \
      -n $0 -- "$@"`
 if [ $? != 0 ] ; then usage; fi
 eval set -- "$OPTS"
@@ -109,6 +110,9 @@
     "--skip-geo")
       SKIP_GEO="TRUE"
       shift;;
+    "--skip-sinfo_uinfo")
+      SKIP_SINFO_UINFO="TRUE"
+      shift;;
     "--postgres")
       POSTGRES="TRUE"
       shift;;
@@ -228,6 +232,17 @@
     -Dflys.backend.importer.skip.porosity=true \
     -Dflys.backend.importer.skip.flow.velocity=true \
     -Dflys.backend.importer.skip.bed.height=true \
+    -Dflys.backend.importer.skip.sinfo.bed_mobility=true \
+    -Dflys.backend.importer.skip.sinfo.selected_additional=true \
+    -Dflys.backend.importer.skip.sinfo.infrastructure=true \
+    -Dflys.backend.importer.skip.sinfo.channel=true \
+    -Dflys.backend.importer.skip.sinfo.collision=true \
+    -Dflys.backend.importer.skip.sinfo.daily_discharge=true \
+    -Dflys.backend.importer.skip.sinfo.tkh=true \
+    -Dflys.backend.importer.skip.sinfo.flow_depth=true \
+    -Dflys.backend.importer.skip.sinfo.depth_evolution=true \
+    -Dflys.backend.importer.skip.uinfo.salix=true \
+    -Dflys.backend.importer.skip.uinfo.vegetation=true \
     $JAR
 }
 
@@ -277,6 +292,17 @@
     -Dflys.backend.importer.skip.porosity=false \
     -Dflys.backend.importer.skip.flow.velocity=false \
     -Dflys.backend.importer.skip.bed.height=false \
+    -Dflys.backend.importer.skip.sinfo.bed_mobility=true \
+    -Dflys.backend.importer.skip.sinfo.selected_additional=true \
+    -Dflys.backend.importer.skip.sinfo.infrastructure=true \
+    -Dflys.backend.importer.skip.sinfo.channel=true \
+    -Dflys.backend.importer.skip.sinfo.collision=true \
+    -Dflys.backend.importer.skip.sinfo.daily_discharge=true \
+    -Dflys.backend.importer.skip.sinfo.tkh=true \
+    -Dflys.backend.importer.skip.sinfo.flow_depth=true \
+    -Dflys.backend.importer.skip.sinfo.depth_evolution=true \
+    -Dflys.backend.importer.skip.uinfo.salix=true \
+    -Dflys.backend.importer.skip.uinfo.vegetation=true \
     $JAR
 }
 
@@ -326,6 +352,17 @@
     -Dflys.backend.importer.skip.porosity=true \
     -Dflys.backend.importer.skip.flow.velocity=true \
     -Dflys.backend.importer.skip.bed.height=true \
+    -Dflys.backend.importer.skip.sinfo.bed_mobility=true \
+    -Dflys.backend.importer.skip.sinfo.selected_additional=true \
+    -Dflys.backend.importer.skip.sinfo.infrastructure=true \
+    -Dflys.backend.importer.skip.sinfo.channel=true \
+    -Dflys.backend.importer.skip.sinfo.collision=true \
+    -Dflys.backend.importer.skip.sinfo.daily_discharge=true \
+    -Dflys.backend.importer.skip.sinfo.tkh=true \
+    -Dflys.backend.importer.skip.sinfo.flow_depth=true \
+    -Dflys.backend.importer.skip.sinfo.depth_evolution=true \
+    -Dflys.backend.importer.skip.uinfo.salix=true \
+    -Dflys.backend.importer.skip.uinfo.vegetation=true \
     $JAR
 }
 
@@ -349,6 +386,66 @@
     > "$LOG_FILE" 2>&1
 }
 
+import_sinfo_uinfo(){
+    LOG_FILE=${LOG_DIR}/sinfo-uinfo.log
+    echo Importing S-INFO and U-INFO data.
+    echo Logging into: $LOG_FILE
+    sed -i 's!\(log4j.appender.IMPORTER.File=\).*!\1'"$LOG_FILE"'!' \
+        $LOG_DIR/log4j.properties
+    java -jar \
+    -Xmx$MIN_MEMORY \
+    -server \
+    -Dlog4j.configuration=file://$LOG_DIR/log4j.properties \
+    -Dflys.backend.user=$DBUSER \
+    -Dflys.backend.password=$DBPASS \
+    -Dflys.backend.url=$BACKEND_URL \
+    -Dflys.backend.driver=$BACKEND_DB_DRIVER \
+    -Dflys.backend.dialect=$BACKEND_DB_DIALECT \
+    -Dflys.backend.importer.infogew.file="$GEW_FILE" \
+    -Dflys.backend.main.value.types=$IMPORTER_MAINVALUE_TYPES \
+    -Dflys.backend.importer.annotation.types=$IMPORTER_ANNOTATION_TYPES \
+    -Dflys.backend.importer.dry.run=$IMPORTER_DRY_RUN \
+    -Dflys.backend.importer.skip.annotations=true \
+    -Dflys.backend.importer.skip.bwastr=true \
+    -Dflys.backend.importer.skip.extra.wsts=true \
+    -Dflys.backend.importer.skip.fixations=true \
+    -Dflys.backend.importer.skip.flood.water=true \
+    -Dflys.backend.importer.skip.flood.protection=true \
+    -Dflys.backend.importer.skip.gauges=true \
+    -Dflys.backend.importer.skip.historical.discharge.tables=true \
+    -Dflys.backend.importer.skip.hyks=true \
+    -Dflys.backend.importer.skip.official.lines=true \
+    -Dflys.backend.importer.skip.prfs=true \
+    -Dflys.backend.importer.skip.w80s=true \
+    -Dflys.backend.importer.skip.w80.csvs=true \
+    -Dflys.backend.importer.skip.da50s=true \
+    -Dflys.backend.importer.skip.da66s=true \
+    -Dflys.backend.importer.skip.wst=true \
+    -Dflys.backend.importer.skip.measurement.stations=true \
+    -Dflys.backend.importer.skip.waterlevel.differences=true \
+    -Dflys.backend.importer.skip.waterlevels=true \
+    -Dflys.backend.importer.skip.sq.relation=true \
+    -Dflys.backend.importer.skip.sediment.density=true \
+    -Dflys.backend.importer.skip.sediment.load=true \
+    -Dflys.backend.importer.skip.sediment.load.ls=true \
+    -Dflys.backend.importer.skip.morphological.width=true \
+    -Dflys.backend.importer.skip.porosity=true \
+    -Dflys.backend.importer.skip.flow.velocity=true \
+    -Dflys.backend.importer.skip.bed.height=true \
+    -Dflys.backend.importer.skip.sinfo.bed_mobility=false \
+    -Dflys.backend.importer.skip.sinfo.selected_additional=false \
+    -Dflys.backend.importer.skip.sinfo.infrastructure=false \
+    -Dflys.backend.importer.skip.sinfo.channel=false \
+    -Dflys.backend.importer.skip.sinfo.collision=false \
+    -Dflys.backend.importer.skip.sinfo.daily_discharge=false \
+    -Dflys.backend.importer.skip.sinfo.tkh=false \
+    -Dflys.backend.importer.skip.sinfo.flow_depth=false \
+    -Dflys.backend.importer.skip.sinfo.depth_evolution=false \
+    -Dflys.backend.importer.skip.uinfo.salix=false \
+    -Dflys.backend.importer.skip.uinfo.vegetation=false \
+    $JAR
+}
+
 
 if [ "$SKIP_HYDRO" != "TRUE" ]; then
 import_hydro
@@ -362,3 +459,6 @@
 if [ "$SKIP_GEO" != "TRUE" ]; then
 import_geo
 fi
+if [ "$SKIP_SINFO_UINFO" != "TRUE" ]; then
+import_sinfo_uinfo
+fi
--- a/backend/contrib/run_geo.sh	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/contrib/run_geo.sh	Fri Jul 13 11:56:22 2018 +0200
@@ -6,7 +6,7 @@
 USER=flys28
 PASS=flys28
 # Alternatively you can provide a direct connection string:
-# OGR_CONNECTION="PG:dbname=flys host=localhost port=5432 user=flys password=flys"
+# OGR_CONNECTION="PG:dbname=flys host=localhost port=63333 user=flys password=flys"
 
 # Optional
 VERBOSE=1
--- a/backend/contrib/run_hydr_morph.sh	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/contrib/run_hydr_morph.sh	Fri Jul 13 11:56:22 2018 +0200
@@ -52,6 +52,19 @@
 IMPORTER_SKIP_SQ_RELATION=false
 IMPORTER_SKIP_WATERLEVELS=false
 IMPORTER_SKIP_WATERLEVEL_DIFFERENCES=false
+
+IMPORTER_SKIP_SINFO_BED_MOBILITY=false
+IMPORTER_SKIP_SINFO_SELECTED_ADDITIONAL=false
+IMPORTER_SKIP_SINFO_INFRASTRUCTURE=false
+IMPORTER_SKIP_SINFO_CHANNEL=false
+IMPORTER_SKIP_SINFO_COLLISION=false
+IMPORTER_SKIP_SINFO_DAILY_DISCHARGE=false
+IMPORTER_SKIP_SINFO_TKH=false
+IMPORTER_SKIP_SINFO_FLOW_DEPTH=false
+IMPORTER_SKIP_SINFO_DEPTH_EVOLUTION=false
+IMPORTER_SKIP_UINFO_SALIX=false
+IMPORTER_SKIP_UINFO_VEGETATION=false
+
 #####################################################################
 
 MIN_MEMORY="8192m"
@@ -104,6 +117,17 @@
     -Dflys.backend.importer.skip.waterlevels=$IMPORTER_SKIP_WATERLEVELS \
     -Dflys.backend.importer.skip.waterlevel.differences=$IMPORTER_SKIP_WATERLEVEL_DIFFERENCES \
     -Dflys.backend.importer.skip.wst=$IMPORTER_SKIP_WST \
+    -Dflys.backend.importer.skip.sinfo.bed_mobility=$IMPORTER_SKIP_SINFO_BED_MOBILITY \
+    -Dflys.backend.importer.skip.sinfo.selected_additional=$IMPORTER_SKIP_SINFO_SELECTED_ADDITIONAL \
+    -Dflys.backend.importer.skip.sinfo.infrastructure=$IMPORTER_SKIP_SINFO_INFRASTRUCTURE \
+    -Dflys.backend.importer.skip.sinfo.channel=$IMPORTER_SKIP_SINFO_CHANNEL \
+    -Dflys.backend.importer.skip.sinfo.collision=$IMPORTER_SKIP_SINFO_COLLISION \
+    -Dflys.backend.importer.skip.sinfo.daily_discharge=$IMPORTER_SKIP_SINFO_DAILY_DISCHARGE \
+    -Dflys.backend.importer.skip.sinfo.tkh=$IMPORTER_SKIP_SINFO_TKH \
+    -Dflys.backend.importer.skip.sinfo.flow_depth=$IMPORTER_SKIP_SINFO_FLOW_DEPTH \
+    -Dflys.backend.importer.skip.sinfo.depth_evolution=$IMPORTER_SKIP_SINFO_DEPTH_EVOLUTION \
+    -Dflys.backend.importer.skip.uinfo.salix=$IMPORTER_SKIP_UINFO_SALIX \
+    -Dflys.backend.importer.skip.uinfo.vegetation=$IMPORTER_SKIP_UINFO_VEGETATION \
     -Dflys.backend.user=$BACKEND_USER \
     -Dflys.backend.password=$BACKEND_PASS \
     -Dflys.backend.url=$BACKEND_URL \
--- a/backend/doc/schema/Dockerfile	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/doc/schema/Dockerfile	Fri Jul 13 11:56:22 2018 +0200
@@ -2,7 +2,7 @@
 #
 # build with e.g. `docker build --force-rm=true -t d4e/river_db .',
 # then run with e.g.
-# `docker run --name d4eriver_db -dp 2345:5432 d4e/river_db:latest'
+# `docker run --name d4eriver_db -dp 2345:63333 d4e/river_db:latest'
 #
 
 FROM debian:jessie
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/doc/schema/oracle-drop-sinfo-uinfo.sql	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,53 @@
+SET AUTOCOMMIT ON;
+
+DROP TABLE bed_mobility CASCADE CONSTRAINTS PURGE;
+DROP TABLE bed_mobility_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE infrastructure CASCADE CONSTRAINTS PURGE;
+DROP TABLE infrastructure_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE channel CASCADE CONSTRAINTS PURGE;
+DROP TABLE channel_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE collision_type CASCADE CONSTRAINTS PURGE;
+DROP TABLE collision CASCADE CONSTRAINTS PURGE;
+DROP TABLE collision_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE tkh CASCADE CONSTRAINTS PURGE;
+DROP TABLE tkh_column CASCADE CONSTRAINTS PURGE;
+DROP TABLE tkh_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE depth_evolution CASCADE CONSTRAINTS PURGE;
+DROP TABLE depth_evolution_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE daily_discharge CASCADE CONSTRAINTS PURGE;
+DROP TABLE daily_discharge_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE salix CASCADE CONSTRAINTS PURGE;
+DROP TABLE salix_values CASCADE CONSTRAINTS PURGE;
+DROP TABLE salix_rank CASCADE CONSTRAINTS PURGE;
+DROP TABLE vegetation_type CASCADE CONSTRAINTS PURGE;
+DROP TABLE vegetation CASCADE CONSTRAINTS PURGE;
+DROP TABLE vegetation_zone CASCADE CONSTRAINTS PURGE;
+DROP TABLE flow_depth CASCADE CONSTRAINTS PURGE;
+DROP TABLE flow_depth_column CASCADE CONSTRAINTS PURGE;
+DROP TABLE flow_depth_values CASCADE CONSTRAINTS PURGE;
+
+DROP SEQUENCE BED_MOBILITY_ID_SEQ;
+DROP SEQUENCE BED_MOBILITY_VALUES_ID_SEQ;
+DROP SEQUENCE INFRASTRUCTURE_ID_SEQ;
+DROP SEQUENCE INFRASTRUCTURE_VALUES_ID_SEQ;
+DROP SEQUENCE CHANNEL_ID_SEQ;
+DROP SEQUENCE CHANNEL_VALUES_ID_SEQ;
+DROP SEQUENCE COLLISION_TYPE_ID_SEQ;
+DROP SEQUENCE COLLISION_ID_SEQ;
+DROP SEQUENCE COLLISION_VALUES_ID_SEQ;
+DROP SEQUENCE TKH_ID_SEQ;
+DROP SEQUENCE TKH_COLUMN_ID_SEQ;
+DROP SEQUENCE TKH_VALUES_ID_SEQ;
+DROP SEQUENCE DEPTH_EVOLUTION_ID_SEQ;
+DROP SEQUENCE DEPTH_EVOLUTION_VALUES_ID_SEQ;
+DROP SEQUENCE DAILY_DISCHARGE_ID_SEQ;
+DROP SEQUENCE DAILY_DISCHARGE_VALUES_ID_SEQ;
+DROP SEQUENCE SALIX_ID_SEQ;
+DROP SEQUENCE SALIX_VALUES_ID_SEQ;
+--DROP SEQUENCE SALIX_RANK_ID_SEQ;
+--DROP SEQUENCE VEGETATION_TYPE_ID_SEQ;
+DROP SEQUENCE VEGETATION_ID_SEQ;
+DROP SEQUENCE VEGETATION_ZONE_ID_SEQ;
+DROP SEQUENCE FLOW_DEPTH_ID_SEQ;
+DROP SEQUENCE FLOW_DEPTH_COLUMN_ID_SEQ;
+DROP SEQUENCE FLOW_DEPTH_VALUES_ID_SEQ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/doc/schema/oracle-sinfo-uinfo.sql	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,471 @@
+SET AUTOCOMMIT ON;
+
+
+--Add new column wsts.sinfo_selection
+
+ALTER TABLE wsts ADD (
+  sinfo_selection CHAR(1) CHECK((sinfo_selection IS NULL) OR (sinfo_selection IN ('W','Q')))
+);
+COMMENT ON COLUMN wsts.sinfo_selection IS 'Whether and how the WST series is selected within S-INFO calculation types ("W"=without-Q-group, "Q"=with-Q-group, NULL=not-selectable)' ;
+
+
+--Add new columns bed_height.sounding_width_info and bed_height.notes
+
+ALTER TABLE bed_height ADD (
+  sounding_width_info VARCHAR2(256),
+  notes VARCHAR2(256)
+);
+COMMENT ON COLUMN bed_height.sounding_width_info IS 'File header line info "ausgewertete Peilbreite"' ;
+COMMENT ON COLUMN bed_height.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+
+--Add new columns bed_height_values.min_height (Talweg) and bed_height_values.max_height (Kammlage) (same type as existing height column)
+
+ALTER TABLE bed_height_values ADD (
+  min_height FLOAT(126),
+  max_height FLOAT(126),
+  height01 FLOAT(32),
+  height02 FLOAT(32),
+  height03 FLOAT(32),
+  height04 FLOAT(32),
+  height05 FLOAT(32),
+  height06 FLOAT(32),
+  height07 FLOAT(32),
+  height08 FLOAT(32),
+  height09 FLOAT(32),
+  height10 FLOAT(32)
+);
+COMMENT ON COLUMN bed_height_values.min_height IS 'Minimum bed height (Talweg) in m' ;
+COMMENT ON COLUMN bed_height_values.max_height IS 'Maximum bed height (Kammlage) in m' ;
+COMMENT ON COLUMN bed_height_values.height01 IS 'Bed height of section 1 in m' ;
+COMMENT ON COLUMN bed_height_values.height02 IS 'Bed height of section 2 in m' ;
+COMMENT ON COLUMN bed_height_values.height03 IS 'Bed height of section 3 in m' ;
+COMMENT ON COLUMN bed_height_values.height04 IS 'Bed height of section 4 in m' ;
+COMMENT ON COLUMN bed_height_values.height05 IS 'Bed height of section 5 in m' ;
+COMMENT ON COLUMN bed_height_values.height06 IS 'Bed height of section 6 in m' ;
+COMMENT ON COLUMN bed_height_values.height07 IS 'Bed height of section 7 in m' ;
+COMMENT ON COLUMN bed_height_values.height08 IS 'Bed height of section 8 in m' ;
+COMMENT ON COLUMN bed_height_values.height09 IS 'Bed height of section 9 in m' ;
+COMMENT ON COLUMN bed_height_values.height10 IS 'Bed height of section 10 in m' ;
+
+
+--Bed mobility
+
+CREATE TABLE bed_mobility (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cBedMobilityRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    kmrange_info  VARCHAR2(32),
+    filename  VARCHAR2(256) NOT NULL,
+    notes  VARCHAR2(256)
+);
+COMMENT ON TABLE bed_mobility IS 'Longitudinal section of the bed mobility of a river' ;
+COMMENT ON COLUMN bed_mobility.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN bed_mobility.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN bed_mobility.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE BED_MOBILITY_ID_SEQ ;
+
+
+CREATE TABLE bed_mobility_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    bed_mobility_id  NUMBER(9,0) NOT NULL CONSTRAINT cBedMobilityValuesBedMobility REFERENCES bed_mobility(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    moving  NUMBER(1,0) DEFAULT 0 NOT NULL CHECK(moving IN (0,1))
+);
+COMMENT ON TABLE bed_mobility_values IS 'Bed mobility of a km' ;
+COMMENT ON COLUMN bed_mobility_values.station IS 'River km' ;
+COMMENT ON COLUMN bed_mobility_values.moving IS 'Whether the river bed at the station is moving' ;
+
+CREATE SEQUENCE BED_MOBILITY_VALUES_ID_SEQ ;
+
+
+--Infrastructure
+
+CREATE TABLE infrastructure (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cInfrastructureRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    annotation_type_id  NUMBER(38,0) NOT NULL CONSTRAINT cInfrastructureAnnotationType REFERENCES annotation_types(id),
+    year  NUMBER(4,0) CHECK((year >= 1700) AND (year <= 2199)),
+    dataprovider  VARCHAR2(256),
+    evaluation_by  VARCHAR2(256),
+    kmrange_info  VARCHAR2(32),
+    filename  VARCHAR2(256) NOT NULL,
+    notes  VARCHAR2(256)
+);
+COMMENT ON TABLE infrastructure IS 'Longitudinal section of infrastructures of a river and a type' ;
+COMMENT ON COLUMN infrastructure.year IS 'File header line info "Stand"' ;
+COMMENT ON COLUMN infrastructure.dataprovider IS 'File header line info "Datenherkunft"' ;
+COMMENT ON COLUMN infrastructure.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN infrastructure.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN infrastructure.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN infrastructure.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE INFRASTRUCTURE_ID_SEQ ;
+
+
+CREATE TABLE infrastructure_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    infrastructure_id  NUMBER(9,0) CONSTRAINT cInfrastructureValuesInfrastru REFERENCES infrastructure(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    attribute_id  NUMBER(38,0) CONSTRAINT cInfrastructureValuesAttrib REFERENCES attributes(id),
+    height  NUMBER(6,2)
+);
+COMMENT ON TABLE infrastructure_values IS 'Infrastructure at a river station' ;
+COMMENT ON COLUMN infrastructure_values.station IS 'River km' ;
+COMMENT ON COLUMN infrastructure_values.height IS 'Geodetic height of the top of the infrastructure in m' ;
+
+CREATE SEQUENCE INFRASTRUCTURE_VALUES_ID_SEQ ;
+
+
+--Channel
+
+CREATE TABLE channel (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cChannelRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    kmrange_info  VARCHAR2(32),
+    filename  VARCHAR2(256) NOT NULL,
+    notes  VARCHAR2(256),
+    year_from  NUMBER(4,0),
+    year_to  NUMBER(4,0)
+);
+COMMENT ON TABLE channel IS 'Longitudinal section of the navigable channel of a river' ;
+COMMENT ON COLUMN channel.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN channel.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN channel.notes IS 'File header line info "weitere Bemerkungen"' ;
+COMMENT ON COLUMN channel.year_from IS 'Start year of the period for which the channel values are valid, NULL when valid for the whole past';
+COMMENT ON COLUMN channel.year_to IS 'End year of the period for which the channel values are valid, NULL when unlimited';
+
+
+CREATE SEQUENCE CHANNEL_ID_SEQ ;
+
+
+CREATE TABLE channel_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    channel_id  NUMBER(9,0) CONSTRAINT cChannelValuesChannel REFERENCES channel(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    width  NUMBER(6,2),
+    depth  NUMBER(6,2)
+);
+COMMENT ON TABLE channel_values IS 'Nominal size of the navigable channel at a river station' ;
+COMMENT ON COLUMN channel_values.station IS 'River km' ;
+COMMENT ON COLUMN channel_values.width IS 'Nominal width of the channel in m' ;
+COMMENT ON COLUMN channel_values.depth IS 'Nominal depth of the channel in m' ;
+
+CREATE SEQUENCE CHANNEL_VALUES_ID_SEQ ;
+
+
+--Collision
+
+CREATE TABLE collision_type (
+    id  NUMBER(9,0) PRIMARY KEY,
+    name  VARCHAR2(64) NOT NULL UNIQUE
+);
+COMMENT ON TABLE collision_type IS 'Type of a ship collision' ;
+COMMENT ON COLUMN collision_type.name IS 'Name of the collision type' ;
+
+CREATE SEQUENCE COLLISION_TYPE_ID_SEQ ;
+
+
+CREATE TABLE collision (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cCollisionRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    year  NUMBER(4,0) NOT NULL,
+    kmrange_info  VARCHAR2(32),
+    filename  VARCHAR2(256) NOT NULL,
+    notes  VARCHAR2(256)
+);
+COMMENT ON TABLE collision IS 'Longitudinal section of ship collisions with the river bed' ;
+COMMENT ON COLUMN collision.year IS 'File header line info "Jahr"' ;
+COMMENT ON COLUMN collision.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN collision.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN collision.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE COLLISION_ID_SEQ ;
+
+
+CREATE TABLE collision_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    collision_id  NUMBER(9,0) NOT NULL CONSTRAINT cCollisionValueCollision REFERENCES collision(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    event_date  DATE NOT NULL,
+    gauge_w  NUMBER(6,2),
+    gauge_name  VARCHAR2(64),
+    collision_type_id  NUMBER(9,0) NOT NULL CONSTRAINT cCollisionValuesCollisionType REFERENCES collision_type(id)
+);
+COMMENT ON TABLE collision_values IS 'Collision event' ;
+COMMENT ON COLUMN collision_values.station IS 'River km' ;
+COMMENT ON COLUMN collision_values.event_date IS 'Date of the collision' ;
+COMMENT ON COLUMN collision_values.gauge_w IS 'Waterlevel during the collision' ;
+COMMENT ON COLUMN collision_values.gauge_name IS 'Name of the gauge' ;
+
+CREATE SEQUENCE COLLISION_VALUES_ID_SEQ ;
+
+
+--Tkh
+
+CREATE TABLE tkh (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cTkhRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    day  DATE,
+    kmrange_info  VARCHAR2(32),
+    filename  VARCHAR2(256) NOT NULL,
+    groupname  VARCHAR2(32) NOT NULL CHECK(groupname IN ('messung','berechnung')),
+    sounding_info  VARCHAR2(64),
+    evaluation_by  VARCHAR2(256),
+    notes  VARCHAR2(256)
+);
+COMMENT ON TABLE tkh IS 'Longitudinal section of computed Transportkoerperhoehe of a river' ;
+COMMENT ON COLUMN tkh.day IS 'File header line info "Datum"' ;
+COMMENT ON COLUMN tkh.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN tkh.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN tkh.groupname IS 'Group the file belongs to' ;
+COMMENT ON COLUMN tkh.sounding_info IS 'File header line info "Peilung"' ;
+COMMENT ON COLUMN tkh.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN tkh.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE TKH_ID_SEQ ;
+
+
+CREATE TABLE tkh_column (
+    id  NUMBER(9,0) PRIMARY KEY,
+    tkh_id  NUMBER(9,0) NOT NULL CONSTRAINT cTkhColumnTkh REFERENCES tkh(id) ON DELETE CASCADE,
+    name  VARCHAR2(64) NOT NULL
+);
+COMMENT ON TABLE tkh_column IS 'Longitudinal section of computed Transportkoerperhoehe for a waterlevel series' ;
+COMMENT ON COLUMN tkh_column.name IS 'Name of the tkh computation column' ;
+
+CREATE SEQUENCE TKH_COLUMN_ID_SEQ ;
+
+
+CREATE TABLE tkh_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    tkh_column_id  NUMBER(9,0) NOT NULL CONSTRAINT cTkhValuesTkhColumn REFERENCES tkh_column(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    tkheight  NUMBER(7,3)
+);
+COMMENT ON TABLE tkh_values IS 'Transportkoerperhoehe of a river station and referenced file column' ;
+COMMENT ON COLUMN tkh_values.station IS 'River km' ;
+COMMENT ON COLUMN tkh_values.tkheight IS 'Transportkoerperhoehe of a river station computed for a waterlevel in  m' ;
+
+CREATE SEQUENCE TKH_VALUES_ID_SEQ ;
+
+
+--Flow depth
+
+CREATE TABLE flow_depth (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cFlowDepthRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    year  NUMBER(4,0) NOT NULL,
+    kmrange_info  VARCHAR2(32),
+    filename  VARCHAR2(256) NOT NULL,
+    sounding_info  VARCHAR2(64),
+    evaluation_by  VARCHAR2(255),
+    notes  VARCHAR2(256)
+);
+
+COMMENT ON TABLE flow_depth IS 'Longitudinal section of computed flow depth of a river' ;
+COMMENT ON COLUMN flow_depth.year IS 'File header line info "Bezugsjahr"' ;
+COMMENT ON COLUMN flow_depth.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN flow_depth.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN flow_depth.sounding_info IS 'File header line info "Peilung"' ;
+COMMENT ON COLUMN flow_depth.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN flow_depth.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE FLOW_DEPTH_ID_SEQ ;
+
+
+CREATE TABLE flow_depth_column (
+    id  NUMBER(9,0) PRIMARY KEY,
+    flow_depth_id  NUMBER(9,0) NOT NULL CONSTRAINT cFlowDepthColumnFlowDepth REFERENCES flow_depth(id) ON DELETE CASCADE,
+    name  VARCHAR2(64) NOT NULL
+);
+
+COMMENT ON TABLE flow_depth_column IS 'Longitudinal section of computed flow depth for a waterlevel series' ;
+COMMENT ON COLUMN flow_depth_column.name IS 'Name of the flow depth computation column' ;
+
+CREATE SEQUENCE FLOW_DEPTH_COLUMN_ID_SEQ ;
+
+
+CREATE TABLE flow_depth_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    flow_depth_column_id  NUMBER(9,0) NOT NULL CONSTRAINT cFlowDepthValuesFlowDepthCol REFERENCES flow_depth_column(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    depth  NUMBER(7,3)
+);
+
+COMMENT ON TABLE flow_depth_values IS 'Flow depth of a river station and referenced file column' ;
+COMMENT ON COLUMN flow_depth_values.station IS 'River km' ;
+COMMENT ON COLUMN flow_depth_values.depth IS 'Flow depth of a river station computed for a waterlevel in  m' ;
+
+CREATE SEQUENCE FLOW_DEPTH_VALUES_ID_SEQ ;
+
+
+--Depth evolution
+
+CREATE TABLE depth_evolution (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cDepthEvolutionRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    reference_year  NUMBER(4,0) NOT NULL,
+    start_year  NUMBER(4,0) NOT NULL,
+    curr_sounding  VARCHAR2(64) NOT NULL,
+    old_sounding  VARCHAR2(64) NOT NULL,
+    kmrange_info  VARCHAR2(32),
+    curr_glw  VARCHAR2(64) NOT NULL,
+    old_glw  VARCHAR2(64) NOT NULL,
+    filename  VARCHAR2(256) NOT NULL,
+    groupname  VARCHAR2(32) NOT NULL CHECK(groupname IN ('aktuell','etappe')),
+    notes  VARCHAR2(256)
+);
+COMMENT ON TABLE depth_evolution IS 'Longitudinal section of the evolution of the flow depth of a river' ;
+COMMENT ON COLUMN depth_evolution.reference_year IS 'File header line info "Bezugsjahr" (GlW)' ;
+COMMENT ON COLUMN depth_evolution.start_year IS 'File header line info "Ausgangsjahr" (GlW)' ;
+COMMENT ON COLUMN depth_evolution.curr_sounding IS 'File header line info "Aktuelle Peilung / Epoche"' ;
+COMMENT ON COLUMN depth_evolution.old_sounding IS 'File header line info "Historische Peilung / Epoche"' ;
+COMMENT ON COLUMN depth_evolution.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN depth_evolution.curr_glw IS 'File header line info "Aktuelle Wasserspiegellage"' ;
+COMMENT ON COLUMN depth_evolution.old_glw IS 'File header line info "Historische Wasserspiegellage"' ;
+COMMENT ON COLUMN depth_evolution.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN depth_evolution.groupname IS 'Group the file belongs to' ;
+COMMENT ON COLUMN depth_evolution.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE DEPTH_EVOLUTION_ID_SEQ ;
+
+
+CREATE TABLE depth_evolution_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    depth_evolution_id  NUMBER(9,0) NOT NULL CONSTRAINT cDepthEvolutionValuesDepthEvol REFERENCES depth_evolution(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    total_change  NUMBER(8,4),
+    change_per_year  NUMBER(8,4)
+);
+COMMENT ON TABLE depth_evolution_values IS 'Evolution of the flow depth of a river station in a referenced period of time' ;
+COMMENT ON COLUMN depth_evolution_values.station IS 'River km' ;
+COMMENT ON COLUMN depth_evolution_values.total_change IS 'Flow depth change of the whole period of time in m' ;
+COMMENT ON COLUMN depth_evolution_values.change_per_year IS 'Average yearly flow depth change in the referenced period of time in m' ;
+
+CREATE SEQUENCE DEPTH_EVOLUTION_VALUES_ID_SEQ ;
+
+
+--Daily discharge
+
+CREATE TABLE daily_discharge (
+    id  NUMBER(9,0) PRIMARY KEY,
+    gauge_id  NUMBER(38,0) NOT NULL CONSTRAINT cDailyDischargeGauge REFERENCES gauges(id) ON DELETE CASCADE,
+    filename  VARCHAR2(256) NOT NULL
+);
+
+COMMENT ON TABLE daily_discharge IS 'Daily discharge value series' ;
+COMMENT ON COLUMN daily_discharge.filename IS 'Name without type extension of the imported file' ;
+
+CREATE SEQUENCE DAILY_DISCHARGE_ID_SEQ ;
+
+
+CREATE TABLE daily_discharge_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    daily_discharge_id  NUMBER(9,0) NOT NULL CONSTRAINT cDailyDischargeValueDailyDisch REFERENCES daily_discharge(id) ON DELETE CASCADE,
+    day  DATE NOT NULL,
+    discharge  NUMBER(8,3) NOT NULL
+);
+
+COMMENT ON TABLE daily_discharge_values IS 'Mean daily discharge of a date and a gauge' ;
+COMMENT ON COLUMN daily_discharge_values.day IS 'Date of the discharge value' ;
+COMMENT ON COLUMN daily_discharge_values.discharge IS 'Mean daily discharge in m^3/s' ;
+
+CREATE SEQUENCE DAILY_DISCHARGE_VALUES_ID_SEQ ;
+
+
+--Salix line
+
+CREATE TABLE salix (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cSalixRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    evaluation_by  VARCHAR2(255),
+    kmrange_info  VARCHAR2(32),
+    filename  VARCHAR2(256) NOT NULL,
+    notes  VARCHAR2(256)
+);
+
+COMMENT ON TABLE salix IS 'Longitudinal section of the salix line parameters of a river' ;
+COMMENT ON COLUMN salix.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN salix.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN salix.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN salix.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE SALIX_ID_SEQ ;
+
+
+CREATE TABLE salix_values (
+    id  NUMBER(9,0) PRIMARY KEY,
+    salix_id  NUMBER(9,0) NOT NULL CONSTRAINT cSalixValuesSalix REFERENCES salix(id) ON DELETE CASCADE,
+    station  NUMBER(7,3) NOT NULL,
+    factor  NUMBER(6,2) NOT NULL,
+    mnw_mw_diff  NUMBER(6,2)
+);
+
+COMMENT ON COLUMN salix_values.station IS 'River km' ;
+COMMENT ON COLUMN salix_values.factor IS 'Salix "factor" of the station in m' ;
+COMMENT ON COLUMN salix_values.mnw_mw_diff IS 'Difference between MNW and MW in m (less than zero)' ;
+
+CREATE SEQUENCE SALIX_VALUES_ID_SEQ ;
+
+
+CREATE TABLE salix_rank (
+    id  NUMBER(9,0) PRIMARY KEY,
+    min_value  NUMBER(6,2),
+    max_value  NUMBER(6,2),
+    name  VARCHAR2(16) NOT NULL
+);
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (1, NULL, -0.3, 'invalid');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (2, -0.3, 0.3, 'very good');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (3, 0.3, 0.5, 'good');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (4, 0.5, 1.0, 'moderate');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (5, 1.0, 1.5, 'bad');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (6, 1.5, NULL, 'very bad');
+
+
+--Vegetation zone
+
+CREATE TABLE vegetation_type (
+    id  NUMBER(9,0) PRIMARY KEY,
+    name  VARCHAR2(256) NOT NULL
+);
+INSERT INTO vegetation_type (id, name) VALUES (1, 'zonal forest');
+INSERT INTO vegetation_type (id, name) VALUES (2, 'dry hartwood forest floodplain');
+INSERT INTO vegetation_type (id, name) VALUES (3, 'wet hartwood forest floodplain');
+INSERT INTO vegetation_type (id, name) VALUES (4, 'salix alba forest');
+INSERT INTO vegetation_type (id, name) VALUES (5, 'salix shrubs');
+INSERT INTO vegetation_type (id, name) VALUES (6, 'reed bed');
+INSERT INTO vegetation_type (id, name) VALUES (7, 'bank pioneers');
+INSERT INTO vegetation_type (id, name) VALUES (8, 'no vegetation');
+INSERT INTO vegetation_type (id, name) VALUES (9, 'water');
+
+
+CREATE TABLE vegetation (
+    id  NUMBER(9,0) PRIMARY KEY,
+    river_id  NUMBER(38,0) NOT NULL CONSTRAINT cVegetationRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    name  VARCHAR2(256),
+    filename  VARCHAR2(256) NOT NULL,
+    notes  VARCHAR2(256)
+);
+
+COMMENT ON TABLE vegetation IS 'Classification of the vegetation of a river' ;
+COMMENT ON COLUMN vegetation.name IS 'File header line info "Einteilung"' ;
+COMMENT ON COLUMN vegetation.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN vegetation.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE VEGETATION_ID_SEQ ;
+
+
+CREATE TABLE vegetation_zone (
+    id  NUMBER(9,0) PRIMARY KEY,
+    vegetation_id  NUMBER(9,0) NOT NULL CONSTRAINT cVegetationZoneVegetation REFERENCES vegetation(id) ON DELETE CASCADE,
+    vegetation_type_id  NUMBER(9,0) NOT NULL CONSTRAINT cVegetationZoneVegetationType REFERENCES vegetation_type(id) ON DELETE CASCADE,
+    min_overflow_days  NUMBER(3,0) NOT NULL,
+    max_overflow_days  NUMBER(3,0) NOT NULL
+);
+
+COMMENT ON TABLE vegetation_zone IS 'Vegetation zone of a river station' ;
+COMMENT ON COLUMN vegetation_zone.min_overflow_days IS 'Minimum number (inclusive) of overflow days in a year for the zone type' ;
+COMMENT ON COLUMN vegetation_zone.max_overflow_days IS 'Maximum number (exclusive) of overflow days in a year for the zone type' ;
+
+CREATE SEQUENCE VEGETATION_ZONE_ID_SEQ ;
--- a/backend/doc/schema/postgresql-drop-spatial.sql	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/doc/schema/postgresql-drop-spatial.sql	Fri Jul 13 11:56:22 2018 +0200
@@ -1,47 +1,43 @@
 BEGIN;
 
-DROP TABLE river_axes;
+DROP TABLE axis_kinds CASCADE;
+DROP TABLE river_axes CASCADE;
 DROP SEQUENCE RIVER_AXES_ID_SEQ;
-
-DROP TABLE river_axes_km;
+DROP TABLE river_axes_km CASCADE;
 DROP SEQUENCE RIVER_AXES_KM_ID_SEQ;
-
-DROP TABLE cross_section_tracks;
+DROP TABLE cross_section_track_kinds CASCADE;
+DROP TABLE cross_section_tracks CASCADE;
 DROP SEQUENCE CROSS_SECTION_TRACKS_ID_SEQ;
-
-DROP TABLE buildings;
+DROP TABLE building_kinds CASCADE;
+DROP TABLE buildings CASCADE;
 DROP SEQUENCE BUILDINGS_ID_SEQ;
-
-DROP TABLE fixpoints;
+DROP TABLE fixpoints CASCADE;
 DROP SEQUENCE FIXPOINTS_ID_SEQ;
-
-DROP TABLE floodplain;
+DROP TABLE floodplain_kinds CASCADE;
+DROP TABLE floodplain CASCADE;
 DROP SEQUENCE FLOODPLAIN_ID_SEQ;
-
-DROP TABLE dem;
+DROP TABLE dem CASCADE;
 DROP SEQUENCE DEM_ID_SEQ;
+DROP TABLE hws_kinds CASCADE;
+DROP TABLE fed_states CASCADE;
+DROP TABLE hws_lines CASCADE;
+DROP SEQUENCE HWS_LINES_ID_SEQ;
+DROP TABLE hws_points CASCADE;
+DROP SEQUENCE HWS_POINTS_ID_SEQ;
+DROP TABLE floodmap_kinds CASCADE;
+DROP TABLE floodmaps CASCADE;
+DROP SEQUENCE FLOODMAPS_ID_SEQ;
+DROP TABLE sectie_kinds CASCADE;
+DROP TABLE sobek_kinds CASCADE;
+DROP TABLE boundary_kinds CASCADE;
+DROP TABLE hydr_boundaries CASCADE;
+DROP SEQUENCE HYDR_BOUNDARIES_ID_SEQ;
+DROP TABLE hydr_boundaries_poly CASCADE;
+DROP SEQUENCE HYDR_BOUNDARIES_POLY_ID_SEQ;
+DROP TABLE jetty_kinds CASCADE;
+DROP TABLE jetties CASCADE;
+DROP SEQUENCE JETTIES_ID_SEQ;
+DROP TABLE flood_marks CASCADE;
+DROP SEQUENCE FLOOD_MARKS_ID_SEQ;
 
-DROP TABLE hws_points;
-DROP SEQUENCE HWS_POINTS_ID_SEQ;
-
-DROP TABLE hws_lines;
-DROP SEQUENCE HWS_LINES_ID_SEQ;
-
-DROP TABLE floodmaps;
-DROP SEQUENCE FLOODMAPS_ID_SEQ;
-
-DROP TABLE hydr_boundaries;
-DROP SEQUENCE HYDR_BOUNDARIES_ID_SEQ;
-
-DROP TABLE hydr_boundaries_poly;
-DROP SEQUENCE HYDR_BOUNDARIES_POLY_ID_SEQ;
-
-DROP TABLE fed_states;
-DROP TABLE hws_kinds;
-DROP TABLE sobek_kinds;
-DROP TABLE sectie_kinds;
-DROP TABLE boundary_kinds;
-DROP TABLE axis_kinds;
-DROP TABLE building_kinds;
-
-COMMIT;
+COMMIT;
\ No newline at end of file
--- a/backend/doc/schema/postgresql-minfo.sql	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/doc/schema/postgresql-minfo.sql	Fri Jul 13 11:56:22 2018 +0200
@@ -262,6 +262,8 @@
 INSERT INTO grain_fraction VALUES (8, 'bed_load', 0.063, 200);
 INSERT INTO grain_fraction VALUES (9, 'suspended_load', 0, 2);
 
+ALTER SEQUENCE GRAIN_FRACTION_ID_SEQ RESTART WITH 10;
+
 
 --lookup table for sediment load kinds
 CREATE TABLE sediment_load_kinds (
@@ -271,6 +273,7 @@
 INSERT INTO sediment_load_kinds (id, kind) VALUES (0, 'non-official');
 INSERT INTO sediment_load_kinds (id, kind) VALUES (1, 'official');
 
+
 CREATE SEQUENCE SEDIMENT_LOAD_LS_ID_SEQ;
 
 CREATE TABLE sediment_load_ls (
--- a/backend/doc/schema/postgresql-setup.sh	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/doc/schema/postgresql-setup.sh	Fri Jul 13 11:56:22 2018 +0200
@@ -29,3 +29,4 @@
 psql -d $DB_NAME -U $DB_NAME -h $PG_HOST -f $SCRIPT_DIR/postgresql.sql
 psql -d $DB_NAME -U $DB_NAME -h $PG_HOST -f $SCRIPT_DIR/postgresql-spatial.sql
 psql -d $DB_NAME -U $DB_NAME -h $PG_HOST -f $SCRIPT_DIR/postgresql-minfo.sql
+psql -d $DB_NAME -U $DB_NAME -h $PG_HOST -f $SCRIPT_DIR/postgresql-sinfo-uinfo.sql
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/doc/schema/postgresql-sinfo-uinfo.sql	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,470 @@
+BEGIN;
+
+
+--Add new column wsts.sinfo_selection
+
+ALTER TABLE wsts ADD COLUMN sinfo_selection VARCHAR(1) CHECK((sinfo_selection IS NULL) OR (sinfo_selection IN ('W','Q')));
+COMMENT ON COLUMN wsts.sinfo_selection IS 'Whether and how the WST series is selected within S-INFO calculation types ("W"=without-Q-group, "Q"=with-Q-group, NULL=not-selectable)' ;
+
+
+--Add new columns bed_height.sounding_width_info and bed_height.comment
+
+ALTER TABLE bed_height
+  ADD sounding_width_info VARCHAR(256),
+  ADD notes VARCHAR(256);
+COMMENT ON COLUMN bed_height.sounding_width_info IS 'File header line info "ausgewertete Peilbreite"' ;
+COMMENT ON COLUMN bed_height.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+
+--Add new columns bed_height_values.min_height (Talweg) and bed_height_values.max_height (Kammlage) (same type as existing height column)
+
+ALTER TABLE bed_height_values
+  ADD min_height NUMERIC,
+  ADD max_height NUMERIC,
+  ADD height01 NUMERIC,
+  ADD height02 NUMERIC,
+  ADD height03 NUMERIC,
+  ADD height04 NUMERIC,
+  ADD height05 NUMERIC,
+  ADD height06 NUMERIC,
+  ADD height07 NUMERIC,
+  ADD height08 NUMERIC,
+  ADD height09 NUMERIC,
+  ADD height10 NUMERIC;
+COMMENT ON COLUMN bed_height_values.min_height IS 'Minimum bed height (Talweg) in m' ;
+COMMENT ON COLUMN bed_height_values.max_height IS 'Maximum bed height (Kammlage) in m' ;
+COMMENT ON COLUMN bed_height_values.height01 IS 'Bed height of section 1 in m' ;
+COMMENT ON COLUMN bed_height_values.height02 IS 'Bed height of section 2 in m' ;
+COMMENT ON COLUMN bed_height_values.height03 IS 'Bed height of section 3 in m' ;
+COMMENT ON COLUMN bed_height_values.height04 IS 'Bed height of section 4 in m' ;
+COMMENT ON COLUMN bed_height_values.height05 IS 'Bed height of section 5 in m' ;
+COMMENT ON COLUMN bed_height_values.height06 IS 'Bed height of section 6 in m' ;
+COMMENT ON COLUMN bed_height_values.height07 IS 'Bed height of section 7 in m' ;
+COMMENT ON COLUMN bed_height_values.height08 IS 'Bed height of section 8 in m' ;
+COMMENT ON COLUMN bed_height_values.height09 IS 'Bed height of section 9 in m' ;
+COMMENT ON COLUMN bed_height_values.height10 IS 'Bed height of section 10 in m' ;
+
+
+--Bed mobility
+
+CREATE TABLE bed_mobility (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cBedMobilityRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    kmrange_info  VARCHAR(32),
+    filename  VARCHAR(256) NOT NULL,
+    notes  VARCHAR(256)
+);
+COMMENT ON TABLE bed_mobility IS 'Longitudinal section of the bed mobility of a river' ;
+COMMENT ON COLUMN bed_mobility.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN bed_mobility.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN bed_mobility.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE BED_MOBILITY_ID_SEQ ;
+
+
+CREATE TABLE bed_mobility_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    bed_mobility_id  NUMERIC(9,0) NOT NULL CONSTRAINT cBedMobilityValuesBedMobility REFERENCES bed_mobility(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    moving  NUMERIC(1,0) DEFAULT 0 NOT NULL CHECK(moving IN (0,1))
+);
+COMMENT ON TABLE bed_mobility_values IS 'Bed mobility of a km' ;
+COMMENT ON COLUMN bed_mobility_values.station IS 'River km' ;
+COMMENT ON COLUMN bed_mobility_values.moving IS 'Whether the river bed at the station is moving' ;
+
+CREATE SEQUENCE BED_MOBILITY_VALUES_ID_SEQ ;
+
+
+--Infrastructure
+
+CREATE TABLE infrastructure (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cInfrastructureRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    annotation_type_id  integer NOT NULL CONSTRAINT cInfrastructureAnnotationType REFERENCES annotation_types(id),
+    year  NUMERIC(4,0) CHECK((year >= 1700) AND (year <= 2199)),
+    dataprovider  VARCHAR(256),
+    evaluation_by  VARCHAR(256),
+    kmrange_info  VARCHAR(32),
+    filename  VARCHAR(256) NOT NULL,
+    notes  VARCHAR(256)
+);
+COMMENT ON TABLE infrastructure IS 'Longitudinal section of infrastructures of a river and a type' ;
+COMMENT ON COLUMN infrastructure.year IS 'File header line info "Stand"' ;
+COMMENT ON COLUMN infrastructure.dataprovider IS 'File header line info "Datenherkunft"' ;
+COMMENT ON COLUMN infrastructure.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN infrastructure.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN infrastructure.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN infrastructure.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE INFRASTRUCTURE_ID_SEQ ;
+
+
+CREATE TABLE infrastructure_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    infrastructure_id  NUMERIC(9,0) CONSTRAINT cInfrastructureValuesInfrastructure REFERENCES infrastructure(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    attribute_id  integer CONSTRAINT cInfrastructureValuesAttributes REFERENCES attributes(id),
+    height  NUMERIC(6,2)
+);
+COMMENT ON TABLE infrastructure_values IS 'Infrastructure at a river station' ;
+COMMENT ON COLUMN infrastructure_values.station IS 'River km' ;
+COMMENT ON COLUMN infrastructure_values.height IS 'Geodetic height of the top of the infrastructure in m' ;
+
+CREATE SEQUENCE INFRASTRUCTURE_VALUES_ID_SEQ ;
+
+
+--Channel
+
+CREATE TABLE channel (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cChannelRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    kmrange_info  VARCHAR(32),
+    filename  VARCHAR(256) NOT NULL,
+    notes  VARCHAR(256),
+    year_from  NUMERIC(4,0),
+    year_to  NUMERIC(4,0)
+);
+COMMENT ON TABLE channel IS 'Longitudinal section of the navigable channel of a river' ;
+COMMENT ON COLUMN channel.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN channel.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN channel.notes IS 'File header line info "weitere Bemerkungen"' ;
+COMMENT ON COLUMN channel.year_from IS 'Start year of the period for which the channel values are valid, NULL when valid for the whole past';
+COMMENT ON COLUMN channel.year_to IS 'End year of the period for which the channel values are valid, NULL when unlimited';
+
+
+CREATE SEQUENCE CHANNEL_ID_SEQ ;
+
+
+CREATE TABLE channel_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    channel_id  NUMERIC(9,0) CONSTRAINT cChannelValuesChannel REFERENCES channel(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    width  NUMERIC(6,2),
+    depth  NUMERIC(6,2)
+);
+COMMENT ON TABLE channel_values IS 'Nominal size of the navigable channel at a river station' ;
+COMMENT ON COLUMN channel_values.station IS 'River km' ;
+COMMENT ON COLUMN channel_values.width IS 'Nominal width of the channel in m' ;
+COMMENT ON COLUMN channel_values.depth IS 'Nominal depth of the channel in m' ;
+
+CREATE SEQUENCE CHANNEL_VALUES_ID_SEQ ;
+
+
+--Collision
+
+CREATE TABLE collision_type (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    name  VARCHAR(64) NOT NULL UNIQUE
+);
+COMMENT ON TABLE collision_type IS 'Type of a ship collision' ;
+COMMENT ON COLUMN collision_type.name IS 'Name of the collision type' ;
+
+CREATE SEQUENCE COLLISION_TYPE_ID_SEQ ;
+
+
+CREATE TABLE collision (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cCollisionRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    year  NUMERIC(4,0) NOT NULL,
+    kmrange_info  VARCHAR(32),
+    filename  VARCHAR(256) NOT NULL,
+    notes  VARCHAR(256)
+);
+COMMENT ON TABLE collision IS 'Longitudinal section of ship collisions with the river bed' ;
+COMMENT ON COLUMN collision.year IS 'File header line info "Jahr"' ;
+COMMENT ON COLUMN collision.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN collision.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN collision.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE COLLISION_ID_SEQ ;
+
+
+CREATE TABLE collision_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    collision_id  NUMERIC(9,0) NOT NULL CONSTRAINT cCollisionValueCollision REFERENCES collision(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    event_date  DATE NOT NULL,
+    gauge_w  NUMERIC(6,2),
+    gauge_name  VARCHAR(64),
+    collision_type_id  NUMERIC(9,0) NOT NULL CONSTRAINT cCollisionValuesCollisionType REFERENCES collision_type(id)
+);
+COMMENT ON TABLE collision_values IS 'Collision event' ;
+COMMENT ON COLUMN collision_values.station IS 'River km' ;
+COMMENT ON COLUMN collision_values.event_date IS 'Date of the collision' ;
+COMMENT ON COLUMN collision_values.gauge_w IS 'Waterlevel during the collision' ;
+COMMENT ON COLUMN collision_values.gauge_name IS 'Name of the gauge' ;
+
+CREATE SEQUENCE COLLISION_VALUES_ID_SEQ ;
+
+
+--Tkh
+
+CREATE TABLE tkh (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cTkhRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    day  DATE,
+    kmrange_info  VARCHAR(32),
+    filename  VARCHAR(256) NOT NULL,
+    groupname  VARCHAR(32) NOT NULL CHECK(groupname IN ('messung','berechnung')),
+    sounding_info  VARCHAR(64),
+    evaluation_by  VARCHAR(256),
+    notes  VARCHAR(256)
+);
+COMMENT ON TABLE tkh IS 'Longitudinal section of computed Transportkörperhöhe of a river' ;
+COMMENT ON COLUMN tkh.day IS 'File header line info "Datum"' ;
+COMMENT ON COLUMN tkh.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN tkh.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN tkh.groupname IS 'Group the file belongs to' ;
+COMMENT ON COLUMN tkh.sounding_info IS 'File header line info "Peilung"' ;
+COMMENT ON COLUMN tkh.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN tkh.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE TKH_ID_SEQ ;
+
+
+CREATE TABLE tkh_column (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    tkh_id  NUMERIC(9,0) NOT NULL CONSTRAINT cTkhColumnTkh REFERENCES tkh(id) ON DELETE CASCADE,
+    name  VARCHAR(64) NOT NULL
+);
+COMMENT ON TABLE tkh_column IS 'Longitudinal section of computed Transportkörperhöhe for a waterlevel series' ;
+COMMENT ON COLUMN tkh_column.name IS 'Name of the tkh computation column' ;
+
+CREATE SEQUENCE TKH_COLUMN_ID_SEQ ;
+
+
+CREATE TABLE tkh_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    tkh_column_id  NUMERIC(9,0) NOT NULL CONSTRAINT cTkhValuesTkhColumn REFERENCES tkh_column(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    tkheight  NUMERIC(7,3)
+);
+COMMENT ON TABLE tkh_values IS 'Transportkörperhöhe of a river station and referenced file column' ;
+COMMENT ON COLUMN tkh_values.station IS 'River km' ;
+COMMENT ON COLUMN tkh_values.tkheight IS 'Transportkörperhöhe of a river station computed for a waterlevel in  m' ;
+
+CREATE SEQUENCE TKH_VALUES_ID_SEQ ;
+
+
+--Flow depth
+
+CREATE TABLE flow_depth (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cFlowDepthRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    year  NUMERIC(4,0) NOT NULL,
+    kmrange_info  VARCHAR(32),
+    filename  VARCHAR(256) NOT NULL,
+    sounding_info  VARCHAR(64),
+    evaluation_by  VARCHAR(255),
+    notes  VARCHAR(256)
+);
+
+COMMENT ON TABLE flow_depth IS 'Longitudinal section of computed flow depth of a river' ;
+COMMENT ON COLUMN flow_depth.year IS 'File header line info "Bezugsjahr"' ;
+COMMENT ON COLUMN flow_depth.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN flow_depth.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN flow_depth.sounding_info IS 'File header line info "Peilung"' ;
+COMMENT ON COLUMN flow_depth.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN flow_depth.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE FLOW_DEPTH_ID_SEQ ;
+
+
+CREATE TABLE flow_depth_column (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    flow_depth_id  NUMERIC(9,0) NOT NULL CONSTRAINT cFlowDepthColumnFlowDepth REFERENCES flow_depth(id) ON DELETE CASCADE,
+    name  VARCHAR(64) NOT NULL
+);
+
+COMMENT ON TABLE flow_depth_column IS 'Longitudinal section of computed flow depth for a waterlevel series' ;
+COMMENT ON COLUMN flow_depth_column.name IS 'Name of the flow depth computation column' ;
+
+CREATE SEQUENCE FLOW_DEPTH_COLUMN_ID_SEQ ;
+
+
+CREATE TABLE flow_depth_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    flow_depth_column_id  NUMERIC(9,0) NOT NULL CONSTRAINT cFlowDepthValuesFlowDepthColumn REFERENCES flow_depth_column(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    depth  NUMERIC(7,3)
+);
+
+COMMENT ON TABLE flow_depth_values IS 'Flow depth of a river station and referenced file column' ;
+COMMENT ON COLUMN flow_depth_values.station IS 'River km' ;
+COMMENT ON COLUMN flow_depth_values.depth IS 'Flow depth of a river station computed for a waterlevel in  m' ;
+
+CREATE SEQUENCE FLOW_DEPTH_VALUES_ID_SEQ ;
+
+
+--Depth evolution
+
+CREATE TABLE depth_evolution (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cDepthEvolutionRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    reference_year  NUMERIC(4,0) NOT NULL,
+    start_year  NUMERIC(4,0) NOT NULL,
+    curr_sounding  VARCHAR(64) NOT NULL,
+    old_sounding  VARCHAR(64) NOT NULL,
+    kmrange_info  VARCHAR(32),
+    curr_glw  VARCHAR(64) NOT NULL,
+    old_glw  VARCHAR(64) NOT NULL,
+    filename  VARCHAR(256) NOT NULL,
+    groupname  VARCHAR(32) NOT NULL CHECK(groupname IN ('aktuell','etappe')),
+    notes  VARCHAR(256)
+);
+COMMENT ON TABLE depth_evolution IS 'Longitudinal section of the evolution of the flow depth of a river' ;
+COMMENT ON COLUMN depth_evolution.reference_year IS 'File header line info "Bezugsjahr" (GlW)' ;
+COMMENT ON COLUMN depth_evolution.start_year IS 'File header line info "Ausgangsjahr" (GlW)' ;
+COMMENT ON COLUMN depth_evolution.curr_sounding IS 'File header line info "Aktuelle Peilung / Epoche"' ;
+COMMENT ON COLUMN depth_evolution.old_sounding IS 'File header line info "Historische Peilung / Epoche"' ;
+COMMENT ON COLUMN depth_evolution.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN depth_evolution.curr_glw IS 'File header line info "Aktuelle Wasserspiegellage"' ;
+COMMENT ON COLUMN depth_evolution.old_glw IS 'File header line info "Historische Wasserspiegellage"' ;
+COMMENT ON COLUMN depth_evolution.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN depth_evolution.groupname IS 'Group the file belongs to' ;
+COMMENT ON COLUMN depth_evolution.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE DEPTH_EVOLUTION_ID_SEQ ;
+
+
+CREATE TABLE depth_evolution_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    depth_evolution_id  NUMERIC(9,0) NOT NULL CONSTRAINT cDepthEvolutionValuesDepthEvolution REFERENCES depth_evolution(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    total_change  NUMERIC(8,4),
+    change_per_year  NUMERIC(8,4)
+);
+COMMENT ON TABLE depth_evolution_values IS 'Evolution of the flow depth of a river station in a referenced period of time' ;
+COMMENT ON COLUMN depth_evolution_values.station IS 'River km' ;
+COMMENT ON COLUMN depth_evolution_values.total_change IS 'Flow depth change of the whole period of time in m' ;
+COMMENT ON COLUMN depth_evolution_values.change_per_year IS 'Average yearly flow depth change in the referenced period of time in m' ;
+
+CREATE SEQUENCE DEPTH_EVOLUTION_VALUES_ID_SEQ ;
+
+
+--Daily discharge
+
+CREATE TABLE daily_discharge (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    gauge_id  integer NOT NULL CONSTRAINT cDailyDischargeGauge REFERENCES gauges(id) ON DELETE CASCADE,
+    filename  VARCHAR(256) NOT NULL
+);
+
+COMMENT ON TABLE daily_discharge IS 'Daily discharge value series' ;
+COMMENT ON COLUMN daily_discharge.filename IS 'Name without type extension of the imported file' ;
+
+CREATE SEQUENCE DAILY_DISCHARGE_ID_SEQ ;
+
+
+CREATE TABLE daily_discharge_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    daily_discharge_id  NUMERIC(9,0) NOT NULL CONSTRAINT cDailyDischargeValueDailyDischarge REFERENCES daily_discharge(id) ON DELETE CASCADE,
+    day  DATE NOT NULL,
+    discharge  NUMERIC(8,3) NOT NULL
+);
+
+COMMENT ON TABLE daily_discharge_values IS 'Mean daily discharge of a date and a gauge' ;
+COMMENT ON COLUMN daily_discharge_values.day IS 'Date of the discharge value' ;
+COMMENT ON COLUMN daily_discharge_values.discharge IS 'Mean daily discharge in m^3/s' ;
+
+CREATE SEQUENCE DAILY_DISCHARGE_VALUES_ID_SEQ ;
+
+
+--Salix line
+
+CREATE TABLE salix (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cSalixRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    evaluation_by  VARCHAR(255),
+    kmrange_info  VARCHAR(32),
+    filename  VARCHAR(256) NOT NULL,
+    notes  VARCHAR(256)
+);
+
+COMMENT ON TABLE salix IS 'Longitudinal section of the salix line parameters of a river' ;
+COMMENT ON COLUMN salix.evaluation_by IS 'File header line info "Auswerter"' ;
+COMMENT ON COLUMN salix.kmrange_info IS 'File header line info "Strecke"' ;
+COMMENT ON COLUMN salix.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN salix.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE SALIX_ID_SEQ ;
+
+
+CREATE TABLE salix_values (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    salix_id  NUMERIC(9,0) NOT NULL CONSTRAINT cSalixValuesSalix REFERENCES salix(id) ON DELETE CASCADE,
+    station  NUMERIC(7,3) NOT NULL,
+    factor  NUMERIC(6,2) NOT NULL,
+    mnw_mw_diff  NUMERIC(6,2)
+);
+
+COMMENT ON COLUMN salix_values.station IS 'River km' ;
+COMMENT ON COLUMN salix_values.factor IS 'Salix "factor" of the station in m' ;
+COMMENT ON COLUMN salix_values.mnw_mw_diff IS 'Difference between MNW and MW in m (less than zero)' ;
+
+CREATE SEQUENCE SALIX_VALUES_ID_SEQ ;
+
+
+CREATE TABLE salix_rank (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    min_value  NUMERIC(6,2),
+    max_value  NUMERIC(6,2),
+    name  VARCHAR(16) NOT NULL
+);
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (1, NULL, -0.3, 'invalid');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (2, -0.3, 0.3, 'very good');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (3, 0.3, 0.5, 'good');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (4, 0.5, 1.0, 'moderate');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (5, 1.0, 1.5, 'bad');
+INSERT INTO salix_rank (id, min_value, max_value, name) VALUES (6, 1.5, NULL, 'very bad');
+
+
+--Vegetation zone
+
+CREATE TABLE vegetation_type (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    name  VARCHAR(256) NOT NULL
+);
+INSERT INTO vegetation_type (id, name) VALUES (1, 'zonal forest');
+INSERT INTO vegetation_type (id, name) VALUES (2, 'dry hartwood forest floodplain');
+INSERT INTO vegetation_type (id, name) VALUES (3, 'wet hartwood forest floodplain');
+INSERT INTO vegetation_type (id, name) VALUES (4, 'salix alba forest');
+INSERT INTO vegetation_type (id, name) VALUES (5, 'salix shrubs');
+INSERT INTO vegetation_type (id, name) VALUES (6, 'reed bed');
+INSERT INTO vegetation_type (id, name) VALUES (7, 'bank pioneers');
+INSERT INTO vegetation_type (id, name) VALUES (8, 'no vegetation');
+INSERT INTO vegetation_type (id, name) VALUES (9, 'water');
+
+
+CREATE TABLE vegetation (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    river_id  integer NOT NULL CONSTRAINT cVegetationRivers REFERENCES rivers(id) ON DELETE CASCADE,
+    name  VARCHAR(256),
+    filename  VARCHAR(256) NOT NULL,
+    notes  VARCHAR(256)
+);
+
+COMMENT ON TABLE vegetation IS 'Classification of the vegetation of a river' ;
+COMMENT ON COLUMN vegetation.name IS 'File header line info "Einteilung"' ;
+COMMENT ON COLUMN vegetation.filename IS 'Name without type extension of the imported file' ;
+COMMENT ON COLUMN vegetation.notes IS 'File header line info "weitere Bemerkungen"' ;
+
+CREATE SEQUENCE VEGETATION_ID_SEQ ;
+
+
+CREATE TABLE vegetation_zone (
+    id  NUMERIC(9,0) PRIMARY KEY,
+    vegetation_id  NUMERIC(9,0) NOT NULL CONSTRAINT cVegetationZoneVegetation REFERENCES vegetation(id) ON DELETE CASCADE,
+    vegetation_type_id  NUMERIC(9,0) NOT NULL CONSTRAINT cVegetationZoneVegetationType REFERENCES vegetation_type(id) ON DELETE CASCADE,
+    min_overflow_days  NUMERIC(3,0) NOT NULL,
+    max_overflow_days  NUMERIC(3,0) NOT NULL
+);
+
+COMMENT ON TABLE vegetation_zone IS 'Vegetation zone of a river station' ;
+COMMENT ON COLUMN vegetation_zone.min_overflow_days IS 'Minimum number (inclusive) of overflow days in a year for the zone type' ;
+COMMENT ON COLUMN vegetation_zone.max_overflow_days IS 'Maximum number (exclusive) of overflow days in a year for the zone type' ;
+
+CREATE SEQUENCE VEGETATION_ZONE_ID_SEQ ;
+
+
+COMMIT;
--- a/backend/pom-oracle.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/pom-oracle.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -36,7 +36,7 @@
               <goal>analyze-only</goal>
             </goals>
             <configuration>
-              <failOnWarning>true</failOnWarning>
+              <failOnWarning>false</failOnWarning>
               <ignoreNonCompile>true</ignoreNonCompile>
             </configuration>
           </execution>
@@ -45,6 +45,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
+        <version>2.4</version>
         <configuration>
           <archive>
             <manifest>
@@ -82,6 +83,30 @@
           </descriptors>
         </configuration>
       </plugin>
+      <!-- 
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>3.0.0</version>
+        <configuration>
+          <configLocation>../checkstyle.xml</configLocation>
+          <encoding>UTF-8</encoding>
+        </configuration>
+        <executions>
+          <execution>
+            <id>validate</id>
+            <phase>validate</phase>
+            <configuration>
+              <consoleOutput>true</consoleOutput>
+              <failsOnError>true</failsOnError>
+            </configuration>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+       -->
     </plugins>
   </build>
 
@@ -137,6 +162,16 @@
       <scope>runtime</scope>
     </dependency>
     <dependency>
+    	<groupId>org.slf4j</groupId>
+    	<artifactId>jul-to-slf4j</artifactId>
+    	<version>1.6.1</version>
+    </dependency>
+    <dependency>
+    	<groupId>org.slf4j</groupId>
+    	<artifactId>slf4j-log4j12</artifactId>
+    	<version>1.6.1</version>
+    </dependency>
+    <dependency>
       <groupId>ojdbc</groupId>
       <artifactId>ojdbc</artifactId>
       <version>0</version>
--- a/backend/pom.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/pom.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -36,7 +36,7 @@
               <goal>analyze-only</goal>
             </goals>
             <configuration>
-              <failOnWarning>true</failOnWarning>
+              <failOnWarning>false</failOnWarning>
               <ignoreNonCompile>true</ignoreNonCompile>
             </configuration>
           </execution>
@@ -45,6 +45,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
+        <version>2.4</version>
         <configuration>
           <archive>
             <manifest>
@@ -82,6 +83,7 @@
           </descriptors>
         </configuration>
       </plugin>
+      <!-- 
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
@@ -104,6 +106,7 @@
           </execution>
         </executions>
       </plugin>
+       -->
     </plugins>
   </build>
 
@@ -177,6 +180,16 @@
       <version>1.1.1</version>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+    	<groupId>org.slf4j</groupId>
+    	<artifactId>jul-to-slf4j</artifactId>
+    	<version>1.6.1</version>
+    </dependency>
+    <dependency>
+    	<groupId>org.slf4j</groupId>
+    	<artifactId>slf4j-log4j12</artifactId>
+    	<version>1.6.1</version>
+    </dependency>
   </dependencies>
 
   <repositories>
--- a/backend/src/assembly/assembly.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/assembly/assembly.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -32,9 +32,20 @@
         <include>*.sql</include>
       </includes>
     </fileSet>
+
+    <!-- Include PDF-manual if existant -->
+    <fileSet>
+      <directory>${project.basedir}/doc/documentation/de</directory>
+      <outputDirectory>/flys-importer/doc/</outputDirectory>
+      <includes>
+        <include>*.pdf</include>
+      </includes>
+    </fileSet>
   </fileSets>
+
+  <!-- Include PDF-manual if existant -->
+  <!-- 
   <files>
-    <!-- Include PDF-manual if existant -->
     <file>
       <source>
         ${project.basedir}/doc/documentation/de/importer-manual.pdf
@@ -42,4 +53,5 @@
       <outputDirectory>/flys-importer/doc/</outputDirectory>
     </file>
   </files>
+   -->
 </assembly>
--- a/backend/src/main/java/org/dive4elements/river/backend/FLYSCredentials.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/backend/FLYSCredentials.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,16 +9,15 @@
 package org.dive4elements.river.backend;
 
 import org.dive4elements.artifacts.common.utils.Config;
-
 import org.dive4elements.river.model.Annotation;
 import org.dive4elements.river.model.AnnotationType;
 import org.dive4elements.river.model.Attribute;
 import org.dive4elements.river.model.AxisKind;
 import org.dive4elements.river.model.BedHeight;
-import org.dive4elements.river.model.BedHeightValue;
 import org.dive4elements.river.model.BedHeightType;
+import org.dive4elements.river.model.BedHeightValue;
+import org.dive4elements.river.model.BoundaryKind;
 import org.dive4elements.river.model.Building;
-import org.dive4elements.river.model.BoundaryKind;
 import org.dive4elements.river.model.CrossSection;
 import org.dive4elements.river.model.CrossSectionLine;
 import org.dive4elements.river.model.CrossSectionPoint;
@@ -61,6 +60,7 @@
 import org.dive4elements.river.model.MorphologicalWidth;
 import org.dive4elements.river.model.MorphologicalWidthValue;
 import org.dive4elements.river.model.NamedMainValue;
+import org.dive4elements.river.model.OfficialLine;
 import org.dive4elements.river.model.Porosity;
 import org.dive4elements.river.model.PorosityValue;
 import org.dive4elements.river.model.Position;
@@ -71,14 +71,14 @@
 import org.dive4elements.river.model.SQRelation;
 import org.dive4elements.river.model.SQRelationValue;
 import org.dive4elements.river.model.SectieKind;
-import org.dive4elements.river.model.SobekKind;
 import org.dive4elements.river.model.SeddbName;
 import org.dive4elements.river.model.SedimentDensity;
 import org.dive4elements.river.model.SedimentDensityValue;
 import org.dive4elements.river.model.SedimentLoad;
-import org.dive4elements.river.model.SedimentLoadValue;
 import org.dive4elements.river.model.SedimentLoadLS;
 import org.dive4elements.river.model.SedimentLoadLSValue;
+import org.dive4elements.river.model.SedimentLoadValue;
+import org.dive4elements.river.model.SobekKind;
 import org.dive4elements.river.model.TimeInterval;
 import org.dive4elements.river.model.Unit;
 import org.dive4elements.river.model.Wst;
@@ -86,208 +86,253 @@
 import org.dive4elements.river.model.WstColumnQRange;
 import org.dive4elements.river.model.WstColumnValue;
 import org.dive4elements.river.model.WstQRange;
-import org.dive4elements.river.model.OfficialLine;
+import org.dive4elements.river.model.sinfo.BedMobility;
+import org.dive4elements.river.model.sinfo.BedMobilityValue;
+import org.dive4elements.river.model.sinfo.Channel;
+import org.dive4elements.river.model.sinfo.ChannelValue;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.dive4elements.river.model.sinfo.CollisionType;
+import org.dive4elements.river.model.sinfo.CollisionValue;
+import org.dive4elements.river.model.sinfo.DailyDischarge;
+import org.dive4elements.river.model.sinfo.DailyDischargeValue;
+import org.dive4elements.river.model.sinfo.DepthEvolution;
+import org.dive4elements.river.model.sinfo.DepthEvolutionValue;
+import org.dive4elements.river.model.sinfo.FlowDepth;
+import org.dive4elements.river.model.sinfo.FlowDepthColumn;
+import org.dive4elements.river.model.sinfo.FlowDepthValue;
+import org.dive4elements.river.model.sinfo.Infrastructure;
+import org.dive4elements.river.model.sinfo.InfrastructureValue;
+import org.dive4elements.river.model.sinfo.Tkh;
+import org.dive4elements.river.model.sinfo.TkhColumn;
+import org.dive4elements.river.model.sinfo.TkhValue;
+import org.dive4elements.river.model.uinfo.Salix;
+import org.dive4elements.river.model.uinfo.SalixRank;
+import org.dive4elements.river.model.uinfo.SalixValue;
+import org.dive4elements.river.model.uinfo.Vegetation;
+import org.dive4elements.river.model.uinfo.VegetationType;
+import org.dive4elements.river.model.uinfo.VegetationZone;
 
 public class FLYSCredentials
 extends      Credentials
 {
     public static final String XPATH_USER =
-        "/artifact-database/backend-database/user/text()";
+            "/artifact-database/backend-database/user/text()";
 
     public static final String XPATH_PASSWORD =
-        "/artifact-database/backend-database/password/text()";
+            "/artifact-database/backend-database/password/text()";
 
     public static final String XPATH_DIALECT =
-        "/artifact-database/backend-database/dialect/text()";
+            "/artifact-database/backend-database/dialect/text()";
 
     public static final String XPATH_DRIVER =
-        "/artifact-database/backend-database/driver/text()";
+            "/artifact-database/backend-database/driver/text()";
 
     public static final String XPATH_URL =
-        "/artifact-database/backend-database/url/text()";
+            "/artifact-database/backend-database/url/text()";
 
     public static final String XPATH_CONNECTION_INIT_SQLS =
-        "/artifact-database/backend-database/connection-init-sqls/text()";
+            "/artifact-database/backend-database/connection-init-sqls/text()";
 
     public static final String XPATH_VALIDATION_QUERY =
-        "/artifact-database/backend-database/validation-query/text()";
+            "/artifact-database/backend-database/validation-query/text()";
 
     public static final String XPATH_MAX_WAIT =
-        "/artifact-database/backend-database/max-wait/text()";
+            "/artifact-database/backend-database/max-wait/text()";
 
     public static final String DEFAULT_USER =
-        System.getProperty("flys.backend.user", "flys");
+            System.getProperty("flys.backend.user", "flys");
 
     public static final String DEFAULT_PASSWORD =
-        System.getProperty("flys.backend.password", "flys");
+            System.getProperty("flys.backend.password", "flys");
 
     public static final String DEFAULT_DIALECT =
-        System.getProperty(
-            "flys.backend.dialect",
-            "org.hibernate.dialect.PostgreSQLDialect");
+            System.getProperty(
+                    "flys.backend.dialect",
+                    "org.hibernate.dialect.PostgreSQLDialect");
 
     public static final String DEFAULT_DRIVER =
-        System.getProperty(
-            "flys.backend.driver",
-            "org.postgresql.Driver");
+            System.getProperty(
+                    "flys.backend.driver",
+                    "org.postgresql.Driver");
 
     public static final String DEFAULT_URL =
-        System.getProperty(
-            "flys.backend.url",
-            "jdbc:postgresql://localhost:5432/flys");
+            System.getProperty(
+                    "flys.backend.url",
+                    "jdbc:postgresql://localhost:5432/flys");
 
-    public static final String DEFAULT_CONNECTION_INIT_SQLS =
-        System.getProperty(
-            "flys.backend.connection.init.sqls");
+    private static final String DEFAULT_CONNECTION_INIT_SQLS = "select 1 from rivers";
 
-    public static final String DEFAULT_VALIDATION_QUERY =
-        System.getProperty(
-            "flys.backend.connection.validation.query");
+    private static final String DEFAULT_VALIDATION_QUERY = "select 1 from rivers";
 
     public static final String DEFAULT_MAX_WAIT =
-        System.getProperty("flys.backend.connection.max.wait");
+            System.getProperty("flys.backend.connection.max.wait");
 
-    public static final Class [] CLASSES = {
-        Annotation.class,
-        AnnotationType.class,
-        Attribute.class,
-        AxisKind.class,
-        BedHeight.class,
-        BedHeightValue.class,
-        BedHeightType.class,
-        Building.class,
-        BoundaryKind.class,
-        CrossSection.class,
-        CrossSectionLine.class,
-        CrossSectionPoint.class,
-        CrossSectionTrack.class,
-        CrossSectionTrackKind.class,
-        Depth.class,
-        DGM.class,
-        DischargeTable.class,
-        DischargeTableValue.class,
-        DischargeZone.class,
-        Edge.class,
-        ElevationModel.class,
-        FedState.class,
-        Fixpoint.class,
-        Floodmark.class,
-        Floodplain.class,
-        FloodplainKind.class,
-        Floodmaps.class,
-        FlowVelocityMeasurement.class,
-        FlowVelocityMeasurementValue.class,
-        FlowVelocityModel.class,
-        FlowVelocityModelValue.class,
-        Gauge.class,
-        GrainFraction.class,
-        HWSKind.class,
-        HWSLine.class,
-        HWSPoint.class,
-        HydrBoundary.class,
-        HydrBoundaryPoly.class,
-        HYK.class,
-        HYKEntry.class,
-        HYKFormation.class,
-        HYKFlowZoneType.class,
-        HYKFlowZone.class,
-        Jetty.class,
-        LocationSystem.class,
-        MainValueType.class,
-        MeasurementStation.class,
-        MorphologicalWidth.class,
-        MorphologicalWidthValue.class,
-        NamedMainValue.class,
-        MainValue.class,
-        Position.class,
-        Range.class,
-        River.class,
-        RiverAxis.class,
-        RiverAxisKm.class,
-        Porosity.class,
-        PorosityValue.class,
-        SectieKind.class,
-        SobekKind.class,
-        SeddbName.class,
-        SedimentDensity.class,
-        SedimentDensityValue.class,
-        SedimentLoad.class,
-        SedimentLoadValue.class,
-        SedimentLoadLS.class,
-        SedimentLoadLSValue.class,
-        SQRelation.class,
-        SQRelationValue.class,
-        TimeInterval.class,
-        Unit.class,
-        WstColumn.class,
-        WstColumnQRange.class,
-        WstColumnValue.class,
-        Wst.class,
-        WstQRange.class,
-        OfficialLine.class
+    public static final Class<?>[] CLASSES = {
+            Annotation.class,
+            AnnotationType.class,
+            Attribute.class,
+            AxisKind.class,
+            BedHeight.class,
+            BedHeightValue.class,
+            BedHeightType.class,
+            Building.class,
+            BoundaryKind.class,
+            CrossSection.class,
+            CrossSectionLine.class,
+            CrossSectionPoint.class,
+            CrossSectionTrack.class,
+            CrossSectionTrackKind.class,
+            Depth.class,
+            DGM.class,
+            DischargeTable.class,
+            DischargeTableValue.class,
+            DischargeZone.class,
+            Edge.class,
+            ElevationModel.class,
+            FedState.class,
+            Fixpoint.class,
+            Floodmark.class,
+            Floodplain.class,
+            FloodplainKind.class,
+            Floodmaps.class,
+            FlowVelocityMeasurement.class,
+            FlowVelocityMeasurementValue.class,
+            FlowVelocityModel.class,
+            FlowVelocityModelValue.class,
+            Gauge.class,
+            GrainFraction.class,
+            HWSKind.class,
+            HWSLine.class,
+            HWSPoint.class,
+            HydrBoundary.class,
+            HydrBoundaryPoly.class,
+            HYK.class,
+            HYKEntry.class,
+            HYKFormation.class,
+            HYKFlowZoneType.class,
+            HYKFlowZone.class,
+            Jetty.class,
+            LocationSystem.class,
+            MainValueType.class,
+            MeasurementStation.class,
+            MorphologicalWidth.class,
+            MorphologicalWidthValue.class,
+            NamedMainValue.class,
+            MainValue.class,
+            Position.class,
+            Range.class,
+            River.class,
+            RiverAxis.class,
+            RiverAxisKm.class,
+            Porosity.class,
+            PorosityValue.class,
+            SectieKind.class,
+            SobekKind.class,
+            SeddbName.class,
+            SedimentDensity.class,
+            SedimentDensityValue.class,
+            SedimentLoad.class,
+            SedimentLoadValue.class,
+            SedimentLoadLS.class,
+            SedimentLoadLSValue.class,
+            SQRelation.class,
+            SQRelationValue.class,
+            TimeInterval.class,
+            Unit.class,
+            WstColumn.class,
+            WstColumnQRange.class,
+            WstColumnValue.class,
+            Wst.class,
+            WstQRange.class,
+            OfficialLine.class,
+            BedMobility.class,
+            BedMobilityValue.class,
+            Infrastructure.class,
+            InfrastructureValue.class,
+            Channel.class,
+            ChannelValue.class,
+            CollisionType.class,
+            Collision.class,
+            CollisionValue.class,
+            DailyDischarge.class,
+            DailyDischargeValue.class,
+            SalixRank.class,
+            Salix.class,
+            SalixValue.class,
+            Tkh.class,
+            TkhColumn.class,
+            TkhValue.class,
+            FlowDepth.class,
+            FlowDepthColumn.class,
+            FlowDepthValue.class,
+            DepthEvolution.class,
+            DepthEvolutionValue.class,
+            Vegetation.class,
+            VegetationZone.class,
+            VegetationType.class
     };
 
     public FLYSCredentials() {
     }
 
     public FLYSCredentials(
-        String user,
-        String password,
-        String dialect,
-        String driver,
-        String url,
-        String connectionInitSqls,
-        String validationQuery,
-        String maxWait
-    ) {
+            final String user,
+            final String password,
+            final String dialect,
+            final String driver,
+            final String url,
+            final String connectionInitSqls,
+            final String validationQuery,
+            final String maxWait
+            ) {
         super(
-            user, password, dialect, driver, url,
-            connectionInitSqls, validationQuery, maxWait, CLASSES);
+                user, password, dialect, driver, url,
+                connectionInitSqls, validationQuery, maxWait, CLASSES);
     }
 
     private static Credentials instance;
 
     public static synchronized Credentials getInstance() {
         if (instance == null) {
-            String user =
-                Config.getStringXPath(XPATH_USER, DEFAULT_USER);
-            String password =
-                Config.getStringXPath(XPATH_PASSWORD, DEFAULT_PASSWORD);
-            String dialect =
-                Config.getStringXPath(XPATH_DIALECT, DEFAULT_DIALECT);
-            String driver =
-                Config.getStringXPath(XPATH_DRIVER, DEFAULT_DRIVER);
-            String url =
-                Config.getStringXPath(XPATH_URL, DEFAULT_URL);
-            String connectionInitSqls =
-                Config.getStringXPath(
-                    XPATH_CONNECTION_INIT_SQLS,
-                    DEFAULT_CONNECTION_INIT_SQLS);
-            String validationQuery =
-                Config.getStringXPath(
-                    XPATH_VALIDATION_QUERY,
-                    DEFAULT_VALIDATION_QUERY);
-            String maxWait =
-                Config.getStringXPath(XPATH_MAX_WAIT, DEFAULT_MAX_WAIT);
+            final String user =
+                    Config.getStringXPath(XPATH_USER, DEFAULT_USER);
+            final String password =
+                    Config.getStringXPath(XPATH_PASSWORD, DEFAULT_PASSWORD);
+            final String dialect =
+                    Config.getStringXPath(XPATH_DIALECT, DEFAULT_DIALECT);
+            final String driver =
+                    Config.getStringXPath(XPATH_DRIVER, DEFAULT_DRIVER);
+            final String url =
+                    Config.getStringXPath(XPATH_URL, DEFAULT_URL);
+            final String connectionInitSqls =
+                    Config.getStringXPath(
+                            XPATH_CONNECTION_INIT_SQLS,
+                            DEFAULT_CONNECTION_INIT_SQLS);
+            final String validationQuery =
+                    Config.getStringXPath(
+                            XPATH_VALIDATION_QUERY,
+                            DEFAULT_VALIDATION_QUERY);
+            final String maxWait =
+                    Config.getStringXPath(XPATH_MAX_WAIT, DEFAULT_MAX_WAIT);
 
             instance = new FLYSCredentials(
-                user, password, dialect, driver, url, connectionInitSqls,
-                validationQuery, maxWait);
+                    user, password, dialect, driver, url, connectionInitSqls,
+                    validationQuery, maxWait);
         }
         return instance;
     }
 
     public static Credentials getDefault() {
         return new FLYSCredentials(
-            DEFAULT_USER,
-            DEFAULT_PASSWORD,
-            DEFAULT_DIALECT,
-            DEFAULT_DRIVER,
-            DEFAULT_URL,
-            DEFAULT_CONNECTION_INIT_SQLS,
-            DEFAULT_VALIDATION_QUERY,
-            DEFAULT_MAX_WAIT
-        );
+                DEFAULT_USER,
+                DEFAULT_PASSWORD,
+                DEFAULT_DIALECT,
+                DEFAULT_DRIVER,
+                DEFAULT_URL,
+                DEFAULT_CONNECTION_INIT_SQLS,
+                DEFAULT_VALIDATION_QUERY,
+                DEFAULT_MAX_WAIT
+                );
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/backend/SedDBCredentials.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/backend/SedDBCredentials.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,129 +10,70 @@
 
 import org.dive4elements.artifacts.common.utils.Config;
 
-
-public class SedDBCredentials
-extends      Credentials
-{
-    public static final String XPATH_USER =
-        "/artifact-database/seddb-database/user/text()";
-
-    public static final String XPATH_PASSWORD =
-        "/artifact-database/seddb-database/password/text()";
-
-    public static final String XPATH_DIALECT =
-        "/artifact-database/seddb-database/dialect/text()";
-
-    public static final String XPATH_DRIVER =
-        "/artifact-database/seddb-database/driver/text()";
-
-    public static final String XPATH_URL =
-        "/artifact-database/seddb-database/url/text()";
-
-    public static final String XPATH_CONNECTION_INIT_SQLS =
-        "/artifact-database/seddb-database/connection-init-sqls/text()";
-
-    public static final String XPATH_VALIDATION_QUERY =
-        "/artifact-database/seddb-database/validation-query/text()";
-
-    public static final String XPATH_MAX_WAIT =
-        "/artifact-database/seddb-database/max-wait/text()";
+public class SedDBCredentials extends Credentials {
+    public static final String XPATH_USER = "/artifact-database/seddb-database/user/text()";
 
-    public static final String DEFAULT_USER =
-        System.getProperty("flys.seddb.user", "seddb");
-
-    public static final String DEFAULT_PASSWORD =
-        System.getProperty("flys.seddb.password", "seddb");
-
-    public static final String DEFAULT_DIALECT =
-        System.getProperty(
-            "flys.seddb.dialect",
-            "org.hibernate.dialect.PostgreSQLDialect");
-
-    public static final String DEFAULT_DRIVER =
-        System.getProperty(
-            "flys.seddb.driver",
-            "org.postgresql.Driver");
+    public static final String XPATH_PASSWORD = "/artifact-database/seddb-database/password/text()";
 
-    public static final String DEFAULT_URL =
-        System.getProperty(
-            "flys.seddb.url",
-            "jdbc:postgresql://localhost:5432/seddb");
+    public static final String XPATH_DIALECT = "/artifact-database/seddb-database/dialect/text()";
 
-    public static final String DEFAULT_CONNECTION_INIT_SQLS =
-        System.getProperty(
-            "flys.seddb.connection.init.sqls");
+    public static final String XPATH_DRIVER = "/artifact-database/seddb-database/driver/text()";
 
-    public static final String DEFAULT_VALIDATION_QUERY =
-        System.getProperty(
-            "flys.seddb.connection.validation.query");
+    public static final String XPATH_URL = "/artifact-database/seddb-database/url/text()";
 
-    public static final String DEFAULT_MAX_WAIT =
-        System.getProperty("flys.seddb.connection.max.wait");
+    public static final String XPATH_CONNECTION_INIT_SQLS = "/artifact-database/seddb-database/connection-init-sqls/text()";
 
-    public static final Class [] CLASSES = {};
+    public static final String XPATH_VALIDATION_QUERY = "/artifact-database/seddb-database/validation-query/text()";
+
+    public static final String XPATH_MAX_WAIT = "/artifact-database/seddb-database/max-wait/text()";
+
+    public static final String DEFAULT_USER = System.getProperty("flys.seddb.user", "seddb");
+
+    public static final String DEFAULT_PASSWORD = System.getProperty("flys.seddb.password", "seddb");
+
+    public static final String DEFAULT_DIALECT = System.getProperty("flys.seddb.dialect", "org.hibernate.dialect.PostgreSQLDialect");
+
+    public static final String DEFAULT_DRIVER = System.getProperty("flys.seddb.driver", "org.postgresql.Driver");
+
+    public static final String DEFAULT_URL = System.getProperty("flys.seddb.url", "jdbc:postgresql://localhost:5432/seddb");
+
+    public static final String DEFAULT_CONNECTION_INIT_SQLS = System.getProperty("flys.seddb.connection.init.sqls");
+
+    public static final String DEFAULT_VALIDATION_QUERY = System.getProperty("flys.seddb.connection.validation.query");
+
+    public static final String DEFAULT_MAX_WAIT = System.getProperty("flys.seddb.connection.max.wait");
+
+    public static final Class[] CLASSES = {};
 
     private static Credentials instance;
 
     public SedDBCredentials() {
     }
 
-    public SedDBCredentials(
-        String user,
-        String password,
-        String dialect,
-        String driver,
-        String url,
-        String connectionInitSqls,
-        String validationQuery,
-        String maxWait
-    ) {
-        super(
-            user, password, dialect, driver, url,
-            connectionInitSqls, validationQuery, maxWait, CLASSES);
+    public SedDBCredentials(final String user, final String password, final String dialect, final String driver, final String url,
+            final String connectionInitSqls, final String validationQuery, final String maxWait) {
+        super(user, password, dialect, driver, url, connectionInitSqls, validationQuery, maxWait, CLASSES);
     }
 
     public static synchronized Credentials getInstance() {
         if (instance == null) {
-            String user =
-                Config.getStringXPath(XPATH_USER, DEFAULT_USER);
-            String password =
-                Config.getStringXPath(XPATH_PASSWORD, DEFAULT_PASSWORD);
-            String dialect =
-                Config.getStringXPath(XPATH_DIALECT, DEFAULT_DIALECT);
-            String driver =
-                Config.getStringXPath(XPATH_DRIVER, DEFAULT_DRIVER);
-            String url =
-                Config.getStringXPath(XPATH_URL, DEFAULT_URL);
-            String connectionInitSqls =
-                Config.getStringXPath(
-                    XPATH_CONNECTION_INIT_SQLS,
-                    DEFAULT_CONNECTION_INIT_SQLS);
-            String validationQuery =
-                Config.getStringXPath(
-                    XPATH_VALIDATION_QUERY,
-                    DEFAULT_VALIDATION_QUERY);
-            String maxWait =
-                Config.getStringXPath(XPATH_MAX_WAIT, DEFAULT_MAX_WAIT);
+            final String user = Config.getStringXPath(XPATH_USER, DEFAULT_USER);
+            final String password = Config.getStringXPath(XPATH_PASSWORD, DEFAULT_PASSWORD);
+            final String dialect = Config.getStringXPath(XPATH_DIALECT, DEFAULT_DIALECT);
+            final String driver = Config.getStringXPath(XPATH_DRIVER, DEFAULT_DRIVER);
+            final String url = Config.getStringXPath(XPATH_URL, DEFAULT_URL);
+            final String connectionInitSqls = Config.getStringXPath(XPATH_CONNECTION_INIT_SQLS, DEFAULT_CONNECTION_INIT_SQLS);
+            final String validationQuery = Config.getStringXPath(XPATH_VALIDATION_QUERY, DEFAULT_VALIDATION_QUERY);
+            final String maxWait = Config.getStringXPath(XPATH_MAX_WAIT, DEFAULT_MAX_WAIT);
 
-            instance = new SedDBCredentials(
-                user, password, dialect, driver, url,
-                connectionInitSqls, validationQuery, maxWait);
+            instance = new SedDBCredentials(user, password, dialect, driver, url, connectionInitSqls, validationQuery, maxWait);
         }
         return instance;
     }
 
     public static Credentials getDefault() {
-        return new SedDBCredentials(
-            DEFAULT_USER,
-            DEFAULT_PASSWORD,
-            DEFAULT_DIALECT,
-            DEFAULT_DRIVER,
-            DEFAULT_URL,
-            DEFAULT_CONNECTION_INIT_SQLS,
-            DEFAULT_VALIDATION_QUERY,
-            DEFAULT_MAX_WAIT
-        );
+        return new SedDBCredentials(DEFAULT_USER, DEFAULT_PASSWORD, DEFAULT_DIALECT, DEFAULT_DRIVER, DEFAULT_URL, DEFAULT_CONNECTION_INIT_SQLS,
+                DEFAULT_VALIDATION_QUERY, DEFAULT_MAX_WAIT);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/backend/utils/DateGuesser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/backend/utils/DateGuesser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,65 +8,66 @@
 
 package org.dive4elements.river.backend.utils;
 
-import java.util.Date;
 import java.util.Calendar;
+import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
+import org.dive4elements.river.model.TimeInterval;
 
 public final class DateGuesser {
     public static final String [] MONTH = {
-        "jan", "feb", "mrz", "apr", "mai", "jun",
-        "jul", "aug", "sep", "okt", "nov", "dez"
+            "jan", "feb", "mrz", "apr", "mai", "jun",
+            "jul", "aug", "sep", "okt", "nov", "dez"
     };
 
-    public static final int guessMonth(String s) {
-        s = s.toLowerCase();
+    public static final int guessMonth(final String s) {
+        final String t = s.toLowerCase();
         for (int i = 0; i < MONTH.length; ++i)
-            if (MONTH[i].equals(s)) {
+            if (MONTH[i].equals(t)) {
                 return i;
             }
         return -1;
     }
 
     public static final Pattern YYYY_MM_DD =
-        Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$");
+            Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$");
 
     public static final Pattern DD_MM_YYYY =
-        Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})$");
+            Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})$");
 
     public static final Pattern MMM_YYYY =
-        Pattern.compile("^(\\d{0,2})\\.?(\\w{3})\\.?(\\d{2,4})$");
+            Pattern.compile("^((\\d{1,2})\\.)?(\\w{3})[\\. -]?((\\d\\d)|(\\d{4}))$");
 
     public static final Pattern GARBAGE_YYYY =
-        Pattern.compile("^\\D*(\\d{2,4})$");
+            Pattern.compile("^[^\\d=]*((\\d\\d)|([12]\\d{3}))$");
 
     public static final Pattern YYYY_MM_DDThh_mm =
-        Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})$");
+            Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})$");
 
     public static final Pattern YYYY_MM_DDThh_mm_ss =
-        Pattern.compile(
-            "^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$");
+            Pattern.compile(
+                    "^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$");
 
     public static final Pattern DD_MM_YYYYThh_mm =
-        Pattern.compile(
-            "^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})T(\\d{1,2}):(\\d{2})$");
+            Pattern.compile(
+                    "^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})T(\\d{1,2}):(\\d{2})$");
 
     public static final Pattern DD_MM_YYYYThh_mm_ss =
-        Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})"
-            + "T(\\d{1,2}):(\\d{2}):(\\d{2})$");
+            Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})"
+                    + "T(\\d{1,2}):(\\d{2}):(\\d{2})$");
 
     public static final Pattern DDMMYY =
-        Pattern.compile("^(\\d{2})(\\d{2})(\\d{2})$");
+            Pattern.compile("^(\\d{2})(\\d{2})(\\d{2})$");
 
     private DateGuesser() {
     }
 
-    public static final int calendarMonth(String month) {
+    public static final int calendarMonth(final String month) {
         return calendarMonth(Integer.parseInt(month));
     }
 
-    public static final int calendarMonth(int month) {
+    public static final int calendarMonth(final int month) {
         return Math.max(Math.min(month-1, 11), 0);
     }
 
@@ -76,156 +77,157 @@
      * @param s The date to be guessed (e.g. 11.02.2001).
      * @return the parsed Date.
      */
-    public static Date guessDate(String s) {
-        if (s == null || (s = s.trim()).length() == 0) {
+    public static Date guessDate(final String s) {
+        if ((s == null) || s.trim().isEmpty()) {
             throw new IllegalArgumentException();
         }
 
+        final String t = s.trim();
         Matcher m;
 
-        m = YYYY_MM_DD.matcher(s);
+        m = YYYY_MM_DD.matcher(t);
 
         if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String year  = m.group(1);
-            String month = m.group(2);
-            String day   = m.group(3);
+            final Calendar cal = Calendar.getInstance();
+            final String year  = m.group(1);
+            final String month = m.group(2);
+            final String day   = m.group(3);
             cal.clear();
             cal.set(
-                Integer.parseInt(year),
-                calendarMonth(month),
-                Integer.parseInt(day),
-                12, 0, 0);
+                    Integer.parseInt(year),
+                    calendarMonth(month),
+                    Integer.parseInt(day),
+                    12, 0, 0);
             return cal.getTime();
         }
 
-        m = DD_MM_YYYY.matcher(s);
+        m = DD_MM_YYYY.matcher(t);
 
         if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String year  = m.group(3);
-            String month = m.group(2);
-            String day   = m.group(1);
+            final Calendar cal = Calendar.getInstance();
+            final String year  = m.group(3);
+            final String month = m.group(2);
+            final String day   = m.group(1);
             cal.clear();
             cal.set(
-                Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
-                calendarMonth(month),
-                Integer.parseInt(day),
-                12, 0, 0);
+                    Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
+                    calendarMonth(month),
+                    Integer.parseInt(day),
+                    12, 0, 0);
             return cal.getTime();
         }
 
-        m = MMM_YYYY.matcher(s);
+        m = MMM_YYYY.matcher(t);
 
         if (m.matches()) {
-            int month = guessMonth(m.group(2));
+            final int month = guessMonth(m.group(3));
             if (month >= 0) {
-                Calendar cal = Calendar.getInstance();
-                String year = m.group(3);
-                String day  = m.group(1);
+                final Calendar cal = Calendar.getInstance();
+                final String year = m.group(4);
+                final String day = m.group(1);
                 cal.clear();
                 cal.set(
-                    Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
-                    month,
-                    day.length() == 0 ? 15 : Integer.parseInt(day),
-                    12, 0, 0);
+                        Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
+                        month,
+                        ((day == null) || day.isEmpty()) ? 15 : Integer.parseInt(day),
+                                12, 0, 0);
                 return cal.getTime();
             }
         }
 
-        m = YYYY_MM_DDThh_mm.matcher(s);
+        m = YYYY_MM_DDThh_mm.matcher(t);
 
         if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String year = m.group(1);
-            String month = m.group(2);
-            String day = m.group(3);
-            String hour = m.group(4);
-            String minute = m.group(5);
+            final Calendar cal = Calendar.getInstance();
+            final String year = m.group(1);
+            final String month = m.group(2);
+            final String day = m.group(3);
+            final String hour = m.group(4);
+            final String minute = m.group(5);
             cal.clear();
             cal.set(
-                Integer.parseInt(year),
-                calendarMonth(month),
-                Integer.parseInt(day),
-                Integer.parseInt(hour),
-                Integer.parseInt(minute),
-                0
-            );
-            return cal.getTime();
-        }
-
-        m = YYYY_MM_DDThh_mm_ss.matcher(s);
-
-        if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String year = m.group(1);
-            String month = m.group(2);
-            String day = m.group(3);
-            String hour = m.group(4);
-            String minute = m.group(5);
-            String second = m.group(6);
-            cal.clear();
-            cal.set(
-                Integer.parseInt(year),
-                calendarMonth(month),
-                Integer.parseInt(day),
-                Integer.parseInt(hour),
-                Integer.parseInt(minute),
-                Integer.parseInt(second)
-            );
+                    Integer.parseInt(year),
+                    calendarMonth(month),
+                    Integer.parseInt(day),
+                    Integer.parseInt(hour),
+                    Integer.parseInt(minute),
+                    0
+                    );
             return cal.getTime();
         }
 
-        m = DD_MM_YYYYThh_mm.matcher(s);
+        m = YYYY_MM_DDThh_mm_ss.matcher(t);
 
         if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String year = m.group(3);
-            String month = m.group(2);
-            String day = m.group(1);
-            String hour = m.group(4);
-            String minute = m.group(5);
+            final Calendar cal = Calendar.getInstance();
+            final String year = m.group(1);
+            final String month = m.group(2);
+            final String day = m.group(3);
+            final String hour = m.group(4);
+            final String minute = m.group(5);
+            final String second = m.group(6);
             cal.clear();
             cal.set(
-                Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
-                calendarMonth(month),
-                Integer.parseInt(day),
-                Integer.parseInt(hour),
-                Integer.parseInt(minute),
-                0
-            );
+                    Integer.parseInt(year),
+                    calendarMonth(month),
+                    Integer.parseInt(day),
+                    Integer.parseInt(hour),
+                    Integer.parseInt(minute),
+                    Integer.parseInt(second)
+                    );
             return cal.getTime();
         }
 
-        m = DD_MM_YYYYThh_mm_ss.matcher(s);
+        m = DD_MM_YYYYThh_mm.matcher(t);
 
         if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String year = m.group(3);
-            String month = m.group(2);
-            String day = m.group(1);
-            String hour = m.group(4);
-            String minute = m.group(5);
-            String second = m.group(6);
+            final Calendar cal = Calendar.getInstance();
+            final String year = m.group(3);
+            final String month = m.group(2);
+            final String day = m.group(1);
+            final String hour = m.group(4);
+            final String minute = m.group(5);
             cal.clear();
             cal.set(
-                Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
-                calendarMonth(month),
-                Integer.parseInt(day),
-                Integer.parseInt(hour),
-                Integer.parseInt(minute),
-                Integer.parseInt(second)
-            );
+                    Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
+                    calendarMonth(month),
+                    Integer.parseInt(day),
+                    Integer.parseInt(hour),
+                    Integer.parseInt(minute),
+                    0
+                    );
             return cal.getTime();
         }
 
-        m = DDMMYY.matcher(s);
+        m = DD_MM_YYYYThh_mm_ss.matcher(t);
 
         if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String day   = m.group(1);
-            String month = m.group(2);
-            String yearS = m.group(3);
+            final Calendar cal = Calendar.getInstance();
+            final String year = m.group(3);
+            final String month = m.group(2);
+            final String day = m.group(1);
+            final String hour = m.group(4);
+            final String minute = m.group(5);
+            final String second = m.group(6);
+            cal.clear();
+            cal.set(
+                    Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
+                    calendarMonth(month),
+                    Integer.parseInt(day),
+                    Integer.parseInt(hour),
+                    Integer.parseInt(minute),
+                    Integer.parseInt(second)
+                    );
+            return cal.getTime();
+        }
+
+        m = DDMMYY.matcher(t);
+
+        if (m.matches()) {
+            final Calendar cal = Calendar.getInstance();
+            final String day   = m.group(1);
+            final String month = m.group(2);
+            final String yearS = m.group(3);
             int year = Integer.parseInt(yearS);
 
             if (year <= cal.get(Calendar.YEAR) % 100) {
@@ -234,33 +236,35 @@
             else {
                 year += 1900;
             }
+            // TODO Warning: two digit year
             cal.clear();
             cal.set(
-                year,
-                Integer.parseInt(month),  // month
-                Integer.parseInt(day), // day
-                12, 0, 0);
+                    year,
+                    Integer.parseInt(month),  // month
+                    Integer.parseInt(day), // day
+                    12, 0, 0);
             return cal.getTime();
         }
 
-        m = GARBAGE_YYYY.matcher(s);
+        m = GARBAGE_YYYY.matcher(t);
 
-        if (m.matches()) {
-            Calendar cal = Calendar.getInstance();
-            String year = m.group(1);
+        if (m.matches() && !t.contains("HQ") && !t.contains("HW")) {
+            final Calendar cal = Calendar.getInstance();
+            final String year = m.group(1);
             cal.clear();
-            cal.set(
-                Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
-                5,  // month
-                15, // day
-                12, 0, 0);
+            cal.set(Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0),
+                    TimeInterval.YEAR_ONLY_DATE.get(Calendar.MONTH),
+                    TimeInterval.YEAR_ONLY_DATE.get(Calendar.DAY_OF_MONTH),
+                    TimeInterval.YEAR_ONLY_DATE.get(Calendar.HOUR_OF_DAY),
+                    TimeInterval.YEAR_ONLY_DATE.get(Calendar.MINUTE),
+                    TimeInterval.YEAR_ONLY_DATE.get(Calendar.SECOND));
             return cal.getTime();
         }
 
         throw new IllegalArgumentException();
     }
 
-    public static void main(String [] args) {
+    public static void main(final String [] args) {
         for (int i = 0; i < args.length; ++i) {
             System.out.println(args[i] + ": " + guessDate(args[i]));
         }
--- a/backend/src/main/java/org/dive4elements/river/importer/Config.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/Config.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,121 +11,164 @@
 public class Config
 {
     public static final String SKIP_DEFAULT =
-        "flys.backend.importer.skip.default";
+            "flys.backend.importer.skip.default";
 
     public static final String DRY_RUN =
-        "flys.backend.importer.dry.run";
+            "flys.backend.importer.dry.run";
 
     public static final String INFO_GEW_FILE =
-        "flys.backend.importer.infogew.file";
+            "flys.backend.importer.infogew.file";
 
     public static final String ANNOTATION_TYPES =
-        "flys.backend.importer.annotation.types";
+            "flys.backend.importer.annotation.types";
 
     public static final String SKIP_GAUGES =
-        "flys.backend.importer.skip.gauges";
+            "flys.backend.importer.skip.gauges";
 
     public static final String SKIP_BWASTR =
-        "flys.backend.importer.skip.bwastr";
+            "flys.backend.importer.skip.bwastr";
 
     public static final String SKIP_HISTORICAL_DISCHARGE_TABLES =
-        "flys.backend.importer.skip.historical.discharge.tables";
+            "flys.backend.importer.skip.historical.discharge.tables";
 
     public static final String SKIP_ANNOTATIONS =
-        "flys.backend.importer.skip.annotations";
+            "flys.backend.importer.skip.annotations";
 
     public static final String SKIP_PRFS =
-        "flys.backend.importer.skip.prfs";
+            "flys.backend.importer.skip.prfs";
 
     public static final String SKIP_DA50S =
-        "flys.backend.importer.skip.da50s";
+            "flys.backend.importer.skip.da50s";
 
     public static final String SKIP_W80S =
-        "flys.backend.importer.skip.w80s";
+            "flys.backend.importer.skip.w80s";
 
     public static final String SKIP_W80_CSVS =
-        "flys.backend.importer.skip.w80.csvs";
+            "flys.backend.importer.skip.w80.csvs";
 
     public static final String SKIP_HYKS =
-        "flys.backend.importer.skip.hyks";
+            "flys.backend.importer.skip.hyks";
 
     public static final String SKIP_WST =
-        "flys.backend.importer.skip.wst";
+            "flys.backend.importer.skip.wst";
 
     public static final String SKIP_EXTRA_WSTS =
-        "flys.backend.importer.skip.extra.wsts";
+            "flys.backend.importer.skip.extra.wsts";
 
     public static final String SKIP_FIXATIONS =
-        "flys.backend.importer.skip.fixations";
+            "flys.backend.importer.skip.fixations";
 
     public static final String SKIP_OFFICIAL_LINES =
-        "flys.backend.importer.skip.official.lines";
+            "flys.backend.importer.skip.official.lines";
 
     public static final String SKIP_FLOOD_WATER =
-        "flys.backend.importer.skip.flood.water";
+            "flys.backend.importer.skip.flood.water";
 
     public static final String SKIP_FLOOD_PROTECTION =
-        "flys.backend.importer.skip.flood.protection";
+            "flys.backend.importer.skip.flood.protection";
 
     public static final String SKIP_BED_HEIGHT =
-        "flys.backend.importer.skip.bed.height";
+            "flys.backend.importer.skip.bed.height";
 
     public static final String SKIP_DA66S =
-        "flys.backend.importer.skip.da66s";
+            "flys.backend.importer.skip.da66s";
 
     public static final String SKIP_SEDIMENT_DENSITY =
-        "flys.backend.importer.skip.sediment.density";
+            "flys.backend.importer.skip.sediment.density";
 
     public static final String SKIP_POROSITY =
-        "flys.backend.importer.skip.porosity";
+            "flys.backend.importer.skip.porosity";
 
     public static final String SKIP_MORPHOLOGICAL_WIDTH =
-        "flys.backend.importer.skip.morphological.width";
+            "flys.backend.importer.skip.morphological.width";
 
     public static final String SKIP_FLOW_VELOCITY =
-        "flys.backend.importer.skip.flow.velocity";
+            "flys.backend.importer.skip.flow.velocity";
 
     public static final String SKIP_SEDIMENT_LOAD_LS =
-        "flys.backend.importer.skip.sediment.load.ls";
+            "flys.backend.importer.skip.sediment.load.ls";
 
     public static final String SKIP_SEDIMENT_LOAD =
-        "flys.backend.importer.skip.sediment.load";
+            "flys.backend.importer.skip.sediment.load";
 
     public static final String SKIP_WATERLEVELS =
-        "flys.backend.importer.skip.waterlevels";
+            "flys.backend.importer.skip.waterlevels";
 
     public static final String SKIP_WATERLEVEL_DIFFERENCES =
-        "flys.backend.importer.skip.waterlevel.differences";
+            "flys.backend.importer.skip.waterlevel.differences";
 
     public static final String SKIP_MEASUREMENT_STATIONS =
-        "flys.backend.importer.skip.measurement.stations";
+            "flys.backend.importer.skip.measurement.stations";
 
     public static final String SKIP_SQ_RELATION =
-        "flys.backend.importer.skip.sq.relation";
+            "flys.backend.importer.skip.sq.relation";
 
     public static final Double CROSS_SECTION_SIMPLIFICATION_EPSILON =
-        getDouble("flys.backend.importer.cross.section.simplification.epsilon");
+            getDouble("flys.backend.importer.cross.section.simplification.epsilon");
 
 
+    private enum SInfoSkip {
+        BED_MOBILITY("bed_mobility"), //
+        SELECTED_ADDITIONAL("selected_additional"), //
+        INFRASTRUCTURE("infrastructure"), //
+        CHANNEL("channel"), //
+        COLLISION("collision"), //
+        DAILY_DISCHARGE("daily_discharge"), //
+        TKH("tkh"), //
+        FLOW_DEPTH("flow_depth"), //
+        DEPTH_EVOLUTION("depth_evolution");
+
+        private final String name;
+
+        private SInfoSkip(final String suffix) {
+            this.name = "flys.backend.importer.skip.sinfo." + suffix;
+        }
+
+        public String getName() {
+            return this.name;
+        }
+
+        public boolean getFlag() {
+            return Config.getFlag(getName());
+        }
+    }
+
+    private enum UInfoSkip {
+        SALIX("salix"), //
+        VEGETATION("vegetation");
+
+        private final String name;
+
+        private UInfoSkip(final String suffix) {
+            this.name = "flys.backend.importer.skip.uinfo." + suffix;
+        }
+
+        public String getName() {
+            return this.name;
+        }
+
+        public boolean getFlag() {
+            return Config.getFlag(getName());
+        }
+    }
+
     public static final Config INSTANCE = new Config();
 
     private Config() {
     }
 
-    public static final boolean getFlag(String key) {
-        String flag = System.getProperty(key);
-        return flag != null
-            ? Boolean.valueOf(flag)
-            : Boolean.getBoolean(SKIP_DEFAULT);
+    public static final boolean getFlag(final String key) {
+        final String flag = System.getProperty(key);
+        return (flag != null) ? Boolean.valueOf(flag) : Boolean.getBoolean(SKIP_DEFAULT);
     }
 
-    public static final Double getDouble(String key) {
+    public static final Double getDouble(final String key) {
         try {
-            String value = System.getProperty(key);
+            final String value = System.getProperty(key);
             return value != null
-                ? Double.valueOf(value)
-                : null;
-        } catch (NumberFormatException nfe) {
+                    ? Double.valueOf(value)
+                            : null;
+        } catch (final NumberFormatException nfe) {
             return null;
         }
     }
@@ -253,5 +296,49 @@
     public boolean skipSQRelation() {
         return getFlag(SKIP_SQ_RELATION);
     }
+
+    public boolean skipSInfoBedMobility() {
+        return SInfoSkip.BED_MOBILITY.getFlag();
+    }
+
+    public boolean skipSInfoSelectedAdditional() {
+        return SInfoSkip.SELECTED_ADDITIONAL.getFlag();
+    }
+
+    public boolean skipSInfoInfrastructure() {
+        return SInfoSkip.INFRASTRUCTURE.getFlag();
+    }
+
+    public boolean skipSInfoChannel() {
+        return SInfoSkip.CHANNEL.getFlag();
+    }
+
+    public boolean skipSInfoCollision() {
+        return SInfoSkip.COLLISION.getFlag();
+    }
+
+    public boolean skipSInfoDailyDischarge() {
+        return SInfoSkip.DAILY_DISCHARGE.getFlag();
+    }
+
+    public boolean skipSInfoTkh() {
+        return SInfoSkip.TKH.getFlag();
+    }
+
+    public boolean skipSInfoFlowDepth() {
+        return SInfoSkip.FLOW_DEPTH.getFlag();
+    }
+
+    public boolean skipSInfoDepthEvolution() {
+        return SInfoSkip.DEPTH_EVOLUTION.getFlag();
+    }
+
+    public boolean skipUInfoSalix() {
+        return UInfoSkip.SALIX.getFlag();
+    }
+
+    public boolean skipUInfoVegetation() {
+        return UInfoSkip.VEGETATION.getFlag();
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportAnnotationType.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportAnnotationType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,56 +8,57 @@
 
 package org.dive4elements.river.importer;
 
+import java.util.List;
+
+import org.apache.log4j.Logger;
 import org.dive4elements.river.model.AnnotationType;
-
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import java.util.List;
 
 public class ImportAnnotationType
 implements   Comparable<ImportAnnotationType>
 {
+    private static final Logger log = Logger.getLogger(ImportAnnotationType.class);
     protected String         name;
     protected AnnotationType peer;
 
     public ImportAnnotationType() {
     }
 
-    public ImportAnnotationType(String name) {
+    public ImportAnnotationType(final String name) {
         this.name = name;
     }
 
-    public int compareTo(ImportAnnotationType other) {
-        return name.compareTo(other.name);
+    @Override
+    public int compareTo(final ImportAnnotationType other) {
+        return this.name.compareTo(other.name);
     }
 
     public String getName() {
-        return name;
+        return this.name;
     }
 
-    public void setName(String name) {
+    public void setName(final String name) {
         this.name = name;
     }
 
 
     public AnnotationType getPeer() {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from AnnotationType where name=:name");
-            query.setParameter("name", name);
-            List<AnnotationType> types = query.list();
-            if (types.isEmpty()) {
-                peer = new AnnotationType(name);
-                session.save(peer);
-            }
-            else {
-                peer = types.get(0);
-            }
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM AnnotationType WHERE lower(name)=:name");
+        query.setParameter("name", this.name.trim().toLowerCase());
+        final List<AnnotationType> types = query.list();
+        if (types.isEmpty()) {
+            this.peer = new AnnotationType(this.name);
+            session.save(this.peer);
+            log.info(String.format("Create new database instance: %d, '%s'", this.peer.getId(), this.name));
         }
-        return peer;
+        else {
+            this.peer = types.get(0);
+        }
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportAttribute.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportAttribute.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,12 +8,11 @@
 
 package org.dive4elements.river.importer;
 
+import java.util.List;
+
 import org.dive4elements.river.model.Attribute;
-
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import java.util.List;
 
 public class ImportAttribute
 implements   Comparable<ImportAttribute>
@@ -25,51 +24,52 @@
     public ImportAttribute() {
     }
 
-    public ImportAttribute(String value) {
+    public ImportAttribute(final String value) {
         this.value = value;
     }
 
     public String getValue() {
-        return value;
+        return this.value;
     }
 
-    public void setValue(String value) {
+    public void setValue(final String value) {
         this.value = value;
     }
 
-    public int compareTo(ImportAttribute other) {
-        return value.compareTo(other.value);
+    @Override
+    public int compareTo(final ImportAttribute other) {
+        return this.value.compareTo(other.value);
     }
 
     @Override
-    public boolean equals(Object other) {
-        if (other == this) return true;
-        if (!(other instanceof ImportAttribute)) return false;
-        return value.equals(((ImportAttribute)other).value);
+    public boolean equals(final Object other) {
+        if (other == this)
+            return true;
+        if (!(other instanceof ImportAttribute))
+            return false;
+        return this.value.equals(((ImportAttribute) other).value);
     }
 
     @Override
     public int hashCode() {
-        return value.hashCode();
+        return this.value.hashCode();
     }
 
     public Attribute getPeer() {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from Attribute where value=:value");
-            query.setString("value", value);
-            List<Attribute> attributes = query.list();
-            if (attributes.isEmpty()) {
-                peer = new Attribute(value);
-                session.save(peer);
-            }
-            else {
-                peer = attributes.get(0);
-            }
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM Attribute WHERE lower(value)=:value");
+        query.setString("value", this.value.trim().toLowerCase());
+        final List<Attribute> attributes = query.list();
+        if (attributes.isEmpty()) {
+            this.peer = new Attribute(this.value);
+            session.save(this.peer);
         }
-        return peer;
+        else {
+            this.peer = attributes.get(0);
+        }
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeight.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeight.java	Fri Jul 13 11:56:22 2018 +0200
@@ -12,15 +12,14 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.BedHeight;
 import org.dive4elements.river.model.BedHeightType;
 import org.dive4elements.river.model.ElevationModel;
 import org.dive4elements.river.model.Range;
 import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportBedHeight
@@ -37,165 +36,160 @@
     protected ImportLocationSystem locationSystem;
     protected ImportElevationModel curElevationModel;
     protected ImportElevationModel oldElevationModel;
+    protected String sounding_width_info;
+    protected String notes;
 
     protected List<ImportBedHeightValue> values;
 
+    protected StoreMode storeMode;
+
     protected BedHeight peer;
 
 
-    public ImportBedHeight(String description) {
+    public ImportBedHeight(final String description) {
         this.description = description;
-        this.values      = new ArrayList<ImportBedHeightValue>();
+        this.values      = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
 
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
     public int getValueCount() {
-        return values.size();
+        return this.values.size();
     }
 
 
-    public void setYear(int year) {
+    public void setYear(final int year) {
         this.year = year;
     }
 
-    public void setTimeInterval(ImportTimeInterval timeInterval) {
+    public void setTimeInterval(final ImportTimeInterval timeInterval) {
         // do nothing
     }
 
-    public void setEvaluationBy(String evaluationBy) {
+    public void setEvaluationBy(final String evaluationBy) {
         this.evaluationBy = evaluationBy;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
-    public void setRange(ImportRange range) {
+    public void setRange(final ImportRange range) {
         this.range = range;
     }
 
-    public void setType(ImportBedHeightType type) {
+    public void setType(final ImportBedHeightType type) {
         this.type = type;
     }
 
-    public void setLocationSystem(ImportLocationSystem locationSystem) {
+    public void setLocationSystem(final ImportLocationSystem locationSystem) {
         this.locationSystem = locationSystem;
     }
 
-    public void setCurElevationModel(ImportElevationModel curElevationModel) {
+    public void setCurElevationModel(final ImportElevationModel curElevationModel) {
         this.curElevationModel = curElevationModel;
     }
 
-    public void setOldElevationModel(ImportElevationModel oldElevationModel) {
+    public void setOldElevationModel(final ImportElevationModel oldElevationModel) {
         this.oldElevationModel = oldElevationModel;
     }
 
-    public void addValue(ImportBedHeightValue value) {
-        values.add((ImportBedHeightValue) value);
+    public void setSoundingWidthInfo(final String sounding_width_info) {
+        this.sounding_width_info = sounding_width_info;
     }
 
-    public void storeDependencies(River river) {
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    public void addValue(final ImportBedHeightValue value) {
+        this.values.add(value);
+    }
+
+    public void storeDependencies(final River river) {
         log.info("Store dependencies for single: '" + getDescription() + "'");
 
-        if (type != null) {
-            type.storeDependencies();
+        if (this.type != null) {
+            this.type.storeDependencies();
         }
 
-        if (locationSystem != null) {
-            locationSystem.storeDependencies();
-        }
-
-        if (curElevationModel != null) {
-            curElevationModel.storeDependencies();
+        if (this.locationSystem != null) {
+            this.locationSystem.storeDependencies();
         }
 
-        if (oldElevationModel != null) {
-            oldElevationModel.storeDependencies();
+        if (this.curElevationModel != null) {
+            this.curElevationModel.storeDependencies();
         }
 
-        BedHeight peer = getPeer(river);
+        if (this.oldElevationModel != null) {
+            this.oldElevationModel.storeDependencies();
+        }
+
+        final BedHeight peer = getPeer(river);
 
         if (peer != null) {
-            for (ImportBedHeightValue value: values) {
+            for (final ImportBedHeightValue value: this.values) {
                 value.storeDependencies(peer);
             }
         }
 
-        Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
         session.flush();
     }
 
-    public BedHeight getPeer(River river) {
-        if (peer == null) {
-            BedHeightType  theType     = type != null ? type.getPeer() : null;
-            ElevationModel theCurModel = curElevationModel.getPeer();
-            Range          theRange    = range != null
-                ? range.getPeer(river)
-                : null;
-
-            if (theType == null) {
-                log.warn("BHS: No bed height type given. Skip file '" +
-                    description + "'");
-                return null;
-            }
-
-            if (theCurModel == null) {
-                log.warn("BHS: No elevation model given. Skip file '" +
-                    description + "'");
-                return null;
-            }
-
-            if (theRange == null) {
-                log.warn("BHS: No km-range given: '" +
-                    description + "'");
-            }
-
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
+    public BedHeight getPeer(final River river) {
+        if (this.peer != null)
+            return null;
 
-            Query query = session.createQuery(
-                "from BedHeight where " +
-                "river=:river and year=:year " +
-                "and type=:type and locationSystem=:locationSystem and " +
-                "curElevationModel=:curElevationModel and range=:range");
-
-            query.setParameter("river", river);
-            query.setParameter("year", year);
-            query.setParameter("type", theType);
-            query.setParameter("locationSystem", locationSystem.getPeer());
-            query.setParameter("curElevationModel", theCurModel);
-            query.setParameter("range", range.getPeer(river));
-
-            List<BedHeight> bedHeights = query.list();
-            if (bedHeights.isEmpty()) {
-                log.info("Create new BedHeight DB instance.");
+        final BedHeightType theType = this.type != null ? this.type.getPeer() : null;
+        final ElevationModel theCurModel = this.curElevationModel.getPeer();
+        final Range theRange = (this.range != null) ? this.range.getPeer(river) : null;
 
-                peer = new BedHeight(
-                    river,
-                    year,
-                    theType,
-                    locationSystem.getPeer(),
-                    theCurModel,
-                    oldElevationModel != null
-                        ? oldElevationModel.getPeer()
-                        : null,
-                    range.getPeer(river),
-                    evaluationBy,
-                    description
-                );
-
-                session.save(peer);
-            }
-            else {
-                peer = bedHeights.get(0);
-            }
+        if (theType == null) {
+            log.warn("BHS: No bed height type given. Skip file '" + this.description + "'");
+            return null;
         }
 
-        return peer;
+        if (theCurModel == null) {
+            log.warn("BHS: No elevation model given. Skip file '" + this.description + "'");
+            return null;
+        }
+
+        if (theRange == null) {
+            log.warn("BHS: No km-range given: '" + this.description + "'");
+        }
+
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+
+        final Query query = session.createQuery("FROM BedHeight WHERE (river=:river) AND (year=:year)"
+                + " AND (type=:type) AND (locationSystem=:locationSystem)"
+                + " AND (curElevationModel=:curElevationModel) AND (range=:range)");
+        query.setParameter("river", river);
+        query.setParameter("year", this.year);
+        query.setParameter("type", theType);
+        query.setParameter("locationSystem", this.locationSystem.getPeer());
+        query.setParameter("curElevationModel", theCurModel);
+        query.setParameter("range", this.range.getPeer(river));
+
+        final List<BedHeight> bedHeights = query.list();
+        if (bedHeights.isEmpty()) {
+            log.info("Create new BedHeight DB instance.");
+            this.peer = new BedHeight(river, this.year, theType, this.locationSystem.getPeer(), theCurModel,
+                    (this.oldElevationModel != null) ? this.oldElevationModel.getPeer() : null, this.range.getPeer(river),
+                            this.evaluationBy, this.description, this.sounding_width_info, this.notes);
+            session.save(this.peer);
+            this.storeMode = StoreMode.INSERT;
+        }
+        else {
+            this.peer = bedHeights.get(0);
+            this.storeMode = StoreMode.UPDATE;
+        }
+
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightType.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,29 +11,27 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.model.BedHeightType;
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.model.BedHeightType;
 
 
 public class ImportBedHeightType {
 
     private static final Logger log =
-        Logger.getLogger(ImportBedHeightType.class);
+            Logger.getLogger(ImportBedHeightType.class);
 
     protected String name;
 
     protected BedHeightType peer;
 
-    public ImportBedHeightType(BedHeightType peer)  {
+    public ImportBedHeightType(final BedHeightType peer)  {
         this.peer = peer;
-        name = peer.getName();
+        this.name = peer.getName();
     }
 
 
-    public ImportBedHeightType(String name) {
+    public ImportBedHeightType(final String name) {
         this.name        = name;
     }
 
@@ -44,27 +42,19 @@
 
 
     public BedHeightType getPeer() {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-
-            Query query = session.createQuery("from BedHeightType "
-                + "where name=:name and description=:description");
-
-            query.setParameter("name", name);
-
-            List<BedHeightType> types = query.list();
-
-            if (types.isEmpty()) {
-                peer = new BedHeightType(name);
-                session.save(peer);
-            }
-            else {
-                peer = types.get(0);
-            }
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM BedHeightType WHERE (trim(name)=:name) AND (trim(description)=:description)");
+        query.setParameter("name", this.name);
+        final List<BedHeightType> types = query.list();
+        if (types.isEmpty()) {
+            this.peer = new BedHeightType(this.name);
+            session.save(this.peer);
+        } else {
+            this.peer = types.get(0);
         }
-
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightValue.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,18 +11,16 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.BedHeight;
 import org.dive4elements.river.model.BedHeightValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportBedHeightValue {
 
-    private static final Logger log =
-        Logger.getLogger(ImportBedHeightValue.class);
+    private static final Logger log = Logger.getLogger(ImportBedHeightValue.class);
 
 
     protected ImportBedHeight bedHeight;
@@ -32,28 +30,32 @@
     protected Double uncertainty;
     protected Double dataGap;
     protected Double soundingWidth;
+    protected Double minHeight;
+    protected Double maxHeight;
+    protected Double[] sectionHeight;
 
     protected BedHeightValue peer;
 
 
-    public ImportBedHeightValue(
-        ImportBedHeight bedHeight,
-        Double station,
-        Double height,
-        Double uncertainty,
-        Double dataGap,
-        Double soundingWidth
-    ) {
+    public ImportBedHeightValue(final ImportBedHeight bedHeight, final Double station, final Double height, final Double uncertainty, final Double dataGap,
+            final Double soundingWidth, final Double minHeight, final Double maxHeight) {
         this.bedHeight     = bedHeight;
         this.station       = station;
         this.height        = height;
         this.uncertainty   = uncertainty;
         this.dataGap       = dataGap;
         this.soundingWidth = soundingWidth;
+        this.minHeight = minHeight;
+        this.maxHeight = maxHeight;
+        this.sectionHeight = new Double[10];
     }
 
 
-    public void storeDependencies(BedHeight bedHeight) {
+    public void setSectionHeight(final int index, final Double value) {
+        this.sectionHeight[index - 1] = value;
+    }
+
+    public void storeDependencies(final BedHeight bedHeight) {
         getPeer(bedHeight);
     }
 
@@ -62,37 +64,31 @@
      * Add this value to database or return database bound Value, assuring
      * that the BedHeight exists in db already.
      */
-    public BedHeightValue getPeer(BedHeight bedHeight) {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-
-            Query query = session.createQuery(
-                "from BedHeightValue where " +
-                "   bedHeight=:bedHeight and " +
-                "   station=:station");
-
-            query.setParameter("bedHeight", bedHeight);
-            query.setParameter("station", station);
+    public BedHeightValue getPeer(final BedHeight bedHeight) {
+        if (this.peer != null)
+            return this.peer;
 
-            List<BedHeightValue> values = query.list();
-            if (values.isEmpty()) {
-                peer = new BedHeightValue(
-                    bedHeight,
-                    station,
-                    height,
-                    uncertainty,
-                    dataGap,
-                    soundingWidth
-                );
-                session.save(peer);
-            }
-            else {
-                peer = values.get(0);
-            }
+        List<BedHeightValue> values;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        if (this.bedHeight.storeMode == StoreMode.INSERT)
+            values = null;
+        else {
+            final Query query = session.createQuery("FROM BedHeightValue WHERE (bedHeight=:bedHeight)"
+                    + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+            query.setParameter("bedHeight", bedHeight);
+            query.setParameter("station", this.station);
+            values = query.list();
         }
-
-        return peer;
+        if ((values == null) || values.isEmpty()) {
+            this.peer = new BedHeightValue(bedHeight, this.station, this.height, this.uncertainty, this.dataGap, this.soundingWidth,
+                    this.minHeight, this.maxHeight);
+            for (int i = 1; i <= 10; i++)
+                this.peer.setSectionHeight(i, this.sectionHeight[i - 1]);
+            session.save(this.peer);
+        } else {
+            this.peer = values.get(0);
+        }
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportCrossSection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportCrossSection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,16 +8,15 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.River;
-import org.dive4elements.river.model.CrossSection;
-import org.dive4elements.river.model.TimeInterval;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
 import java.util.List;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.CrossSection;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.TimeInterval;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 /** CrossSection to be imported, holds list of ImportCrossSectionLines. */
 public class ImportCrossSection
@@ -28,6 +27,7 @@
     protected String                       description;
     protected ImportTimeInterval           timeInterval;
     protected List<ImportCrossSectionLine> lines;
+    protected StoreMode storeMode;
 
     protected CrossSection peer;
 
@@ -35,94 +35,97 @@
     }
 
     public ImportCrossSection(
-        ImportRiver                  river,
-        String                       description,
-        ImportTimeInterval           timeInterval,
-        List<ImportCrossSectionLine> lines
-    ) {
+            final ImportRiver                  river,
+            final String                       description,
+            final ImportTimeInterval           timeInterval,
+            final List<ImportCrossSectionLine> lines
+            ) {
         this.river        = river;
         this.description  = description;
         this.timeInterval = timeInterval;
         this.lines        = lines;
+        this.storeMode = StoreMode.NONE;
         wireWithLines();
     }
 
     public void wireWithLines() {
-        for (ImportCrossSectionLine line: lines) {
+        for (final ImportCrossSectionLine line: this.lines) {
             line.setCrossSection(this);
         }
     }
 
     public ImportRiver getRiver() {
-        return river;
+        return this.river;
     }
 
-    public void setRiver(ImportRiver river) {
+    public void setRiver(final ImportRiver river) {
         this.river = river;
     }
 
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
     public ImportTimeInterval getTimeInterval() {
-        return timeInterval;
+        return this.timeInterval;
     }
 
-    public void setTimeInterval(ImportTimeInterval timeInterval) {
+    public void setTimeInterval(final ImportTimeInterval timeInterval) {
         this.timeInterval = timeInterval;
     }
 
     public void storeDependencies() {
 
-        log.info("store cross section '" + description + "'");
+        log.info("store cross section '" + this.description + "'");
 
         getPeer();
 
-        int i = 1, N = lines.size();
+        // int i = 1;
+        // final int N = this.lines.size();
 
-        for (ImportCrossSectionLine line: lines) {
+        for (final ImportCrossSectionLine line: this.lines) {
             line.storeDependencies();
-            log.info("  stored " + i + " lines. remaining: " + (N-i));
-            ++i;
+            // log.info(" stored " + i + " lines. remaining: " + (N-i));
+            // ++i;
         }
+        log.info(" lines stored: " + this.lines.size());
     }
 
     public CrossSection getPeer() {
 
-        if (peer == null) {
-            River r = river.getPeer();
-            TimeInterval t = timeInterval != null
-                ? timeInterval.getPeer()
-                : null;
+        if (this.peer == null) {
+            final River r = this.river.getPeer();
+            final TimeInterval t = (this.timeInterval != null) ? this.timeInterval.getPeer() : null;
 
-            Session session =
-                ImporterSession.getInstance().getDatabaseSession();
+            final Session session =
+                    ImporterSession.getInstance().getDatabaseSession();
 
-            Query query = session.createQuery(
-                "from CrossSection where " +
-                "river=:r and "            +
-                "timeInterval=:t and "     +
-                "description=:d");
+            final Query query = session.createQuery(
+                    "from CrossSection where " +
+                            "river=:r and "            +
+                            "timeInterval=:t and "     +
+                    "description=:d");
 
             query.setParameter("r", r);
             query.setParameter("t", t);
-            query.setParameter("d", description);
+            query.setParameter("d", this.description);
 
-            List<CrossSection> crossSections = query.list();
+            final List<CrossSection> crossSections = query.list();
             if (crossSections.isEmpty()) {
-                peer = new CrossSection(r, t, description);
-                session.save(peer);
+                this.peer = new CrossSection(r, t, this.description);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = crossSections.get(0);
+                this.peer = crossSections.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportCrossSectionLine.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportCrossSectionLine.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,18 +8,18 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.CrossSection;
-import org.dive4elements.river.model.CrossSectionPoint;
-import org.dive4elements.river.model.CrossSectionLine;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import java.util.Comparator;
 import java.util.List;
-import java.util.Comparator;
 import java.util.Map;
 import java.util.TreeMap;
 
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.CrossSection;
+import org.dive4elements.river.model.CrossSectionLine;
+import org.dive4elements.river.model.CrossSectionPoint;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
 /**
  * A CrossSectionLine (containing points) ready to be transformed into a mapped
  * object and written to db (used in importer).
@@ -27,39 +27,42 @@
 public class ImportCrossSectionLine
 {
     public static final Comparator<CrossSectionPoint> INDEX_CMP =
-        new Comparator<CrossSectionPoint>() {
-            public int compare(CrossSectionPoint a, CrossSectionPoint b) {
-                return a.getColPos().compareTo(b.getColPos());
-            }
-        };
+            new Comparator<CrossSectionPoint>() {
+        @Override
+        public int compare(final CrossSectionPoint a, final CrossSectionPoint b) {
+            return a.getColPos().compareTo(b.getColPos());
+        }
+    };
 
     protected Double km;
     protected ImportCrossSection crossSection;
     protected List<XY> points;
+    protected StoreMode storeMode;
 
     protected CrossSectionLine peer;
 
     public ImportCrossSectionLine() {
     }
 
-    public ImportCrossSectionLine(Double km, List<XY> points) {
+    public ImportCrossSectionLine(final Double km, final List<XY> points) {
         this.km     = km;
         this.points = points;
+        this.storeMode = StoreMode.NONE;
     }
 
     public ImportCrossSection getCrossSection() {
-        return crossSection;
+        return this.crossSection;
     }
 
-    public void setCrossSection(ImportCrossSection crossSection) {
+    public void setCrossSection(final ImportCrossSection crossSection) {
         this.crossSection = crossSection;
     }
 
     public Double getKm() {
-        return km;
+        return this.km;
     }
 
-    public void setKm(Double km) {
+    public void setKm(final Double km) {
         this.km = km;
     }
 
@@ -70,35 +73,37 @@
 
     /** Write a line and its points. */
     protected void storePoints() {
-        CrossSectionLine csl = getPeer();
-
-        Map<CrossSectionPoint, CrossSectionPoint> map =
-            new TreeMap<CrossSectionPoint, CrossSectionPoint>(INDEX_CMP);
+        final CrossSectionLine csl = getPeer();
+        if (this.storeMode == StoreMode.INSERT) {
+            insertPoints();
+            return;
+        }
+        final Map<CrossSectionPoint, CrossSectionPoint> map =
+                new TreeMap<>(INDEX_CMP);
 
         // Build index for faster (index) collision lookup.
-        List<CrossSectionPoint> ps = csl.getPoints();
+        final List<CrossSectionPoint> ps = csl.getPoints();
         if (ps != null) {
-            for (CrossSectionPoint point: ps) {
+            for (final CrossSectionPoint point: ps) {
                 map.put(point, point);
             }
         }
 
-        Session session =
-            ImporterSession.getInstance().getDatabaseSession();
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
 
-        CrossSectionPoint key = new CrossSectionPoint();
+        final CrossSectionPoint key = new CrossSectionPoint();
 
         // Somehow it looks as if even with the map it is still possible that
         // multiple points with same id enter hibernate (and then violate a
         // constraint). -> TODO
-        for (XY xy: points) {
+        for (final XY xy: this.points) {
             key.setColPos(xy.getIndex());
             CrossSectionPoint csp = map.get(key);
             if (csp == null) { // create new
                 csp = new CrossSectionPoint(
-                    csl, key.getColPos(),
-                    Double.valueOf(xy.getX()),
-                    Double.valueOf(xy.getY()));
+                        csl, key.getColPos(),
+                        Double.valueOf(xy.getX()),
+                        Double.valueOf(xy.getY()));
             }
             else { // update old
                 csp.setX(Double.valueOf(xy.getX()));
@@ -108,29 +113,41 @@
         }
     }
 
+    /**
+     * Insert the points of a new line into the database without previously querying the database
+     */
+    private void insertPoints() {
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        for (final XY xy : this.points) {
+            session.save(new CrossSectionPoint(getPeer(), xy.getIndex(), xy.getX(), xy.getY()));
+        }
+    }
+
     /** Pull database-mapped object from db, or create (and save) one. */
     public CrossSectionLine getPeer() {
-        if (peer == null) {
-            CrossSection cs = crossSection.getPeer();
-
-            Session session =
-                ImporterSession.getInstance().getDatabaseSession();
-
-            Query query = session.createQuery(
-                "from CrossSectionLine where crossSection=:cs and km=:km");
-            query.setParameter("cs", cs);
-            query.setParameter("km", km);
-
-            List<CrossSectionLine> lines = query.list();
-            if (lines.isEmpty()) {
-                peer = new CrossSectionLine(cs, km);
-                session.save(peer);
+        if (this.peer == null) {
+            final CrossSection cs = this.crossSection.getPeer();
+            final Session session = ImporterSession.getInstance().getDatabaseSession();
+            List<CrossSectionLine> lines;
+            if (this.crossSection.storeMode == StoreMode.INSERT)
+                lines = null;
+            else {
+                final Query query = session.createQuery("from CrossSectionLine where crossSection=:cs and km=:km");
+                query.setParameter("cs", cs);
+                query.setParameter("km", this.km);
+                lines = query.list();
+            }
+            if ((lines == null) || lines.isEmpty()) {
+                this.peer = new CrossSectionLine(cs, this.km);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = lines.get(0);
+                this.peer = lines.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportElevationModel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportElevationModel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,17 +11,15 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.model.ElevationModel;
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.model.ElevationModel;
 
 
 public class ImportElevationModel {
 
     private static final Logger log =
-        Logger.getLogger(ImportElevationModel.class);
+            Logger.getLogger(ImportElevationModel.class);
 
     protected String name;
 
@@ -30,44 +28,40 @@
     protected ElevationModel peer;
 
 
-    public ImportElevationModel(String name, ImportUnit unit) {
+    public ImportElevationModel(final String name, final ImportUnit unit) {
         this.name = name;
         this.unit = unit;
     }
 
 
     public void storeDependencies() {
-        ElevationModel model = getPeer();
+        final ElevationModel model = getPeer();
     }
 
     public ElevationModel getPeer() {
-        if (unit == null) {
+        if (this.unit == null) {
             log.warn("No elevation model specified.");
             return null;
         }
-
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from ElevationModel where " +
-                "name=:name and unit=:unit");
-            query.setParameter("name", name);
-            query.setParameter("unit", unit.getPeer());
-            List<ElevationModel> models = query.list();
+        if (this.peer != null)
+            return this.peer;
 
-            if (models.isEmpty()) {
-                log.info("Create new ElevationModel DB instance.");
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM ElevationModel WHERE (trim(name)=:name) AND (unit=:unit)");
+        query.setParameter("name", this.name);
+        query.setParameter("unit", this.unit.getPeer());
+        final List<ElevationModel> models = query.list();
 
-                peer = new ElevationModel(name, unit.getPeer());
-                session.save(peer);
-            }
-            else {
-                peer = models.get(0);
-            }
+        if (models.isEmpty()) {
+            log.info("Create new ElevationModel DB instance.");
+
+            this.peer = new ElevationModel(this.name, this.unit.getPeer());
+            session.save(this.peer);
         }
-
-        return peer;
+        else {
+            this.peer = models.get(0);
+        }
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportFlowVelocityModel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportFlowVelocityModel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -12,75 +12,75 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.DischargeZone;
 import org.dive4elements.river.model.FlowVelocityModel;
 import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportFlowVelocityModel {
 
     private static final Logger log = Logger
-        .getLogger(ImportFlowVelocityModel.class);
+            .getLogger(ImportFlowVelocityModel.class);
 
     private String description;
 
     private ImportDischargeZone dischargeZone;
 
-    private List<ImportFlowVelocityModelValue> values;
+    private final List<ImportFlowVelocityModelValue> values;
+
+    protected StoreMode storeMode;
 
     private FlowVelocityModel peer;
 
     public ImportFlowVelocityModel() {
-        values = new ArrayList<ImportFlowVelocityModelValue>();
+        this.values = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
-    public ImportFlowVelocityModel(String description) {
+    public ImportFlowVelocityModel(final String description) {
         this();
-
         this.description = description;
     }
 
-    public ImportFlowVelocityModel(ImportDischargeZone dischargeZone,
-        String description) {
+    public ImportFlowVelocityModel(final ImportDischargeZone dischargeZone,
+            final String description) {
         this();
-
         this.dischargeZone = dischargeZone;
         this.description = description;
     }
 
-    public void setDischargeZone(ImportDischargeZone dischargeZone) {
+    public void setDischargeZone(final ImportDischargeZone dischargeZone) {
         this.dischargeZone = dischargeZone;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
-    public void addValue(ImportFlowVelocityModelValue value) {
+    public void addValue(final ImportFlowVelocityModelValue value) {
         this.values.add(value);
     }
 
-    public void storeDependencies(River river) {
+    public void storeDependencies(final River river) {
         log.debug("store dependencies");
 
-        if (dischargeZone == null) {
+        if (this.dischargeZone == null) {
             log.warn("skip flow velocity model: No discharge zone specified.");
             return;
         }
 
-        dischargeZone.storeDependencies(river);
+        this.dischargeZone.storeDependencies(river);
 
-        FlowVelocityModel peer = getPeer(river);
+        final FlowVelocityModel peer = getPeer(river);
 
         if (peer != null) {
             int i = 0;
 
-            for (ImportFlowVelocityModelValue value : values) {
-                value.storeDependencies(peer);
+            for (final ImportFlowVelocityModelValue value : this.values) {
+                value.storeDependencies(peer, this.storeMode);
                 i++;
             }
 
@@ -88,30 +88,32 @@
         }
     }
 
-    public FlowVelocityModel getPeer(River river) {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
+    public FlowVelocityModel getPeer(final River river) {
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
 
-            DischargeZone zone = dischargeZone.getPeer(river);
+            final DischargeZone zone = this.dischargeZone.getPeer(river);
 
-            Query query = session.createQuery("from FlowVelocityModel where "
-                + "   dischargeZone=:dischargeZone");
+            final Query query = session.createQuery("from FlowVelocityModel where "
+                    + "   dischargeZone=:dischargeZone");
 
             query.setParameter("dischargeZone", zone);
 
-            List<FlowVelocityModel> model = query.list();
+            final List<FlowVelocityModel> model = query.list();
 
             if (model.isEmpty()) {
-                peer = new FlowVelocityModel(zone, description);
-                session.save(peer);
+                this.peer = new FlowVelocityModel(zone, this.description);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = model.get(0);
+                this.peer = model.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
 
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportFlowVelocityModelValue.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportFlowVelocityModelValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,34 +9,33 @@
 package org.dive4elements.river.importer;
 
 import java.math.BigDecimal;
-
 import java.util.List;
 
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.FlowVelocityModel;
 import org.dive4elements.river.model.FlowVelocityModelValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportFlowVelocityModelValue {
 
-    private BigDecimal station;
-    private BigDecimal q;
-    private BigDecimal totalChannel;
-    private BigDecimal mainChannel;
-    private BigDecimal shearStress;
+    private final BigDecimal station;
+    private final BigDecimal q;
+    private final BigDecimal totalChannel;
+    private final BigDecimal mainChannel;
+    private final BigDecimal shearStress;
 
     private FlowVelocityModelValue peer;
 
 
     public ImportFlowVelocityModelValue(
-        BigDecimal station,
-        BigDecimal q,
-        BigDecimal totalChannel,
-        BigDecimal mainChannel,
-        BigDecimal shearStress
-    ) {
+            final BigDecimal station,
+            final BigDecimal q,
+            final BigDecimal totalChannel,
+            final BigDecimal mainChannel,
+            final BigDecimal shearStress
+            ) {
         this.station      = station;
         this.q            = q;
         this.totalChannel = totalChannel;
@@ -45,39 +44,41 @@
     }
 
 
-    public void storeDependencies(FlowVelocityModel model) {
-        getPeer(model);
+    public void storeDependencies(final FlowVelocityModel model, final StoreMode parentStoreMode) {
+        getPeer(model, parentStoreMode);
     }
 
 
-    public FlowVelocityModelValue getPeer(FlowVelocityModel model) {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
+    public FlowVelocityModelValue getPeer(final FlowVelocityModel model, final StoreMode parentStoreMode) {
+        if (this.peer == null) {
+            List<FlowVelocityModelValue> values;
+            final Session session = ImporterSession.getInstance().getDatabaseSession();
+            if (parentStoreMode == StoreMode.INSERT)
+                values = null;
+            else {
+                final Query query = session.createQuery(
+                        "from FlowVelocityModelValue where " +
+                                "   flowVelocity=:model and " +
+                                "   station between :station - 0.00001 and :station + 0.00001"
+                        );
 
-            Query query = session.createQuery(
-                "from FlowVelocityModelValue where " +
-                "   flowVelocity=:model and " +
-                "   station between :station - 0.00001 and :station + 0.00001"
-            );
+                query.setParameter("model", model);
+                query.setParameter("station", this.station.doubleValue());
 
-            query.setParameter("model", model);
-            query.setParameter("station", station.doubleValue());
-
-            List<FlowVelocityModelValue> values = query.list();
+                values = query.list();
+            }
+            if ((values == null) || values.isEmpty()) {
+                this.peer = new FlowVelocityModelValue(
+                        model, this.station, this.q, this.totalChannel, this.mainChannel, this.shearStress);
 
-            if (values.isEmpty()) {
-                peer = new FlowVelocityModelValue(
-                    model, station, q, totalChannel, mainChannel, shearStress);
-
-                session.save(peer);
+                session.save(this.peer);
             }
             else {
-                peer = values.get(0);
+                this.peer = values.get(0);
             }
         }
 
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportHYK.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportHYK.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,16 +8,15 @@
 
 package org.dive4elements.river.importer;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.HYK;
 import org.dive4elements.river.model.River;
-
-import java.util.List;
-import java.util.ArrayList;
-
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.apache.log4j.Logger;
 
 public class ImportHYK
 {
@@ -28,61 +27,66 @@
 
     protected List<ImportHYKEntry> entries;
 
+    protected StoreMode storeMode;
+
     protected HYK peer;
 
     public ImportHYK() {
-        entries = new ArrayList<ImportHYKEntry>();
+        this.entries = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
-    public ImportHYK(ImportRiver river, String description) {
+    public ImportHYK(final ImportRiver river, final String description) {
         this();
         this.river       = river;
         this.description = description;
     }
 
     public ImportRiver getRiver() {
-        return river;
+        return this.river;
     }
 
-    public void setRiver(ImportRiver river) {
+    public void setRiver(final ImportRiver river) {
         this.river = river;
     }
 
-    public void addEntry(ImportHYKEntry entry) {
-        entries.add(entry);
+    public void addEntry(final ImportHYKEntry entry) {
+        this.entries.add(entry);
         entry.setHYK(this);
     }
 
     public void storeDependencies() {
-        log.info("store HYK '" + description + "'");
+        log.info("store HYK '" + this.description + "'");
         getPeer();
-        for (int i = 0, N = entries.size(); i < N; ++i) {
-            ImportHYKEntry entry = entries.get(i);
+        for (int i = 0, N = this.entries.size(); i < N; ++i) {
+            final ImportHYKEntry entry = this.entries.get(i);
             log.info("  store km " + entry.getKm() +
-                " (" + (i+1) + " of " + N + ")");
+                    " (" + (i+1) + " of " + N + ")");
             entry.storeDependencies();
         }
     }
 
     public HYK getPeer() {
-        if (peer == null) {
-            River r = river.getPeer();
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from HYK where river=:river and description=:description");
+        if (this.peer == null) {
+            final River r = this.river.getPeer();
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            final Query query = session.createQuery(
+                    "from HYK where river=:river and description=:description");
             query.setParameter("river", r);
-            query.setParameter("description", description);
-            List<HYK> hyks = query.list();
+            query.setParameter("description", this.description);
+            final List<HYK> hyks = query.list();
             if (hyks.isEmpty()) {
-                peer = new HYK(r, description);
-                session.save(peer);
+                this.peer = new HYK(r, this.description);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = hyks.get(0);
+                this.peer = hyks.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportHYKEntry.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportHYKEntry.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,17 +8,16 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.HYKEntry;
-import org.dive4elements.river.model.HYK;
-
+import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.ArrayList;
 
-import java.math.BigDecimal;
-
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.HYK;
+import org.dive4elements.river.model.HYKEntry;
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
 
 public class ImportHYKEntry
 {
@@ -28,17 +27,20 @@
 
     protected List<ImportHYKFormation> formations;
 
+    protected StoreMode storeMode;
+
     protected HYKEntry peer;
 
     public ImportHYKEntry() {
-        formations = new ArrayList<ImportHYKFormation>();
+        this.formations = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
     public ImportHYKEntry(
-        ImportHYK  hyk,
-        BigDecimal km,
-        Date       measure
-    ) {
+            final ImportHYK  hyk,
+            final BigDecimal km,
+            final Date       measure
+            ) {
         this();
         this.hyk     = hyk;
         this.km      = km;
@@ -46,56 +48,63 @@
     }
 
     public ImportHYK getHYK() {
-        return hyk;
+        return this.hyk;
     }
 
-    public void setHYK(ImportHYK hyk) {
+    public void setHYK(final ImportHYK hyk) {
         this.hyk = hyk;
     }
 
     public BigDecimal getKm() {
-        return km;
+        return this.km;
     }
 
-    public void setKm(BigDecimal km) {
+    public void setKm(final BigDecimal km) {
         this.km = km;
     }
 
-    public void addFormation(ImportHYKFormation formation) {
-        int numFormation = formations.size();
-        formations.add(formation);
+    public void addFormation(final ImportHYKFormation formation) {
+        final int numFormation = this.formations.size();
+        this.formations.add(formation);
         formation.setFormationNum(numFormation);
         formation.setEntry(this);
     }
 
     public void storeDependencies() {
         getPeer();
-        for (ImportHYKFormation formation: formations) {
+        for (final ImportHYKFormation formation: this.formations) {
             formation.storeDependencies();
         }
     }
 
     public HYKEntry getPeer() {
-        if (peer == null) {
-            HYK h = hyk.getPeer();
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from HYKEntry where HYK=:hyk " +
-                "and km=:km and measure=:measure");
-            query.setParameter("hyk", h);
-            query.setParameter("km", km);
-            query.setParameter("measure", measure);
-            List<HYKEntry> entries = query.list();
-            if (entries.isEmpty()) {
-                peer = new HYKEntry(h, km, measure);
-                session.save(peer);
+        if (this.peer == null) {
+            final HYK h = this.hyk.getPeer();
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            List<HYKEntry> entries;
+            if (this.hyk.storeMode == StoreMode.INSERT)
+                entries = null;
+            else {
+                final Query query = session.createQuery(
+                        "from HYKEntry where HYK=:hyk " +
+                        "and km=:km and measure=:measure");
+                query.setParameter("hyk", h);
+                query.setParameter("km", this.km);
+                query.setParameter("measure", this.measure);
+                entries = query.list();
+            }
+            if ((entries == null) || entries.isEmpty()) {
+                this.peer = new HYKEntry(h, this.km, this.measure);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = entries.get(0);
+                this.peer = entries.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportHYKFlowZone.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportHYKFlowZone.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,16 +8,15 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.HYKFormation;
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.HYKFlowZone;
 import org.dive4elements.river.model.HYKFlowZoneType;
-
-import org.hibernate.Session;
+import org.dive4elements.river.model.HYKFormation;
 import org.hibernate.Query;
-
-import java.util.List;
-
-import java.math.BigDecimal;
+import org.hibernate.Session;
 
 public class ImportHYKFlowZone
 {
@@ -32,11 +31,11 @@
     }
 
     public ImportHYKFlowZone(
-        ImportHYKFormation    formation,
-        ImportHYKFlowZoneType type,
-        BigDecimal            a,
-        BigDecimal            b
-    ) {
+            final ImportHYKFormation    formation,
+            final ImportHYKFlowZoneType type,
+            final BigDecimal            a,
+            final BigDecimal            b
+            ) {
         this.formation = formation;
         this.type      = type;
         this.a         = a;
@@ -44,10 +43,10 @@
     }
 
     public ImportHYKFormation getFormation() {
-        return formation;
+        return this.formation;
     }
 
-    public void setFormation(ImportHYKFormation formation) {
+    public void setFormation(final ImportHYKFormation formation) {
         this.formation = formation;
     }
 
@@ -56,29 +55,34 @@
     }
 
     public HYKFlowZone getPeer() {
-        if (peer == null) {
-            HYKFormation    f = formation.getPeer();
-            HYKFlowZoneType t = type.getPeer();
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from HYKFlowZone where formation=:formation " +
-                "and type=:type and a=:a and b=:b");
-            query.setParameter("formation", f);
-            query.setParameter("type", t);
-            query.setParameter("a", a);
-            query.setParameter("b", b);
-            List<HYKFlowZone> zones = query.list();
-            if (zones.isEmpty()) {
-                peer = new HYKFlowZone(f, t, a, b);
-                session.save(peer);
+        if (this.peer == null) {
+            final HYKFormation    f = this.formation.getPeer();
+            final HYKFlowZoneType t = this.type.getPeer();
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            List<HYKFlowZone> zones;
+            if (this.formation.storeMode == StoreMode.INSERT)
+                zones = null;
+            {
+                final Query query = session.createQuery(
+                        "from HYKFlowZone where formation=:formation " +
+                        "and type=:type and a=:a and b=:b");
+                query.setParameter("formation", f);
+                query.setParameter("type", t);
+                query.setParameter("a", this.a);
+                query.setParameter("b", this.b);
+                zones = query.list();
+            }
+            if ((zones == null) || zones.isEmpty()) {
+                this.peer = new HYKFlowZone(f, t, this.a, this.b);
+                session.save(this.peer);
             }
             else {
-                peer = zones.get(0);
+                this.peer = zones.get(0);
             }
 
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportHYKFormation.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportHYKFormation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,16 +8,15 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.HYKFormation;
-import org.dive4elements.river.model.HYKEntry;
-
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.hibernate.Session;
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.HYKEntry;
+import org.dive4elements.river.model.HYKFormation;
 import org.hibernate.Query;
-
-import java.math.BigDecimal;
+import org.hibernate.Session;
 
 public class ImportHYKFormation
 {
@@ -31,21 +30,24 @@
 
     protected List<ImportHYKFlowZone> zones;
 
+    protected StoreMode storeMode;
+
     protected HYKFormation peer;
 
     public ImportHYKFormation() {
-        zones = new ArrayList<ImportHYKFlowZone>();
+        this.zones = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
     public ImportHYKFormation(
-        int            formationNum,
-        ImportHYKEntry entry,
-        BigDecimal     top,
-        BigDecimal     bottom,
-        BigDecimal     distanceVL,
-        BigDecimal     distanceHF,
-        BigDecimal     distanceVR
-    ) {
+            final int            formationNum,
+            final ImportHYKEntry entry,
+            final BigDecimal     top,
+            final BigDecimal     bottom,
+            final BigDecimal     distanceVL,
+            final BigDecimal     distanceHF,
+            final BigDecimal     distanceVR
+            ) {
         this();
         this.formationNum = formationNum;
         this.entry        = entry;
@@ -56,103 +58,110 @@
         this.distanceVR   = distanceVR;
     }
 
-    public void addFlowZone(ImportHYKFlowZone zone) {
-        zones.add(zone);
+    public void addFlowZone(final ImportHYKFlowZone zone) {
+        this.zones.add(zone);
         zone.setFormation(this);
     }
 
     public int getFormationNum() {
-        return formationNum;
+        return this.formationNum;
     }
 
-    public void setFormationNum(int formationNum) {
+    public void setFormationNum(final int formationNum) {
         this.formationNum = formationNum;
     }
 
     public ImportHYKEntry getEntry() {
-        return entry;
+        return this.entry;
     }
 
-    public void setEntry(ImportHYKEntry entry) {
+    public void setEntry(final ImportHYKEntry entry) {
         this.entry = entry;
     }
 
     public BigDecimal getTop() {
-        return top;
+        return this.top;
     }
 
-    public void setTop(BigDecimal top) {
+    public void setTop(final BigDecimal top) {
         this.top = top;
     }
 
     public BigDecimal getBottom() {
-        return bottom;
+        return this.bottom;
     }
 
-    public void setBottom(BigDecimal bottom) {
+    public void setBottom(final BigDecimal bottom) {
         this.bottom = bottom;
     }
 
     public BigDecimal getDistanceVL() {
-        return distanceVL;
+        return this.distanceVL;
     }
 
-    public void setDistanceVL(BigDecimal distanceVL) {
+    public void setDistanceVL(final BigDecimal distanceVL) {
         this.distanceVL = distanceVL;
     }
 
     public BigDecimal getDistanceHF() {
-        return distanceHF;
+        return this.distanceHF;
     }
 
-    public void setDistanceHF(BigDecimal distanceHF) {
+    public void setDistanceHF(final BigDecimal distanceHF) {
         this.distanceHF = distanceHF;
     }
 
     public BigDecimal getDistanceVR() {
-        return distanceVR;
+        return this.distanceVR;
     }
 
-    public void setDistanceVR(BigDecimal distanceVR) {
+    public void setDistanceVR(final BigDecimal distanceVR) {
         this.distanceVR = distanceVR;
     }
 
     public void storeDependencies() {
         getPeer();
-        for (ImportHYKFlowZone zone: zones) {
+        for (final ImportHYKFlowZone zone: this.zones) {
             zone.storeDependencies();
         }
     }
 
     public HYKFormation getPeer() {
-        if (peer == null) {
-            HYKEntry e = entry.getPeer();
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from HYKFormation where formationNum=:formationNum " +
-                "and entry=:entry and top=:top and bottom=:bottom " +
-                "and distanceVL=:distanceVL and distanceHF=:distanceHF " +
-                "and distanceVR=:distanceVR");
-            query.setParameter("formationNum", formationNum);
-            query.setParameter("entry", e);
-            query.setParameter("top", top);
-            query.setParameter("bottom", bottom);
-            query.setParameter("distanceVL", distanceVL);
-            query.setParameter("distanceHF", distanceHF);
-            query.setParameter("distanceVR", distanceVR);
-            List<HYKFormation> formations = query.list();
-            if (formations.isEmpty()) {
-                peer = new HYKFormation(
-                    formationNum, e, top, bottom,
-                    distanceVL, distanceHF, distanceVR);
-                session.save(peer);
+        if (this.peer == null) {
+            final HYKEntry e = this.entry.getPeer();
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            List<HYKFormation> formations;
+            if (this.entry.storeMode == StoreMode.INSERT)
+                formations = null;
+            else {
+                final Query query = session.createQuery(
+                        "from HYKFormation where formationNum=:formationNum " +
+                                "and entry=:entry and top=:top and bottom=:bottom " +
+                                "and distanceVL=:distanceVL and distanceHF=:distanceHF " +
+                        "and distanceVR=:distanceVR");
+                query.setParameter("formationNum", this.formationNum);
+                query.setParameter("entry", e);
+                query.setParameter("top", this.top);
+                query.setParameter("bottom", this.bottom);
+                query.setParameter("distanceVL", this.distanceVL);
+                query.setParameter("distanceHF", this.distanceHF);
+                query.setParameter("distanceVR", this.distanceVR);
+                formations = query.list();
+            }
+            if ((formations == null) || formations.isEmpty()) {
+                this.peer = new HYKFormation(
+                        this.formationNum, e, this.top, this.bottom,
+                        this.distanceVL, this.distanceHF, this.distanceVR);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = formations.get(0);
+                this.peer = formations.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportLocationSystem.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportLocationSystem.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,17 +11,15 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.model.LocationSystem;
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.model.LocationSystem;
 
 
 public class ImportLocationSystem {
 
     private static final Logger log =
-        Logger.getLogger(ImportLocationSystem.class);
+            Logger.getLogger(ImportLocationSystem.class);
 
 
     protected String name;
@@ -30,40 +28,34 @@
     protected LocationSystem peer;
 
 
-    public ImportLocationSystem(String name, String description) {
+    public ImportLocationSystem(final String name, final String description) {
         this.name        = name;
         this.description = description;
     }
 
     public void storeDependencies() {
-        log.info("store LocationSystem '" + name + "'");
-        LocationSystem ls = getPeer();
+        log.info("store LocationSystem '" + this.name + "'");
+        final LocationSystem ls = getPeer();
 
-        Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
         session.flush();
     }
 
     public LocationSystem getPeer() {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from LocationSystem where " +
-                "name=:name and description=:description");
-            query.setParameter("name", name);
-            query.setParameter("description", description);
-
-            List<LocationSystem> lss = query.list();
-            if (lss.isEmpty()) {
-                peer = new LocationSystem(name, description);
-                session.save(peer);
-            }
-            else {
-                peer = lss.get(0);
-            }
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM LocationSystem WHERE (trim(name)=:name) AND (trim(description)=:description)");
+        query.setParameter("name", this.name);
+        query.setParameter("description", this.description);
+        final List<LocationSystem> lss = query.list();
+        if (lss.isEmpty()) {
+            this.peer = new LocationSystem(this.name, this.description);
+            session.save(this.peer);
+        } else {
+            this.peer = lss.get(0);
         }
-
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportPorosity.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportPorosity.java	Fri Jul 13 11:56:22 2018 +0200
@@ -12,12 +12,12 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.Porosity;
+import org.dive4elements.river.model.River;
 import org.hibernate.Query;
 import org.hibernate.Session;
 
-import org.dive4elements.river.model.River;
-import org.dive4elements.river.model.Porosity;
-
 
 public class ImportPorosity {
 
@@ -33,82 +33,88 @@
 
     protected List<ImportPorosityValue> values;
 
-    public ImportPorosity(String description) {
+    protected StoreMode storeMode;
+
+    public ImportPorosity(final String description) {
         this.description = description;
-        this.values = new ArrayList<ImportPorosityValue>();
+        this.values = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-    public void setDepth(ImportDepth depth) {
+    public void setDepth(final ImportDepth depth) {
         this.depth = depth;
     }
 
-    public void setTimeInterval(ImportTimeInterval importTimeInterval) {
+    public void setTimeInterval(final ImportTimeInterval importTimeInterval) {
         this.timeInterval = importTimeInterval;
     }
 
-    public void addValue(ImportPorosityValue value) {
-        values.add(value);
+    public void addValue(final ImportPorosityValue value) {
+        this.values.add(value);
     }
 
-    public void storeDependencies(River river) {
-        log.info("store dependencies");
+    public void storeDependencies(final River river) {
+        log.info("store dependencies for '" + getDescription() + "'");
 
-        if (depth != null) {
-            depth.storeDependencies();
+        if (this.depth != null) {
+            this.depth.storeDependencies();
         }
 
-        Porosity peer = getPeer(river);
+        final Porosity peer = getPeer(river);
 
         if (peer != null) {
-            log.info("store porosity values.");
-            for (ImportPorosityValue value : values) {
-                value.storeDependencies(peer);
+            // log.info("store porosity values.");
+            for (final ImportPorosityValue value : this.values) {
+                value.storeDependencies(peer, this.storeMode);
             }
+            log.info("Porosity values processed: " + this.values.size());
         }
     }
 
-    public Porosity getPeer(River river) {
-        log.info("get peer");
+    public Porosity getPeer(final River river) {
+        // log.info("get peer");
 
-        if (depth == null) {
-            log.warn("cannot store porosity '" + description
-                + "': no depth");
+        if (this.depth == null) {
+            log.warn("cannot store porosity '" + this.description
+                    + "': no depth");
             return null;
         }
 
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
 
-            Query query = session.createQuery("from Porosity where "
-                + "   river=:river and "
-                + "   depth=:depth and "
-                + "   description=:description");
+            final Query query = session.createQuery("from Porosity where "
+                    + "   river=:river and "
+                    + "   depth=:depth and "
+                    + "   description=:description");
 
             query.setParameter("river", river);
-            query.setParameter("depth", depth.getPeer());
-            query.setParameter("description", description);
+            query.setParameter("depth", this.depth.getPeer());
+            query.setParameter("description", this.description);
 
-            List<Porosity> porosity = query.list();
+            final List<Porosity> porosity = query.list();
 
             if (porosity.isEmpty()) {
                 log.debug("Create new Porosity DB instance.");
 
-                peer = new Porosity(river, depth.getPeer(),
-                    description, timeInterval.getPeer());
+                this.peer = new Porosity(river, this.depth.getPeer(),
+                        this.description, this.timeInterval.getPeer());
 
-                session.save(peer);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = porosity.get(0);
+                this.peer = porosity.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
 
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportPorosityValue.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportPorosityValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,22 +9,20 @@
 package org.dive4elements.river.importer;
 
 import java.math.BigDecimal;
-
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.Porosity;
 import org.dive4elements.river.model.PorosityValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportPorosityValue {
 
     private static final Logger log =
-        Logger.getLogger(ImportPorosityValue.class);
+            Logger.getLogger(ImportPorosityValue.class);
 
 
     protected PorosityValue peer;
@@ -39,11 +37,11 @@
 
 
     public ImportPorosityValue(
-        BigDecimal station,
-        BigDecimal shoreOffset,
-        BigDecimal porosity,
-        String     description
-    ) {
+            final BigDecimal station,
+            final BigDecimal shoreOffset,
+            final BigDecimal porosity,
+            final String     description
+            ) {
         this.station     = station;
         this.shoreOffset = shoreOffset;
         this.porosity    = porosity;
@@ -51,53 +49,57 @@
     }
 
 
-    public void storeDependencies(Porosity porosity) {
-        log.info("store dependencies");
+    public void storeDependencies(final Porosity porosity, final StoreMode parentStoreMode) {
+        // log.info("store dependencies");
 
-        getPeer(porosity);
+        getPeer(porosity, parentStoreMode);
     }
 
 
-    public PorosityValue getPeer(Porosity porosity) {
+    public PorosityValue getPeer(final Porosity porosity, final StoreMode parentStoreMode) {
         log.info("get peer");
 
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-
-            Query query = session.createQuery(
-                "from PorosityValue "
-                + "where porosity=:porosity "
-                + "and station between :station - 0.0001f "
-                + "    and :station + 0.0001f "
-                + "and porosityValue between :poros -0.0001f "
-                + "    and :poros + 0.0001f "
-                + "and description=:description");
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            List<PorosityValue> values;
+            if (parentStoreMode == StoreMode.INSERT)
+                values = null;
+            else {
+                final Query query = session.createQuery(
+                        "from PorosityValue "
+                                + "where porosity=:porosity "
+                                + "and station between :station - 0.0001f "
+                                + "    and :station + 0.0001f "
+                                + "and porosityValue between :poros -0.0001f "
+                                + "    and :poros + 0.0001f "
+                                + "and description=:description");
 
-            query.setParameter("porosity", porosity);
-            query.setParameter("station", station.floatValue());
-            query.setParameter("poros", this.porosity.floatValue());
-            query.setParameter("description", description);
+                query.setParameter("porosity", porosity);
+                query.setParameter("station", this.station.floatValue());
+                query.setParameter("poros", this.porosity.floatValue());
+                query.setParameter("description", this.description);
 
-            List<PorosityValue> values = query.list();
-            if (values.isEmpty()) {
-                log.debug("Create new PorosityValue DB instance.");
+                values = query.list();
+            }
+            if ((values == null) || values.isEmpty()) {
+                // log.debug("Create new PorosityValue DB instance.");
 
-                peer = new PorosityValue(
-                    porosity,
-                    station,
-                    shoreOffset,
-                    this.porosity,
-                    description);
+                this.peer = new PorosityValue(
+                        porosity,
+                        this.station,
+                        this.shoreOffset,
+                        this.porosity,
+                        this.description);
 
-                session.save(peer);
+                session.save(this.peer);
             }
             else {
-                peer = values.get(0);
+                this.peer = values.get(0);
             }
         }
 
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportRange.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportRange.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,12 +8,11 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.Range;
-import org.dive4elements.river.model.River;
-
 import java.math.BigDecimal;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.river.model.Range;
+import org.dive4elements.river.model.River;
 
 /** A range that is about to be imported. */
 public class ImportRange
@@ -30,7 +29,7 @@
     public ImportRange() {
     }
 
-    public ImportRange(BigDecimal a) {
+    public ImportRange(final BigDecimal a) {
         this.a = a;
         this.b = null;
     }
@@ -55,14 +54,14 @@
         }
         else {
             if (a.compareTo(b) > 0) {
-                BigDecimal t = a; a = b; b = t;
+                final BigDecimal t = a; a = b; b = t;
             }
             this.a = a;
             this.b = b;
         }
     }
 
-    private static final int compare(BigDecimal a, BigDecimal b) {
+    private static final int compare(final BigDecimal a, final BigDecimal b) {
         if (a == null && b == null) {
             return 0;
         }
@@ -75,41 +74,54 @@
         return a.compareTo(b);
     }
 
-    public int compareTo(ImportRange other) {
-        int cmp = compare(a, other.a);
+    @Override
+    public int compareTo(final ImportRange other) {
+        final int cmp = compare(this.a, other.a);
         if (cmp != 0) return cmp;
-        return compare(b, other.b);
+        return compare(this.b, other.b);
     }
 
     public BigDecimal getA() {
-        return a;
+        return this.a;
     }
 
-    public void setA(BigDecimal a) {
-        if (this.b != null && a.compareTo(b) >= 0) {
+    public void setA(final BigDecimal a) {
+        if (this.b != null && a.compareTo(this.b) >= 0) {
             throw new IllegalArgumentException(
-                "a (" + a + ") must be smaller than b (" + b + ").");
+                    "a (" + a + ") must be smaller than b (" + this.b + ").");
         }
         this.a = a;
     }
 
     public BigDecimal getB() {
-        return b;
+        return this.b;
     }
 
-    public void setB(BigDecimal b) {
-        if (b != null && b.compareTo(a) <= 0) {
+    public void setB(final BigDecimal b) {
+        if (b != null && b.compareTo(this.a) <= 0) {
             throw new IllegalArgumentException(
-                "b (" + b + ") must be greater than a (" + a + ") or null.");
+                    "b (" + b + ") must be greater than a (" + this.a + ") or null.");
         }
         this.b = b;
     }
 
-    public Range getPeer(River river) {
-        if (peer == null) {
-            peer = ImporterSession.getInstance().getRange(river, a, b);
+    /**
+     * Difference of a and b
+     *
+     * @return b - a, or NaN if a or b null
+     */
+    public double difference() {
+        if ((this.a != null) && (this.b != null))
+            return this.b.subtract(this.a).doubleValue();
+        else
+            return Double.NaN;
+    }
+
+    public Range getPeer(final River river) {
+        if (this.peer == null) {
+            this.peer = ImporterSession.getInstance().getRange(river, this.a, this.b);
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,10 +8,23 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.artifacts.common.utils.FileTools.HashedFile;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
+import org.apache.log4j.Logger;
 import org.dive4elements.artifacts.common.utils.FileTools;
-
+import org.dive4elements.artifacts.common.utils.FileTools.HashedFile;
+import org.dive4elements.river.backend.utils.DouglasPeuker;
+import org.dive4elements.river.importer.parsers.AbstractSedimentLoadParser;
 import org.dive4elements.river.importer.parsers.AnnotationClassifier;
 import org.dive4elements.river.importer.parsers.AnnotationsParser;
 import org.dive4elements.river.importer.parsers.BedHeightParser;
@@ -29,34 +42,17 @@
 import org.dive4elements.river.importer.parsers.PorosityParser;
 import org.dive4elements.river.importer.parsers.SQRelationParser;
 import org.dive4elements.river.importer.parsers.SedimentDensityParser;
-import org.dive4elements.river.importer.parsers.AbstractSedimentLoadParser;
 import org.dive4elements.river.importer.parsers.SedimentLoadLSParser;
 import org.dive4elements.river.importer.parsers.SedimentLoadParser;
+import org.dive4elements.river.importer.parsers.W80CSVParser;
 import org.dive4elements.river.importer.parsers.W80Parser;
-import org.dive4elements.river.importer.parsers.W80CSVParser;
 import org.dive4elements.river.importer.parsers.WaterlevelDifferencesParser;
 import org.dive4elements.river.importer.parsers.WaterlevelParser;
 import org.dive4elements.river.importer.parsers.WstParser;
-
+import org.dive4elements.river.importer.sinfo.SInfoImporter;
+import org.dive4elements.river.importer.uinfo.UInfoImporter;
 import org.dive4elements.river.model.River;
 import org.dive4elements.river.model.Unit;
-
-import org.dive4elements.river.backend.utils.DouglasPeuker;
-
-import java.io.File;
-import java.io.IOException;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Iterator;
-
-import org.apache.log4j.Logger;
-
 import org.hibernate.Query;
 import org.hibernate.Session;
 
@@ -71,22 +67,22 @@
     public static final String FIXATIONS = "Fixierungen";
 
     public static final String EXTRA_LONGITUDINALS =
-        "Zus.Laengsschnitte";
+            "Zus.Laengsschnitte";
 
     public static final String [] OFFICIAL_LINES_FOLDERS = {
-        "Basisdaten",
-        "Fixierungen" };
+            "Basisdaten",
+    "Fixierungen" };
 
     public static final String OFFICIAL_LINES =
-        "Amtl_Linien.wst";
+            "Amtl_Linien.wst";
 
     public static final String OFFICIAL_LINES_CONFIG =
-        "Amtl_Linien.config";
+            "Amtl_Linien.config";
 
     public static final String FLOOD_WATER = "HW-Marken";
 
     public static final String FLOOD_PROTECTION =
-        "HW-Schutzanlagen";
+            "HW-Schutzanlagen";
 
     public static final String MINFO_DIR = "Morphologie";
 
@@ -99,10 +95,10 @@
     public static final String POROSITY_DIR = "Porositaet";
 
     public static final String MORPHOLOGICAL_WIDTH_DIR =
-        "morphologische_Breite";
+            "morphologische_Breite";
 
     public static final String FLOW_VELOCITY_DIR =
-        "Geschwindigkeit_Schubspannung";
+            "Geschwindigkeit_Schubspannung";
 
     public static final String FLOW_VELOCITY_MODEL = "Modellrechnungen";
 
@@ -119,22 +115,22 @@
     public static final String SEDIMENT_LOAD_EPOCH_DIR = "Epochen";
 
     public static final String SEDIMENT_LOAD_OFF_EPOCH_DIR =
-        "amtliche Epochen";
+            "amtliche Epochen";
 
     public static final String MINFO_FIXATIONS_DIR = "Fixierungsanalyse";
 
     public static final String MINFO_WATERLEVELS_DIR = "Wasserspiegellagen";
 
     public static final String MINFO_WATERLEVEL_DIFF_DIR =
-        "Wasserspiegeldifferenzen";
+            "Wasserspiegeldifferenzen";
 
     public static final String MINFO_BASE_DIR = "Basisdaten";
 
     public static final String MINFO_CORE_DATA_FILE =
-        "Stammdaten_Messstellen.csv";
+            "Stammdaten_Messstellen.csv";
 
     public static final String MINFO_SQ_DIR =
-        "Feststofftransport-Abfluss-Beziehung";
+            "Feststofftransport-Abfluss-Beziehung";
 
     protected String name;
 
@@ -142,6 +138,9 @@
 
     protected Long officialNumber;
 
+    /**
+     * Path of the river/Hydrologie/Basisdaten/river.wst file from which all other file paths are derived
+     */
     protected File wstFile;
 
     protected File bbInfoFile;
@@ -199,31 +198,40 @@
     /** Database-mapped River instance. */
     protected River peer;
 
+    /**
+     * Importer for a river's S-INFO files.
+     */
+    private final SInfoImporter sinfoImporter;
+
+    /**
+     * Importer for a river's U-INFO files.
+     */
+    private final UInfoImporter uinfoImporter;
 
     /** Callback-implementation for CrossSectionParsers. */
     private class ImportRiverCrossSectionParserCallback
     implements    CrossSectionParser.Callback {
 
-        private Set<HashedFile> files = new HashSet<HashedFile>();
-        private String          type;
+        private final Set<HashedFile> files = new HashSet<>();
+        private final String          type;
 
         /**
          * Create new Callback, given type which is used for logging
          * purposes only.
          */
-        public ImportRiverCrossSectionParserCallback(String type) {
+        public ImportRiverCrossSectionParserCallback(final String type) {
             this.type = type;
         }
 
 
         /** Accept file if not duplicate. */
         @Override
-        public boolean accept(File file) {
-            HashedFile hf = new HashedFile(file);
-            boolean success = files.add(hf);
+        public boolean accept(final File file) {
+            final HashedFile hf = new HashedFile(file);
+            final boolean success = this.files.add(hf);
             if (!success) {
-                log.warn(type + " file '" + file
-                    + "' seems to be a duplicate.");
+                log.warn(this.type + " file '" + file
+                        + "' seems to be a duplicate.");
             }
             return success;
         }
@@ -231,92 +239,94 @@
 
         /** Add crosssection. */
         @Override
-        public void parsed(CrossSectionParser parser) {
-           log.debug("callback from " + type + " parser");
-
-            String  description = parser.getDescription();
-            Integer year        = parser.getYear();
-            ImportTimeInterval ti = year != null
-                ? new ImportTimeInterval(yearToDate(year))
-                : null;
-
-            Map<Double, List<XY>> data = parser.getData();
-
-            List<ImportCrossSectionLine> lines =
-                new ArrayList<ImportCrossSectionLine>(data.size());
-
-            Double simplificationEpsilon =
-                Config.INSTANCE.getCrossSectionSimplificationEpsilon();
-
-            long numReadPoints      = 0L;
-            long numRemainingPoints = 0L;
+        public void parsed(final CrossSectionParser parser) {
+            log.debug("callback from " + this.type + " parser");
 
-            for (Map.Entry<Double, List<XY>> entry: data.entrySet()) {
-                Double   km     = entry.getKey();
-                List<XY> points = entry.getValue();
-                numReadPoints += points.size();
-                if (simplificationEpsilon != null) {
-                    points = DouglasPeuker.simplify(
-                        points, simplificationEpsilon);
-                }
-                numRemainingPoints += points.size();
-                lines.add(new ImportCrossSectionLine(km, points));
-            }
+            final String  description = parser.getDescription();
+            final Integer year        = parser.getYear();
+            final ImportTimeInterval ti = year != null
+                    ? new ImportTimeInterval(yearToDate(year))
+                            : null;
 
-            ImportRiver.this.addCrossSections(description, ti, lines);
+                    final Map<Double, List<XY>> data = parser.getData();
 
-            if (simplificationEpsilon != null) {
-                double percent = numReadPoints > 0L
-                    ? ((double)numRemainingPoints/numReadPoints)*100d
-                    : 0d;
+                    final List<ImportCrossSectionLine> lines =
+                            new ArrayList<>(data.size());
 
-                log.info(String.format(
-                    "Number of points in cross section: %d / %d (%.2f%%)",
-                    numReadPoints, numRemainingPoints, percent));
-            }
+                    final Double simplificationEpsilon =
+                            Config.INSTANCE.getCrossSectionSimplificationEpsilon();
+
+                    long numReadPoints      = 0L;
+                    long numRemainingPoints = 0L;
+
+                    for (final Map.Entry<Double, List<XY>> entry: data.entrySet()) {
+                        final Double   km     = entry.getKey();
+                        List<XY> points = entry.getValue();
+                        numReadPoints += points.size();
+                        if (simplificationEpsilon != null) {
+                            points = DouglasPeuker.simplify(
+                                    points, simplificationEpsilon);
+                        }
+                        numRemainingPoints += points.size();
+                        lines.add(new ImportCrossSectionLine(km, points));
+                    }
+
+                    ImportRiver.this.addCrossSections(description, ti, lines);
+
+                    if (simplificationEpsilon != null) {
+                        final double percent = numReadPoints > 0L
+                                ? ((double)numRemainingPoints/numReadPoints)*100d
+                                        : 0d;
+
+                                log.info(String.format(
+                                        "Number of points in cross section: %d / %d (%.2f%%)",
+                                        numReadPoints, numRemainingPoints, percent));
+                    }
         }
     } // ImportRiverCrossSectionParserCallback
 
 
     private void addCrossSections(
-        String                       description,
-        ImportTimeInterval           ti,
-        List<ImportCrossSectionLine> lines
-    ) {
-        crossSections.add(
-            new ImportCrossSection(this, description, ti, lines));
+            final String                       description,
+            final ImportTimeInterval           ti,
+            final List<ImportCrossSectionLine> lines
+            ) {
+        this.crossSections.add(
+                new ImportCrossSection(this, description, ti, lines));
     }
 
 
     public ImportRiver() {
-        hyks                     = new ArrayList<ImportHYK>();
-        crossSections            = new ArrayList<ImportCrossSection>();
-        extraWsts                = new ArrayList<ImportWst>();
-        fixations                = new ArrayList<ImportWst>();
-        officialLines            = new ArrayList<ImportWst>();
-        floodWater               = new ArrayList<ImportWst>();
-        waterlevels              = new ArrayList<ImportWst>();
-        waterlevelDifferences    = new ArrayList<ImportWst>();
-        floodProtection          = new ArrayList<ImportWst>();
-        sedimentDensities        = new ArrayList<ImportSedimentDensity>();
-        porosities               = new ArrayList<ImportPorosity>();
-        morphologicalWidths      = new ArrayList<ImportMorphWidth>();
-        flowVelocityModels       = new ArrayList<ImportFlowVelocityModel>();
-        flowVelocityMeasurements =
-            new ArrayList<ImportFlowVelocityMeasurement>();
-        sedimentLoadLSs          = new ArrayList<ImportSedimentLoadLS>();
-        sedimentLoads            = new ArrayList<ImportSedimentLoad>();
-        measurementStations      = new ArrayList<ImportMeasurementStation>();
-        sqRelations              = new ArrayList<ImportSQRelation>();
+        this.hyks                     = new ArrayList<>();
+        this.crossSections            = new ArrayList<>();
+        this.extraWsts                = new ArrayList<>();
+        this.fixations                = new ArrayList<>();
+        this.officialLines            = new ArrayList<>();
+        this.floodWater               = new ArrayList<>();
+        this.waterlevels              = new ArrayList<>();
+        this.waterlevelDifferences    = new ArrayList<>();
+        this.floodProtection          = new ArrayList<>();
+        this.sedimentDensities        = new ArrayList<>();
+        this.porosities               = new ArrayList<>();
+        this.morphologicalWidths      = new ArrayList<>();
+        this.flowVelocityModels       = new ArrayList<>();
+        this.flowVelocityMeasurements =
+                new ArrayList<>();
+        this.sedimentLoadLSs          = new ArrayList<>();
+        this.sedimentLoads            = new ArrayList<>();
+        this.measurementStations      = new ArrayList<>();
+        this.sqRelations              = new ArrayList<>();
+        this.sinfoImporter = new SInfoImporter();
+        this.uinfoImporter = new UInfoImporter();
     }
 
     public ImportRiver(
-        String               name,
-        String               modelUuid,
-        File                 wstFile,
-        File                 bbInfoFile,
-        AnnotationClassifier annotationClassifier
-    ) {
+            final String               name,
+            final String               modelUuid,
+            final File                 wstFile,
+            final File                 bbInfoFile,
+            final AnnotationClassifier annotationClassifier
+            ) {
         this();
         this.name                 = name;
         this.modelUuid            = modelUuid;
@@ -326,18 +336,18 @@
     }
 
     public String getName() {
-        return name;
+        return this.name;
     }
 
-    public void setName(String name) {
+    public void setName(final String name) {
         this.name = name;
     }
 
     public String getModelUuid() {
-        return modelUuid;
+        return this.modelUuid;
     }
 
-    public void setModelUuid(String modelUuid) {
+    public void setModelUuid(final String modelUuid) {
         this.modelUuid = modelUuid;
     }
 
@@ -345,41 +355,48 @@
         return this.officialNumber;
     }
 
-    public void setOfficialNumber(Long officialNumber) {
+    public void setOfficialNumber(final Long officialNumber) {
         this.officialNumber = officialNumber;
     }
 
     public File getWstFile() {
-        return wstFile;
+        return this.wstFile;
     }
 
-    public void setWstFile(File wstFile) {
+    public void setWstFile(final File wstFile) {
         this.wstFile = wstFile;
     }
 
     public File getBBInfo() {
-        return bbInfoFile;
+        return this.bbInfoFile;
     }
 
-    public void setBBInfo(File bbInfoFile) {
+    public void setBBInfo(final File bbInfoFile) {
         this.bbInfoFile = bbInfoFile;
     }
 
     public ImportWst getWst() {
-        return wst;
+        return this.wst;
     }
 
-    public void setWst(ImportWst wst) {
+    public void setWst(final ImportWst wst) {
         this.wst = wst;
     }
 
-    public File getMinfoDir() {
-        File riverDir  = wstFile
-            .getParentFile().getParentFile().getParentFile();
-        return new File(riverDir, MINFO_DIR);
+    private File getMinfoDir() {
+        return new File(getRiverDir(), MINFO_DIR);
+    }
+
+    private File getRiverDir() {
+        return this.wstFile.getParentFile().getParentFile().getParentFile();
+    }
+
+    public AnnotationClassifier getAnnotationClassifier() {
+        return this.annotationClassifier;
     }
 
     public void parseDependencies() throws IOException {
+        log.info("Root dir is '" + getRiverDir() + "'");
         parseGauges();
         parseAnnotations();
         parsePRFs();
@@ -405,6 +422,10 @@
         parseWaterlevels();
         parseWaterlevelDifferences();
         parseSQRelation();
+        this.sinfoImporter.setup(getRiverDir(), this);
+        this.sinfoImporter.parse();
+        this.uinfoImporter.setup(getRiverDir(), this);
+        this.uinfoImporter.parse();
     }
 
     public void parseFloodProtection() throws IOException {
@@ -415,41 +436,41 @@
 
         log.info("Parse flood protection wst file");
 
-        File riverDir = wstFile.getParentFile().getParentFile();
+        final File riverDir = this.wstFile.getParentFile().getParentFile();
 
-        File dir = FileTools.repair(new File(riverDir, FLOOD_PROTECTION));
+        final File dir = FileTools.repair(new File(riverDir, FLOOD_PROTECTION));
 
         if (!dir.isDirectory() || !dir.canRead()) {
             log.info("no directory '" + dir + "' found");
             return;
         }
 
-        File [] files = dir.listFiles();
+        final File [] files = dir.listFiles();
 
         if (files == null) {
             log.warn("cannot read '" + dir + "'");
             return;
         }
 
-        for (File file: files) {
+        for (final File file: files) {
             if (!file.isFile() || !file.canRead()) {
                 continue;
             }
-            String name = file.getName().toLowerCase();
+            final String name = file.getName().toLowerCase();
             if (!(name.endsWith(".zus") || name.endsWith(".wst"))) {
                 continue;
             }
             log.info("found file '" + file.getName() + "'");
             try {
-                WstParser wstParser = new WstParser();
+                final WstParser wstParser = new WstParser();
                 wstParser.parse(file);
-                ImportWst iw = wstParser.getWst();
+                final ImportWst iw = wstParser.getWst();
                 iw.setKind(5);
                 iw.setDescription(
-                    FLOOD_PROTECTION + "/" + iw.getDescription());
-                floodProtection.add(iw);
+                        FLOOD_PROTECTION + "/" + iw.getDescription());
+                this.floodProtection.add(iw);
             }
-            catch (WstParser.ParseException e) {
+            catch (final WstParser.ParseException e) {
                 log.error(e.getMessage());
             }
         }
@@ -460,13 +481,13 @@
             log.info("skip storing official number.");
             return;
         }
-        getPeer().setOfficialNumber(officialNumber);
+        getPeer().setOfficialNumber(this.officialNumber);
     }
 
     public void parseBedHeight() throws IOException {
-        File minfoDir     = getMinfoDir();
-        File bedHeightDir = new File(minfoDir, BED_HEIGHT_DIR);
-        File singlesDir   = new File(bedHeightDir, BED_HEIGHT_SINGLE_DIR);
+        final File minfoDir     = getMinfoDir();
+        final File bedHeightDir = new File(minfoDir, BED_HEIGHT_DIR);
+        final File singlesDir   = new File(bedHeightDir, BED_HEIGHT_SINGLE_DIR);
 
         if (Config.INSTANCE.skipBedHeight()) {
             log.info("skip parsing bed heights.");
@@ -486,26 +507,26 @@
 
         log.debug("Parse sediment density");
 
-        File minfoDir = getMinfoDir();
-        File sediment = new File(minfoDir, SEDIMENT_DENSITY_DIR);
+        final File minfoDir = getMinfoDir();
+        final File sediment = new File(minfoDir, SEDIMENT_DENSITY_DIR);
 
-        File[] files = sediment.listFiles();
+        final File[] files = sediment.listFiles();
 
         if (files == null) {
             log.warn("Cannot read directory '" + sediment + "'");
             return;
         }
 
-        SedimentDensityParser parser = new SedimentDensityParser();
+        final SedimentDensityParser parser = new SedimentDensityParser();
 
-        for (File file: files) {
+        for (final File file: files) {
             parser.parse(file);
         }
 
-        sedimentDensities = parser.getSedimentDensities();
+        this.sedimentDensities = parser.getSedimentDensities();
 
-        log.info("Parsed " + sedimentDensities.size()
-            + " sediment densities.");
+        log.info("Parsed " + this.sedimentDensities.size()
+        + " sediment densities.");
     }
 
     protected void parsePorosity() throws IOException {
@@ -516,25 +537,25 @@
 
         log.debug("Parse porosity");
 
-        File minfoDir = getMinfoDir();
-        File porosity = new File(minfoDir, POROSITY_DIR);
+        final File minfoDir = getMinfoDir();
+        final File porosity = new File(minfoDir, POROSITY_DIR);
 
-        File[] files = porosity.listFiles();
+        final File[] files = porosity.listFiles();
 
         if (files == null) {
             log.warn("Cannot read directory '" + porosity + "'");
             return;
         }
 
-        PorosityParser parser = new PorosityParser();
+        final PorosityParser parser = new PorosityParser();
 
-        for (File file: files) {
+        for (final File file: files) {
             parser.parse(file);
         }
 
-        porosities = parser.getPorosities();
+        this.porosities = parser.getPorosities();
 
-        log.info("Parsed " + porosities.size() + " porosities.");
+        log.info("Parsed " + this.porosities.size() + " porosities.");
     }
 
     protected void parseMorphologicalWidth() throws IOException {
@@ -545,26 +566,26 @@
 
         log.debug("Parse morphological width");
 
-        File minfoDir = getMinfoDir();
-        File morphDir = new File(minfoDir, MORPHOLOGICAL_WIDTH_DIR);
+        final File minfoDir = getMinfoDir();
+        final File morphDir = new File(minfoDir, MORPHOLOGICAL_WIDTH_DIR);
 
-        File[] files = morphDir.listFiles();
+        final File[] files = morphDir.listFiles();
 
         if (files == null) {
             log.warn("Cannot read directory '" + morphDir + "'");
             return;
         }
 
-        MorphologicalWidthParser parser = new MorphologicalWidthParser();
+        final MorphologicalWidthParser parser = new MorphologicalWidthParser();
 
-        for (File file: files) {
+        for (final File file: files) {
             parser.parse(file);
         }
 
-        morphologicalWidths = parser.getMorphologicalWidths();
+        this.morphologicalWidths = parser.getMorphologicalWidths();
 
-        log.info("Parsed " + morphologicalWidths.size()
-            + " morph. widths files.");
+        log.info("Parsed " + this.morphologicalWidths.size()
+        + " morph. widths files.");
     }
 
 
@@ -576,78 +597,78 @@
 
         log.debug("Parse flow velocity");
 
-        File minfoDir   = getMinfoDir();
-        File flowDir    = new File(minfoDir, FLOW_VELOCITY_DIR);
-        File modelDir   = new File(flowDir, FLOW_VELOCITY_MODEL);
-        File measureDir = new File(flowDir, FLOW_VELOCITY_MEASUREMENTS);
+        final File minfoDir   = getMinfoDir();
+        final File flowDir    = new File(minfoDir, FLOW_VELOCITY_DIR);
+        final File modelDir   = new File(flowDir, FLOW_VELOCITY_MODEL);
+        final File measureDir = new File(flowDir, FLOW_VELOCITY_MEASUREMENTS);
 
-        File[] modelFiles   = modelDir.listFiles();
-        File[] measureFiles = measureDir.listFiles();
+        final File[] modelFiles   = modelDir.listFiles();
+        final File[] measureFiles = measureDir.listFiles();
 
         if (modelFiles == null) {
             log.warn("Cannot read directory '" + modelDir + "'");
         }
         else {
-            FlowVelocityModelParser parser = new FlowVelocityModelParser();
+            final FlowVelocityModelParser parser = new FlowVelocityModelParser();
 
-            for (File model: modelFiles) {
+            for (final File model: modelFiles) {
                 log.debug("Parse file '" + model + "'");
                 parser.parse(model);
             }
 
-            flowVelocityModels = parser.getModels();
+            this.flowVelocityModels = parser.getModels();
         }
 
         if (measureFiles == null) {
             log.warn("Cannot read directory '" + measureDir + "'");
         }
         else {
-            FlowVelocityMeasurementParser parser =
-                new FlowVelocityMeasurementParser();
+            final FlowVelocityMeasurementParser parser =
+                    new FlowVelocityMeasurementParser();
 
-            for (File measurement: measureFiles) {
+            for (final File measurement: measureFiles) {
                 log.debug("Parse file '" + measurement + "'");
                 parser.parse(measurement);
             }
 
-            flowVelocityMeasurements = parser.getMeasurements();
+            this.flowVelocityMeasurements = parser.getMeasurements();
         }
     }
 
 
     private void parseSedimentLoadFiles(
-        File[] files,
-        AbstractSedimentLoadParser parser
-    ) throws IOException {
-       for (File file: files) {
-           if (file.isDirectory()) {
-               for (File child: file.listFiles()) {
-                   parser.parse(child);
-               }
-           }
-           else {
-               parser.parse(file);
-           }
-       }
+            final File[] files,
+            final AbstractSedimentLoadParser parser
+            ) throws IOException {
+        for (final File file: files) {
+            if (file.isDirectory()) {
+                for (final File child: file.listFiles()) {
+                    parser.parse(child);
+                }
+            }
+            else {
+                parser.parse(file);
+            }
+        }
     }
 
 
     private void parseSedimentLoadDir(
-        File sedimentLoadDir,
-        AbstractSedimentLoadParser parser
-    ) throws IOException {
+            final File sedimentLoadDir,
+            final AbstractSedimentLoadParser parser
+            ) throws IOException {
 
-        File[] sedimentLoadSubDirs = {
-            new File(sedimentLoadDir,
-                     SEDIMENT_LOAD_SINGLE_DIR),
-            new File(sedimentLoadDir,
-                     SEDIMENT_LOAD_EPOCH_DIR),
-            new File(sedimentLoadDir,
-                     SEDIMENT_LOAD_OFF_EPOCH_DIR),
+        final File[] sedimentLoadSubDirs = {
+                new File(sedimentLoadDir,
+                        SEDIMENT_LOAD_SINGLE_DIR),
+                new File(sedimentLoadDir,
+                        SEDIMENT_LOAD_EPOCH_DIR),
+                new File(sedimentLoadDir,
+                        SEDIMENT_LOAD_OFF_EPOCH_DIR),
         };
 
-        for (File subDir : sedimentLoadSubDirs) {
-            File[] files = subDir.listFiles();
+        for (final File subDir : sedimentLoadSubDirs) {
+            final File[] files = subDir.listFiles();
 
             if (files == null || files.length == 0) {
                 log.warn("Cannot read directory '" + subDir + "'");
@@ -667,38 +688,38 @@
 
         log.debug("Parse sediment load longitudinal section data");
 
-        SedimentLoadLSParser parser = new SedimentLoadLSParser();
+        final SedimentLoadLSParser parser = new SedimentLoadLSParser();
 
-        File minfoDir          = getMinfoDir();
-        File sedimentLoadDir   = new File(minfoDir, SEDIMENT_LOAD_DIR);
-        File sedimentLoadLSDir = new File(sedimentLoadDir,
-                                          SEDIMENT_LOAD_LS_DIR);
+        final File minfoDir          = getMinfoDir();
+        final File sedimentLoadDir   = new File(minfoDir, SEDIMENT_LOAD_DIR);
+        final File sedimentLoadLSDir = new File(sedimentLoadDir,
+                SEDIMENT_LOAD_LS_DIR);
 
         parseSedimentLoadDir(sedimentLoadLSDir, parser);
 
-        sedimentLoadLSs = parser.getSedimentLoadLSs();
+        this.sedimentLoadLSs = parser.getSedimentLoadLSs();
     }
 
 
     protected void parseSedimentLoad() throws IOException {
         if (Config.INSTANCE.skipSedimentLoad()) {
             log.info(
-                "skip parsing sediment load data at measurement stations");
+                    "skip parsing sediment load data at measurement stations");
             return;
         }
 
         log.debug("Parse sediment load data at measurement stations");
 
-        SedimentLoadParser parser = new SedimentLoadParser(getPeer());
+        final SedimentLoadParser parser = new SedimentLoadParser(getPeer());
 
-        File minfoDir          = getMinfoDir();
-        File sedimentLoadDir   = new File(minfoDir, SEDIMENT_LOAD_DIR);
-        File sedimentLoadMSDir = new File(sedimentLoadDir,
-                                          SEDIMENT_LOAD_MS_DIR);
+        final File minfoDir          = getMinfoDir();
+        final File sedimentLoadDir   = new File(minfoDir, SEDIMENT_LOAD_DIR);
+        final File sedimentLoadMSDir = new File(sedimentLoadDir,
+                SEDIMENT_LOAD_MS_DIR);
 
         parseSedimentLoadDir(sedimentLoadMSDir, parser);
 
-        sedimentLoads = parser.getSedimentLoads();
+        this.sedimentLoads = parser.getSedimentLoads();
     }
 
 
@@ -710,29 +731,29 @@
 
         log.info("Parse waterlevels");
 
-        File minfo  = getMinfoDir();
-        File fixDir = new File(minfo, MINFO_FIXATIONS_DIR);
-        File wspDir = new File(fixDir, MINFO_WATERLEVELS_DIR);
+        final File minfo  = getMinfoDir();
+        final File fixDir = new File(minfo, MINFO_FIXATIONS_DIR);
+        final File wspDir = new File(fixDir, MINFO_WATERLEVELS_DIR);
 
-        File[] files = wspDir.listFiles();
+        final File[] files = wspDir.listFiles();
 
         if (files == null) {
             log.warn("Cannot read directory for wl '" + wspDir + "'");
             return;
         }
 
-        WaterlevelParser parser = new WaterlevelParser();
+        final WaterlevelParser parser = new WaterlevelParser();
 
-        for (File file: files) {
+        for (final File file: files) {
             parser.parse(file);
         }
 
         // The parsed ImportWaterlevels are converted to
         // 'fixation'-wsts now.
-        for(ImportWst iw: parser.getWaterlevels()) {
+        for(final ImportWst iw: parser.getWaterlevels()) {
             iw.setDescription("CSV/" + iw.getDescription());
             iw.setKind(7);
-            waterlevels.add(iw);
+            this.waterlevels.add(iw);
         }
     }
 
@@ -744,27 +765,27 @@
 
         log.info("Parse measurement stations");
 
-        File minfo = getMinfoDir();
-        File minfoBaseDir = new File(minfo, MINFO_BASE_DIR);
-        File coredataFile = new File(minfoBaseDir, MINFO_CORE_DATA_FILE);
+        final File minfo = getMinfoDir();
+        final File minfoBaseDir = new File(minfo, MINFO_BASE_DIR);
+        final File coredataFile = new File(minfoBaseDir, MINFO_CORE_DATA_FILE);
 
         if (coredataFile == null || !coredataFile.exists()) {
             log.warn("No core data file '"
-                + coredataFile.getAbsolutePath() + "' found");
+                    + coredataFile.getAbsolutePath() + "' found");
             return;
         }
 
-        MeasurementStationsParser parser = new MeasurementStationsParser();
+        final MeasurementStationsParser parser = new MeasurementStationsParser();
         try {
             parser.parse(coredataFile);
-            measurementStations = parser.getMeasurementStations();
+            this.measurementStations = parser.getMeasurementStations();
 
-            log.info("Successfully parsed " + measurementStations.size()
-                + " measurement stations.");
+            log.info("Successfully parsed " + this.measurementStations.size()
+            + " measurement stations.");
         }
-        catch (IOException ioe) {
+        catch (final IOException ioe) {
             log.error("unable to parse file '" + coredataFile.getName() +
-                ": " + ioe.getMessage());
+                    ": " + ioe.getMessage());
         }
     }
 
@@ -777,28 +798,28 @@
 
         log.info("Parse waterlevel differences");
 
-        File minfo  = getMinfoDir();
-        File fixDir = new File(minfo, MINFO_FIXATIONS_DIR);
-        File diffDir = new File(fixDir, MINFO_WATERLEVEL_DIFF_DIR);
+        final File minfo  = getMinfoDir();
+        final File fixDir = new File(minfo, MINFO_FIXATIONS_DIR);
+        final File diffDir = new File(fixDir, MINFO_WATERLEVEL_DIFF_DIR);
 
-        File[] files = diffDir.listFiles();
+        final File[] files = diffDir.listFiles();
 
         if (files == null) {
             log.warn("Cannot read directory '" + diffDir + "'");
             return;
         }
 
-        WaterlevelDifferencesParser parser = new WaterlevelDifferencesParser();
+        final WaterlevelDifferencesParser parser = new WaterlevelDifferencesParser();
 
-        for (File file: files) {
+        for (final File file: files) {
             parser.parse(file);
         }
 
         // WaterlevelDifferences become Wsts now.
-        for(ImportWst iw: parser.getDifferences()) {
+        for(final ImportWst iw: parser.getDifferences()) {
             iw.setDescription("CSV/" + iw.getDescription());
             iw.setKind(6);
-            waterlevelDifferences.add(iw);
+            this.waterlevelDifferences.add(iw);
         }
     }
 
@@ -811,45 +832,50 @@
 
         log.info("Parse sq relations");
 
-        File minfo = getMinfoDir();
-        File sqDir = new File(minfo, MINFO_SQ_DIR);
+        final File minfo = getMinfoDir();
+        final File sqDir = new File(minfo, MINFO_SQ_DIR);
 
-        File[] files = sqDir.listFiles();
+        final File[] files = sqDir.listFiles();
 
         if (files == null) {
             log.warn("Cannot read directory '" + sqDir + "'");
             return;
         }
 
-        SQRelationParser parser = new SQRelationParser(getPeer());
+        final SQRelationParser parser = new SQRelationParser(getPeer());
 
-        for (File file: files) {
+        for (final File file: files) {
             parser.parse(file);
         }
 
-        sqRelations = parser.getSQRelations();
+        this.sqRelations = parser.getSQRelations();
 
-        log.debug("Parsed " + sqRelations.size() + " SQ relations.");
+        log.debug("Parsed " + this.sqRelations.size() + " SQ relations.");
     }
 
 
-    protected void parseBedHeights(File dir) throws IOException {
+    protected void parseBedHeights(final File dir) throws IOException {
         log.debug("Parse bed height singles");
 
-        File[] files = dir.listFiles();
+        final File[] files = dir.listFiles(new FilenameFilter() {
+            @Override
+            public boolean accept(final File dir, final String name) {
+                return name.toLowerCase().endsWith(".csv");
+            }
+        });
 
         if (files == null) {
             log.warn("Cannot read directory '" + dir + "'");
             return;
         }
 
-        BedHeightParser parser = new BedHeightParser();
+        final BedHeightParser parser = new BedHeightParser();
 
-        for (File file: files) {
+        for (final File file: files) {
             parser.parse(file);
         }
 
-        bedHeights = parser.getBedHeights();
+        this.bedHeights = parser.getBedHeights();
     }
 
     public void parseFloodWater() throws IOException {
@@ -860,40 +886,40 @@
 
         log.info("Parse flood water wst file");
 
-        File riverDir = wstFile.getParentFile().getParentFile();
+        final File riverDir = this.wstFile.getParentFile().getParentFile();
 
-        File dir = FileTools.repair(new File(riverDir, FLOOD_WATER));
+        final File dir = FileTools.repair(new File(riverDir, FLOOD_WATER));
 
         if (!dir.isDirectory() || !dir.canRead()) {
             log.info("no directory '" + dir + "' found");
             return;
         }
 
-        File [] files = dir.listFiles();
+        final File [] files = dir.listFiles();
 
         if (files == null) {
             log.warn("cannot read '" + dir + "'");
             return;
         }
 
-        for (File file: files) {
+        for (final File file: files) {
             if (!file.isFile() || !file.canRead()) {
                 continue;
             }
-            String name = file.getName().toLowerCase();
+            final String name = file.getName().toLowerCase();
             if (!(name.endsWith(".zus") || name.endsWith(".wst"))) {
                 continue;
             }
             log.info("found file '" + file.getName() + "'");
             try {
-                WstParser wstParser = new WstParser();
+                final WstParser wstParser = new WstParser();
                 wstParser.parse(file);
-                ImportWst iw = wstParser.getWst();
+                final ImportWst iw = wstParser.getWst();
                 iw.setKind(4);
                 iw.setDescription(FLOOD_WATER + "/" + iw.getDescription());
-                floodWater.add(iw);
+                this.floodWater.add(iw);
             }
-            catch (WstParser.ParseException e) {
+            catch (final WstParser.ParseException e) {
                 log.error(e.getMessage());
             }
         }
@@ -907,31 +933,31 @@
 
         log.info("Parse official wst files");
 
-        File riverDir = wstFile.getParentFile().getParentFile();
+        final File riverDir = this.wstFile.getParentFile().getParentFile();
 
-        for (String folder: OFFICIAL_LINES_FOLDERS) {
-            File dir = FileTools.repair(new File(riverDir, folder));
+        for (final String folder: OFFICIAL_LINES_FOLDERS) {
+            final File dir = FileTools.repair(new File(riverDir, folder));
 
             if (!dir.isDirectory() || !dir.canRead()) {
                 log.info("no directory '" + folder + "' found");
                 continue;
             }
 
-            File file = FileTools.repair(new File(dir, OFFICIAL_LINES));
+            final File file = FileTools.repair(new File(dir, OFFICIAL_LINES));
             if (!file.isFile() || !file.canRead()) {
                 log.warn("no official lines wst file found");
                 continue;
             }
             log.debug("Found WST file: " + file);
 
-            ImportWst iw = new ImportWst(
-                ImportOfficialWstColumn.COLUMN_FACTORY);
+            final ImportWst iw = new ImportWst(
+                    ImportOfficialWstColumn.COLUMN_FACTORY);
 
-            WstParser wstParser = new WstParser(iw);
+            final WstParser wstParser = new WstParser(iw);
             try {
                 wstParser.parse(file);
             }
-            catch (WstParser.ParseException e) {
+            catch (final WstParser.ParseException e) {
                 log.error(e.getMessage());
                 continue;
             }
@@ -939,41 +965,41 @@
             iw.setKind(3);
             iw.setDescription(folder + "/" + iw.getDescription());
 
-            File configFile = FileTools.repair(
-                new File(dir, OFFICIAL_LINES_CONFIG));
+            final File configFile = FileTools.repair(
+                    new File(dir, OFFICIAL_LINES_CONFIG));
             if (!configFile.isFile() || !configFile.canRead()) {
                 log.warn("no config file for official lines found");
             }
             else {
-                OfficialLinesConfigParser olcp =
-                    new OfficialLinesConfigParser();
+                final OfficialLinesConfigParser olcp =
+                        new OfficialLinesConfigParser();
                 try {
                     olcp.parse(configFile);
                 }
-                catch (IOException ioe) {
+                catch (final IOException ioe) {
                     log.warn("Error reading offical lines config", ioe);
                 }
-                List<String> mainValueNames = olcp.getMainValueNames();
+                final List<String> mainValueNames = olcp.getMainValueNames();
                 if (mainValueNames.isEmpty()) {
                     log.warn(
-                        "config file for offical lines contains no entries");
+                            "config file for offical lines contains no entries");
                 }
                 else {
                     // Join as much as possible.
-                    Iterator<ImportWstColumn> wi = iw.getColumns().iterator();
-                    Iterator<String> si = olcp.getMainValueNames().iterator();
+                    final Iterator<ImportWstColumn> wi = iw.getColumns().iterator();
+                    final Iterator<String> si = olcp.getMainValueNames().iterator();
                     while (wi.hasNext() && si.hasNext()) {
-                        ImportOfficialWstColumn wc =
-                            (ImportOfficialWstColumn)wi.next();
-                        String name = si.next();
-                        ImportOfficialLine iol =
-                            new ImportOfficialLine(name, wc);
+                        final ImportOfficialWstColumn wc =
+                                (ImportOfficialWstColumn)wi.next();
+                        final String name = si.next();
+                        final ImportOfficialLine iol =
+                                new ImportOfficialLine(name, wc);
                         wc.setOfficialLine(iol);
                     }
                 }
             }
 
-            officialLines.add(iw);
+            this.officialLines.add(iw);
         } // for all folders
 
     }
@@ -986,42 +1012,42 @@
 
         log.info("Parse fixation wst files");
 
-        File riverDir = wstFile.getParentFile().getParentFile();
+        final File riverDir = this.wstFile.getParentFile().getParentFile();
 
-        File fixDir = FileTools.repair(
-            new File(riverDir, FIXATIONS));
+        final File fixDir = FileTools.repair(
+                new File(riverDir, FIXATIONS));
 
         if (!fixDir.isDirectory() || !fixDir.canRead()) {
             log.info("no fixation wst file directory found");
             return;
         }
 
-        File [] files = fixDir.listFiles();
+        final File [] files = fixDir.listFiles();
 
         if (files == null) {
             log.warn("cannot read fixations wst file directory");
             return;
         }
 
-        for (File file: files) {
+        for (final File file: files) {
             if (!file.isFile() || !file.canRead()) {
                 continue;
             }
-            String name = file.getName().toLowerCase();
+            final String name = file.getName().toLowerCase();
             if (!name.endsWith(".wst")) {
                 continue;
             }
             log.debug("Found WST file: " + file);
 
             try {
-                WstParser wstParser = new WstParser();
+                final WstParser wstParser = new WstParser();
                 wstParser.parse(file);
-                ImportWst iw = wstParser.getWst();
+                final ImportWst iw = wstParser.getWst();
                 iw.setKind(2);
                 iw.setDescription(FIXATIONS+ "/" + iw.getDescription());
-                fixations.add(iw);
+                this.fixations.add(iw);
             }
-            catch (WstParser.ParseException e) {
+            catch (final WstParser.ParseException e) {
                 log.error(e.getMessage());
             }
         }
@@ -1035,43 +1061,43 @@
 
         log.info("Parse extra longitudinal wst files");
 
-        File riverDir = wstFile.getParentFile().getParentFile();
+        final File riverDir = this.wstFile.getParentFile().getParentFile();
 
-        File extraDir = FileTools.repair(
-            new File(riverDir, EXTRA_LONGITUDINALS));
+        final File extraDir = FileTools.repair(
+                new File(riverDir, EXTRA_LONGITUDINALS));
 
         if (!extraDir.isDirectory() || !extraDir.canRead()) {
             log.info("no extra longitudinal wst file directory found");
             return;
         }
 
-        File [] files = extraDir.listFiles();
+        final File [] files = extraDir.listFiles();
 
         if (files == null) {
             log.warn("cannot read extra longitudinal wst file directory");
             return;
         }
 
-        for (File file: files) {
+        for (final File file: files) {
             if (!file.isFile() || !file.canRead()) {
                 continue;
             }
-            String name = file.getName().toLowerCase();
+            final String name = file.getName().toLowerCase();
             if (!(name.endsWith(".zus") || name.endsWith(".wst"))) {
                 continue;
             }
             log.debug("Found WST file: " + file);
 
             try {
-                WstParser wstParser = new WstParser();
+                final WstParser wstParser = new WstParser();
                 wstParser.parse(file);
-                ImportWst iw = wstParser.getWst();
+                final ImportWst iw = wstParser.getWst();
                 iw.setKind(1);
                 iw.setDescription(
-                    EXTRA_LONGITUDINALS + "/" + iw.getDescription());
-                extraWsts.add(iw);
+                        EXTRA_LONGITUDINALS + "/" + iw.getDescription());
+                this.extraWsts.add(iw);
             }
-            catch (WstParser.ParseException e) {
+            catch (final WstParser.ParseException e) {
                 log.error(e.getMessage());
             }
         }
@@ -1084,13 +1110,13 @@
             return;
         }
 
-        WstParser wstParser = new WstParser();
+        final WstParser wstParser = new WstParser();
         try {
-            wstParser.parse(wstFile);
-            wst = wstParser.getWst();
-            wst.setKmUp(wst.guessWaterLevelIncreasing());
+            wstParser.parse(this.wstFile);
+            this.wst = wstParser.getWst();
+            this.wst.setKmUp(this.wst.guessWaterLevelIncreasing());
         }
-        catch (WstParser.ParseException e) {
+        catch (final WstParser.ParseException e) {
             log.error(e.getMessage());
         }
     }
@@ -1101,7 +1127,7 @@
             return;
         }
 
-        File gltFile = new File(wstFile.getParentFile(), PEGEL_GLT);
+        File gltFile = new File(this.wstFile.getParentFile(), PEGEL_GLT);
         gltFile = FileTools.repair(gltFile);
 
         if (!gltFile.isFile() || !gltFile.canRead()) {
@@ -1109,12 +1135,12 @@
             return;
         }
 
-        PegelGltParser pgltp = new PegelGltParser();
+        final PegelGltParser pgltp = new PegelGltParser();
         pgltp.parse(gltFile);
 
-        gauges = pgltp.getGauges();
+        this.gauges = pgltp.getGauges();
 
-        for (ImportGauge gauge: gauges) {
+        for (final ImportGauge gauge: this.gauges) {
             gauge.parseDependencies();
         }
     }
@@ -1125,12 +1151,12 @@
             return;
         }
 
-        File riverDir = wstFile.getParentFile().getParentFile();
-        AnnotationsParser aparser =
-            new AnnotationsParser(annotationClassifier);
+        final File riverDir = this.wstFile.getParentFile().getParentFile();
+        final AnnotationsParser aparser =
+                new AnnotationsParser(this.annotationClassifier);
         aparser.parse(riverDir);
 
-        annotations = aparser.getAnnotations();
+        this.annotations = aparser.getAnnotations();
     }
 
     public void parseHYKs() {
@@ -1140,33 +1166,33 @@
         }
 
         log.info("looking for HYK files");
-        HYKParser parser = new HYKParser();
-        File riverDir = wstFile
-            .getParentFile()  // Basisdaten
-            .getParentFile()  // Hydrologie
-            .getParentFile(); // <river>
+        final HYKParser parser = new HYKParser();
+        final File riverDir = this.wstFile
+                .getParentFile()  // Basisdaten
+                .getParentFile()  // Hydrologie
+                .getParentFile(); // <river>
 
         parser.parseHYKs(riverDir, new HYKParser.Callback() {
 
-            Set<HashedFile> hfs = new HashSet<HashedFile>();
+            Set<HashedFile> hfs = new HashSet<>();
 
             @Override
-            public boolean hykAccept(File file) {
-                HashedFile hf = new HashedFile(file);
-                boolean success = hfs.add(hf);
+            public boolean hykAccept(final File file) {
+                final HashedFile hf = new HashedFile(file);
+                final boolean success = this.hfs.add(hf);
                 if (!success) {
                     log.warn("HYK file '" + file
-                        + "' seems to be a duplicate.");
+                            + "' seems to be a duplicate.");
                 }
                 return success;
             }
 
             @Override
-            public void hykParsed(HYKParser parser) {
+            public void hykParsed(final HYKParser parser) {
                 log.debug("callback from HYK parser");
-                ImportHYK hyk = parser.getHYK();
+                final ImportHYK hyk = parser.getHYK();
                 hyk.setRiver(ImportRiver.this);
-                hyks.add(hyk);
+                ImportRiver.this.hyks.add(hyk);
             }
         });
     }
@@ -1178,14 +1204,14 @@
             log.info("skip parsing W80s");
             return;
         }
-        W80Parser parser = new W80Parser();
-        File riverDir = wstFile
-            .getParentFile()  // Basisdaten
-            .getParentFile()  // Hydrologie
-            .getParentFile(); // <river>
+        final W80Parser parser = new W80Parser();
+        final File riverDir = this.wstFile
+                .getParentFile()  // Basisdaten
+                .getParentFile()  // Hydrologie
+                .getParentFile(); // <river>
 
-        ImportRiverCrossSectionParserCallback w80Callback =
-            new ImportRiverCrossSectionParserCallback("w80");
+        final ImportRiverCrossSectionParserCallback w80Callback =
+                new ImportRiverCrossSectionParserCallback("w80");
         parser.parseW80s(riverDir, w80Callback);
     }
 
@@ -1195,20 +1221,20 @@
             log.info("skip parsing W80 csvs");
             return;
         }
-        W80CSVParser parser = new W80CSVParser();
-        File riverDir = wstFile
-            .getParentFile()  // Basisdaten
-            .getParentFile()  // Hydrologie
-            .getParentFile(); // <river>
+        final W80CSVParser parser = new W80CSVParser();
+        final File riverDir = this.wstFile
+                .getParentFile()  // Basisdaten
+                .getParentFile()  // Hydrologie
+                .getParentFile(); // <river>
 
         // Construct the Cross-Section-Data path.
-        File csDir = new File(riverDir.getPath()
-            + File.separator + "Geodaesie"
-            + File.separator + "Querprofile"
-            + File.separator + "QP-Daten");
+        final File csDir = new File(riverDir.getPath()
+                + File.separator + "Geodaesie"
+                + File.separator + "Querprofile"
+                + File.separator + "QP-Daten");
 
-        ImportRiverCrossSectionParserCallback w80CSVCallback =
-            new ImportRiverCrossSectionParserCallback("w80-csv");
+        final ImportRiverCrossSectionParserCallback w80CSVCallback =
+                new ImportRiverCrossSectionParserCallback("w80-csv");
         parser.parseW80CSVs(csDir, w80CSVCallback);
     }
 
@@ -1222,14 +1248,14 @@
             log.info("skip parsing DA50s");
             return;
         }
-        DA50Parser parser = new DA50Parser();
-        File riverDir = wstFile
-            .getParentFile()  // Basisdaten
-            .getParentFile()  // Hydrologie
-            .getParentFile(); // <river>
+        final DA50Parser parser = new DA50Parser();
+        final File riverDir = this.wstFile
+                .getParentFile()  // Basisdaten
+                .getParentFile()  // Hydrologie
+                .getParentFile(); // <river>
 
-        ImportRiverCrossSectionParserCallback da50Callback =
-            new ImportRiverCrossSectionParserCallback("da50");
+        final ImportRiverCrossSectionParserCallback da50Callback =
+                new ImportRiverCrossSectionParserCallback("da50");
 
         parser.parseDA50s(riverDir, da50Callback);
     }
@@ -1245,14 +1271,14 @@
         }
 
         log.info("looking for DA66 files");
-        DA66Parser parser = new DA66Parser();
-        File riverDir = wstFile
-            .getParentFile()  // Basisdaten
-            .getParentFile()  // Hydrologie
-            .getParentFile(); // <river>
+        final DA66Parser parser = new DA66Parser();
+        final File riverDir = this.wstFile
+                .getParentFile()  // Basisdaten
+                .getParentFile()  // Hydrologie
+                .getParentFile(); // <river>
 
-        ImportRiverCrossSectionParserCallback da66Callback =
-            new ImportRiverCrossSectionParserCallback("da66");
+        final ImportRiverCrossSectionParserCallback da66Callback =
+                new ImportRiverCrossSectionParserCallback("da66");
 
         parser.parseDA66s(riverDir, da66Callback);
     }
@@ -1265,21 +1291,21 @@
         }
 
         log.info("looking for PRF files");
-        PRFParser parser = new PRFParser();
-        File riverDir = wstFile
-            .getParentFile()  // Basisdaten
-            .getParentFile()  // Hydrologie
-            .getParentFile(); // <river>
+        final PRFParser parser = new PRFParser();
+        final File riverDir = this.wstFile
+                .getParentFile()  // Basisdaten
+                .getParentFile()  // Hydrologie
+                .getParentFile(); // <river>
 
-        ImportRiverCrossSectionParserCallback prfCallback =
-            new ImportRiverCrossSectionParserCallback("prf");
+        final ImportRiverCrossSectionParserCallback prfCallback =
+                new ImportRiverCrossSectionParserCallback("prf");
         parser.parsePRFs(riverDir, prfCallback);
     }
 
-    public static Date yearToDate(int year) {
-        Calendar cal = Calendar.getInstance();
+    public static Date yearToDate(final int year) {
+        final Calendar cal = Calendar.getInstance();
         cal.set(year, 5, 15, 12, 0, 0);
-        long ms = cal.getTimeInMillis();
+        final long ms = cal.getTimeInMillis();
         cal.setTimeInMillis(ms - ms%1000);
         return cal.getTime();
     }
@@ -1288,13 +1314,13 @@
         /* test whether river is already in database.
          * Otherwise it makes no sense to skip waterlevel model WST-file
          * because the altitude reference is taken from there. */
-        Session session = ImporterSession.getInstance().getDatabaseSession();
-        Query query = session.createQuery("from River where name=:name");
-        query.setString("name", name);
-        List<River> rivers = query.list();
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("from River where name=:name");
+        query.setString("name", this.name);
+        final List<River> rivers = query.list();
         if (rivers.isEmpty() && Config.INSTANCE.skipWst()){
             log.error("River not yet in database. "
-                + "You cannot skip importing waterlevel model.");
+                    + "You cannot skip importing waterlevel model.");
             return;
         }
 
@@ -1321,15 +1347,17 @@
         storeWaterlevelDifferences();
         storeSQRelations();
         storeOfficialNumber();
+        this.sinfoImporter.store();
+        this.uinfoImporter.store();
     }
 
     public void storeWstUnit() {
-        if (wst == null) {
+        if (this.wst == null) {
             log.warn("No unit given. "
-                + "Waterlevel-model WST-file has to be imported already.");
+                    + "Waterlevel-model WST-file has to be imported already.");
         }
         else {
-            wstUnit = wst.getUnit();
+            this.wstUnit = this.wst.getUnit();
         }
     }
 
@@ -1337,7 +1365,7 @@
         if (!Config.INSTANCE.skipHYKs()) {
             log.info("store HYKs");
             getPeer();
-            for (ImportHYK hyk: hyks) {
+            for (final ImportHYK hyk: this.hyks) {
                 hyk.storeDependencies();
             }
         }
@@ -1345,28 +1373,28 @@
 
     public void storeCrossSections() {
         if (!Config.INSTANCE.skipPRFs()
-            || !Config.INSTANCE.skipDA66s()
-            || !Config.INSTANCE.skipDA50s()
-            || !Config.INSTANCE.skipW80s()
-            || !Config.INSTANCE.skipW80CSVs()) {
+                || !Config.INSTANCE.skipDA66s()
+                || !Config.INSTANCE.skipDA50s()
+                || !Config.INSTANCE.skipW80s()
+                || !Config.INSTANCE.skipW80CSVs()) {
             log.info("store cross sections");
             getPeer();
-            for (ImportCrossSection crossSection: crossSections) {
+            for (final ImportCrossSection crossSection: this.crossSections) {
                 crossSection.storeDependencies();
             }
         }
     }
 
     public void storeWst() {
-        if (wst != null && !Config.INSTANCE.skipWst()) {
-            River river = getPeer();
-            wst.storeDependencies(river);
+        if (this.wst != null && !Config.INSTANCE.skipWst()) {
+            final River river = getPeer();
+            this.wst.storeDependencies(river);
 
             // The flow direction of the main wst and the corresponding
             // waterlevels determine if the river is 'km_up'.
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            river.setKmUp(wst.getKmUp());
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            river.setKmUp(this.wst.getKmUp());
             session.save(river);
         }
     }
@@ -1374,8 +1402,8 @@
     public void storeFixations() {
         if (!Config.INSTANCE.skipFixations()) {
             log.info("store fixation wsts");
-            River river = getPeer();
-            for (ImportWst fWst: fixations) {
+            final River river = getPeer();
+            for (final ImportWst fWst: this.fixations) {
                 log.debug("Fixation name: " + fWst.getDescription());
                 fWst.storeDependencies(river);
             }
@@ -1387,9 +1415,9 @@
     public void storeWaterlevels() {
         if (!Config.INSTANCE.skipWaterlevels())
 
-        log.info("store waterlevel wsts from csv");
-        River river = getPeer();
-        for (ImportWst wWst: waterlevels) {
+            log.info("store waterlevel wsts from csv");
+        final River river = getPeer();
+        for (final ImportWst wWst: this.waterlevels) {
             log.debug("Waterlevel name: " + wWst.getDescription());
             wWst.storeDependencies(river);
         }
@@ -1400,9 +1428,9 @@
     public void storeWaterlevelDifferences() {
         if (!Config.INSTANCE.skipWaterlevelDifferences())
 
-        log.info("store waterleveldifferences wsts from csv");
-        River river = getPeer();
-        for (ImportWst dWst: waterlevelDifferences) {
+            log.info("store waterleveldifferences wsts from csv");
+        final River river = getPeer();
+        for (final ImportWst dWst: this.waterlevelDifferences) {
             log.debug("water.diff.: name " + dWst.getDescription());
             dWst.storeDependencies(river);
         }
@@ -1412,8 +1440,8 @@
     public void storeExtraWsts() {
         if (!Config.INSTANCE.skipExtraWsts()) {
             log.info("store extra wsts");
-            River river = getPeer();
-            for (ImportWst wst: extraWsts) {
+            final River river = getPeer();
+            for (final ImportWst wst: this.extraWsts) {
                 log.debug("name: " + wst.getDescription());
                 wst.storeDependencies(river);
             }
@@ -1421,24 +1449,24 @@
     }
 
     public void storeOfficialLines() {
-        if (Config.INSTANCE.skipOfficialLines() || officialLines.isEmpty()) {
+        if (Config.INSTANCE.skipOfficialLines() || this.officialLines.isEmpty()) {
             return;
         }
 
         log.info("store official lines wsts");
-        River river = getPeer();
-        for (ImportWst wst: officialLines) {
+        final River river = getPeer();
+        for (final ImportWst wst: this.officialLines) {
             log.debug("name: " + wst.getDescription());
             wst.storeDependencies(river);
 
             // Store the official lines after the columns are store.
-            for (ImportWstColumn wc: wst.getColumns()) {
-                ImportOfficialWstColumn owc = (ImportOfficialWstColumn)wc;
-                ImportOfficialLine ioc = owc.getOfficialLine();
+            for (final ImportWstColumn wc: wst.getColumns()) {
+                final ImportOfficialWstColumn owc = (ImportOfficialWstColumn)wc;
+                final ImportOfficialLine ioc = owc.getOfficialLine();
                 if (ioc != null) {
                     if (ioc.getPeer(river) == null) {
                         log.warn("Cannot store official line: "
-                            + ioc.getName());
+                                + ioc.getName());
                     }
                 }
             }
@@ -1448,8 +1476,8 @@
     public void storeFloodWater() {
         if (!Config.INSTANCE.skipFloodWater()) {
             log.info("store flood water wsts");
-            River river = getPeer();
-            for (ImportWst wst: floodWater) {
+            final River river = getPeer();
+            for (final ImportWst wst: this.floodWater) {
                 log.debug("name: " + wst.getDescription());
                 wst.storeDependencies(river);
             }
@@ -1460,8 +1488,8 @@
     public void storeFloodProtection() {
         if (!Config.INSTANCE.skipFloodProtection()) {
             log.info("store flood protection wsts");
-            River river = getPeer();
-            for (ImportWst wst: floodProtection) {
+            final River river = getPeer();
+            for (final ImportWst wst: this.floodProtection) {
                 log.debug("name: " + wst.getDescription());
                 wst.storeDependencies(river);
             }
@@ -1472,13 +1500,13 @@
     public void storeBedHeight() {
         if (!Config.INSTANCE.skipBedHeight()) {
             log.info("store bed heights");
-            River river = getPeer();
+            final River river = getPeer();
 
-            if (bedHeights != null) {
-                for (ImportBedHeight tmp: bedHeights) {
-                    ImportBedHeight single = (ImportBedHeight) tmp;
+            if (this.bedHeights != null) {
+                for (final ImportBedHeight tmp: this.bedHeights) {
+                    final ImportBedHeight single = tmp;
 
-                    String desc = single.getDescription();
+                    final String desc = single.getDescription();
 
                     log.debug("name: " + desc);
 
@@ -1496,10 +1524,10 @@
         if (!Config.INSTANCE.skipSedimentDensity()) {
             log.info("store sediment density");
 
-            River river = getPeer();
+            final River river = getPeer();
 
-            for (ImportSedimentDensity density: sedimentDensities) {
-                String desc = density.getDescription();
+            for (final ImportSedimentDensity density: this.sedimentDensities) {
+                final String desc = density.getDescription();
 
                 log.debug("name: " + desc);
 
@@ -1512,10 +1540,10 @@
         if (!Config.INSTANCE.skipPorosity()) {
             log.info("store porosity");
 
-            River river = getPeer();
+            final River river = getPeer();
 
-            for (ImportPorosity porosity: porosities) {
-                String desc = porosity.getDescription();
+            for (final ImportPorosity porosity: this.porosities) {
+                final String desc = porosity.getDescription();
 
                 log.debug("name: " + desc);
 
@@ -1528,9 +1556,9 @@
         if (!Config.INSTANCE.skipMorphologicalWidth()) {
             log.info("store morphological width");
 
-            River river = getPeer();
+            final River river = getPeer();
 
-            for (ImportMorphWidth width: morphologicalWidths) {
+            for (final ImportMorphWidth width: this.morphologicalWidths) {
                 width.storeDependencies(river);
             }
         }
@@ -1540,14 +1568,14 @@
         if (!Config.INSTANCE.skipFlowVelocity()) {
             log.info("store flow velocity");
 
-            River river = getPeer();
+            final River river = getPeer();
 
-            for (ImportFlowVelocityModel flowVelocityModel: flowVelocityModels
-            ) {
+            for (final ImportFlowVelocityModel flowVelocityModel: this.flowVelocityModels
+                    ) {
                 flowVelocityModel.storeDependencies(river);
             }
 
-            for (ImportFlowVelocityMeasurement m: flowVelocityMeasurements) {
+            for (final ImportFlowVelocityMeasurement m: this.flowVelocityMeasurements) {
                 m.storeDependencies(river);
             }
         }
@@ -1558,9 +1586,9 @@
         if (!Config.INSTANCE.skipSedimentLoadLS()) {
             log.info("store sediment load longitudinal section data");
 
-            River river = getPeer();
+            final River river = getPeer();
 
-            for (ImportSedimentLoadLS sedimentLoadLS: sedimentLoadLSs) {
+            for (final ImportSedimentLoadLS sedimentLoadLS: this.sedimentLoadLSs) {
                 sedimentLoadLS.storeDependencies(river);
             }
         }
@@ -1571,7 +1599,7 @@
         if (!Config.INSTANCE.skipSedimentLoad()) {
             log.info("store sediment load data at measurement stations");
 
-            for (ImportSedimentLoad sedimentLoad: sedimentLoads) {
+            for (final ImportSedimentLoad sedimentLoad: this.sedimentLoads) {
                 sedimentLoad.storeDependencies();
             }
         }
@@ -1582,12 +1610,12 @@
         if (!Config.INSTANCE.skipMeasurementStations()) {
             log.info("store measurement stations");
 
-            River river = getPeer();
+            final River river = getPeer();
 
             int count = 0;
 
-            for (ImportMeasurementStation station: measurementStations) {
-                boolean success = station.storeDependencies(river);
+            for (final ImportMeasurementStation station: this.measurementStations) {
+                final boolean success = station.storeDependencies(river);
                 if (success) {
                     count++;
                 }
@@ -1604,7 +1632,7 @@
 
             int count = 0;
 
-            for (ImportSQRelation sqRelation: sqRelations) {
+            for (final ImportSQRelation sqRelation: this.sqRelations) {
                 sqRelation.storeDependencies();
                 count++;
             }
@@ -1616,8 +1644,8 @@
 
     public void storeAnnotations() {
         if (!Config.INSTANCE.skipAnnotations()) {
-            River river = getPeer();
-            for (ImportAnnotation annotation: annotations) {
+            final River river = getPeer();
+            for (final ImportAnnotation annotation: this.annotations) {
                 annotation.getPeer(river);
             }
         }
@@ -1626,10 +1654,10 @@
     public void storeGauges() {
         if (!Config.INSTANCE.skipGauges()) {
             log.info("store gauges:");
-            River river = getPeer();
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            for (ImportGauge gauge: gauges) {
+            final River river = getPeer();
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            for (final ImportGauge gauge: this.gauges) {
                 log.info("\tgauge: " + gauge.getName());
                 gauge.storeDependencies(river);
                 ImporterSession.getInstance().getDatabaseSession();
@@ -1639,31 +1667,31 @@
     }
 
     public River getPeer() {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery("from River where name=:name");
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            final Query query = session.createQuery("from River where name=:name");
 
             Unit u = null;
-            if (wstUnit != null) {
-                u = wstUnit.getPeer();
+            if (this.wstUnit != null) {
+                u = this.wstUnit.getPeer();
             }
 
-            query.setString("name", name);
-            List<River> rivers = query.list();
+            query.setString("name", this.name);
+            final List<River> rivers = query.list();
             if (rivers.isEmpty()) {
-                log.info("Store new river '" + name + "'");
-                peer = new River(name, u, modelUuid);
+                log.info("Store new river '" + this.name + "'");
+                this.peer = new River(this.name, u, this.modelUuid);
                 if (!Config.INSTANCE.skipBWASTR()) {
-                    peer.setOfficialNumber(officialNumber);
+                    this.peer.setOfficialNumber(this.officialNumber);
                 }
-                session.save(peer);
+                session.save(this.peer);
             }
             else {
-                peer = rivers.get(0);
+                this.peer = rivers.get(0);
             }
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoad.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoad.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,9 +8,11 @@
 
 package org.dive4elements.river.importer;
 
+import java.util.ArrayList;
 import java.util.List;
-import java.util.ArrayList;
 
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.GrainFraction;
 import org.dive4elements.river.model.SedimentLoad;
 import org.dive4elements.river.model.TimeInterval;
@@ -19,6 +21,8 @@
 
 public class ImportSedimentLoad
 {
+    private static Logger log = Logger.getLogger(ImportSedimentLoad.class);
+
     private SedimentLoad peer;
 
     private ImportGrainFraction grainFraction;
@@ -27,92 +31,98 @@
     private String              description;
     private Integer             kind;
 
-    private List<ImportSedimentLoadValue> values;
+    private final List<ImportSedimentLoadValue> values;
+
+    protected StoreMode storeMode;
 
     public ImportSedimentLoad() {
-        this.values = new ArrayList<ImportSedimentLoadValue>();
+        this.values = new ArrayList<>();
     }
 
     public ImportSedimentLoad(
-        ImportGrainFraction grainFraction,
-        ImportTimeInterval  timeInterval,
-        ImportTimeInterval  sqTimeInterval,
-        String              description,
-        Integer             kind
-    ) {
+            final ImportGrainFraction grainFraction,
+            final ImportTimeInterval  timeInterval,
+            final ImportTimeInterval  sqTimeInterval,
+            final String              description,
+            final Integer             kind
+            ) {
         this.grainFraction  = grainFraction;
         this.timeInterval   = timeInterval;
         this.sqTimeInterval = sqTimeInterval;
         this.description    = description;
         this.kind           = kind;
 
-        this.values = new ArrayList<ImportSedimentLoadValue>();
+        this.values = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
-    public void addValue(ImportSedimentLoadValue value) {
-        values.add(value);
+    public void addValue(final ImportSedimentLoadValue value) {
+        this.values.add(value);
     }
 
     public void storeDependencies() {
-        grainFraction.getPeer();
-        timeInterval.getPeer();
+        log.info("store dependencies for '" + this.description + "'");
+        this.grainFraction.getPeer();
+        this.timeInterval.getPeer();
 
-        if (sqTimeInterval != null) {
-            sqTimeInterval.getPeer();
+        if (this.sqTimeInterval != null) {
+            this.sqTimeInterval.getPeer();
         }
 
         getPeer();
 
-        for (ImportSedimentLoadValue value : values) {
-            value.storeDependencies(peer);
+        for (final ImportSedimentLoadValue value : this.values) {
+            value.storeDependencies(this.peer, this.storeMode);
         }
-
+        log.info("Values processed: " + this.values.size());
     }
 
     public SedimentLoad getPeer() {
 
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-
-            String sqtquery = sqTimeInterval == null
-                ? "sq_time_interval_id is null"
-                : "sqTimeInterval = :sqTimeInterval";
-            Query query = session.createQuery(
-                "from SedimentLoad where " +
-                "   grainFraction = :grainFraction and " +
-                "   timeInterval = :timeInterval and " +
-                "   description = :description and " +
-                "   kind = :kind and " +
-                    sqtquery);
-
-            GrainFraction gf = grainFraction.getPeer();
-            TimeInterval  ti = timeInterval.getPeer();
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
 
-            TimeInterval sqti = sqTimeInterval != null
-                ? sqTimeInterval.getPeer()
-                : null;
-
-            query.setParameter("grainFraction", gf);
-            query.setParameter("timeInterval", ti);
+            final String sqtquery = this.sqTimeInterval == null
+                    ? "sq_time_interval_id is null"
+                            : "sqTimeInterval = :sqTimeInterval";
+            final Query query = session.createQuery(
+                    "from SedimentLoad where " +
+                            "   grainFraction = :grainFraction and " +
+                            "   timeInterval = :timeInterval and " +
+                            "   description = :description and " +
+                            "   kind = :kind and " +
+                            sqtquery);
 
-            if (sqti != null) {
-                query.setParameter("sqTimeInterval", sqti);
-            }
-            query.setParameter("description", description);
-            query.setParameter("kind", kind);
+            final GrainFraction gf = this.grainFraction.getPeer();
+            final TimeInterval  ti = this.timeInterval.getPeer();
 
-            List<SedimentLoad> loads = query.list();
-            if (loads.isEmpty()) {
-                peer = new SedimentLoad(gf, ti, sqti, description, kind);
-                session.save(peer);
-            }
-            else {
-                peer = loads.get(0);
-            }
+            final TimeInterval sqti = this.sqTimeInterval != null
+                    ? this.sqTimeInterval.getPeer()
+                            : null;
+
+                    query.setParameter("grainFraction", gf);
+                    query.setParameter("timeInterval", ti);
+
+                    if (sqti != null) {
+                        query.setParameter("sqTimeInterval", sqti);
+                    }
+                    query.setParameter("description", this.description);
+                    query.setParameter("kind", this.kind);
+
+                    final List<SedimentLoad> loads = query.list();
+                    if (loads.isEmpty()) {
+                        this.peer = new SedimentLoad(gf, ti, sqti, this.description, this.kind);
+                        session.save(this.peer);
+                        this.storeMode = StoreMode.INSERT;
+                    }
+                    else {
+                        this.peer = loads.get(0);
+                        this.storeMode = StoreMode.UPDATE;
+                    }
         }
 
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoadLS.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoadLS.java	Fri Jul 13 11:56:22 2018 +0200
@@ -12,15 +12,14 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.GrainFraction;
 import org.dive4elements.river.model.River;
 import org.dive4elements.river.model.SedimentLoadLS;
 import org.dive4elements.river.model.TimeInterval;
 import org.dive4elements.river.model.Unit;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportSedimentLoadLS {
@@ -35,53 +34,56 @@
 
     private ImportTimeInterval sqTimeInterval;
 
-    private String description;
+    private final String description;
 
     private Integer kind;
 
-    private List<ImportSedimentLoadLSValue> values;
+    private final List<ImportSedimentLoadLSValue> values;
+
+    protected StoreMode storeMode;
 
     private SedimentLoadLS peer;
 
-    public ImportSedimentLoadLS(String description) {
-        this.values = new ArrayList<ImportSedimentLoadLSValue>();
+    public ImportSedimentLoadLS(final String description) {
+        this.values = new ArrayList<>();
         this.description = description;
+        this.storeMode = StoreMode.NONE;
     }
 
-    public void setTimeInterval(ImportTimeInterval timeInterval) {
+    public void setTimeInterval(final ImportTimeInterval timeInterval) {
         this.timeInterval = timeInterval;
     }
 
-    public void setSQTimeInterval(ImportTimeInterval sqTimeInterval) {
+    public void setSQTimeInterval(final ImportTimeInterval sqTimeInterval) {
         this.sqTimeInterval = sqTimeInterval;
     }
 
-    public void setUnit(ImportUnit unit) {
+    public void setUnit(final ImportUnit unit) {
         this.unit = unit;
     }
 
-    public void setGrainFraction(ImportGrainFraction grainFraction) {
+    public void setGrainFraction(final ImportGrainFraction grainFraction) {
         this.grainFraction = grainFraction;
     }
 
-    public void setKind(Integer kind) {
+    public void setKind(final Integer kind) {
         this.kind = kind;
     }
 
-    public void addValue(ImportSedimentLoadLSValue value) {
+    public void addValue(final ImportSedimentLoadLSValue value) {
         this.values.add(value);
     }
 
-    public void storeDependencies(River river) {
-        log.debug("store dependencies");
+    public void storeDependencies(final River river) {
+        log.info("store dependencies for '" + this.description + "'");
 
-        SedimentLoadLS peer = getPeer(river);
+        final SedimentLoadLS peer = getPeer(river);
 
         if (peer != null) {
             int i = 0;
 
-            for (ImportSedimentLoadLSValue value : values) {
-                value.storeDependencies(peer);
+            for (final ImportSedimentLoadLSValue value : this.values) {
+                value.storeDependencies(peer, this.storeMode);
                 i++;
             }
 
@@ -89,40 +91,38 @@
         }
     }
 
-    public SedimentLoadLS getPeer(River river) {
+    public SedimentLoadLS getPeer(final River river) {
         log.debug("get peer");
 
-        GrainFraction gf = grainFraction != null ? grainFraction.getPeer()
-            : null;
+        final GrainFraction gf = this.grainFraction != null ? this.grainFraction.getPeer()
+                : null;
 
-        Unit u = unit != null ? unit.getPeer() : null;
+        final Unit u = this.unit != null ? this.unit.getPeer() : null;
 
-        TimeInterval ti = timeInterval != null ? timeInterval.getPeer() : null;
-        TimeInterval sqti = sqTimeInterval != null
-                ? sqTimeInterval.getPeer()
-                : null;
+        final TimeInterval ti = (this.timeInterval != null) ? this.timeInterval.getPeer() : null;
+        final TimeInterval sqti = (this.sqTimeInterval != null) ? this.sqTimeInterval.getPeer() : null;
 
         if (ti == null || u == null) {
             log.warn(
-                "Skip invalid SedimentLoadLS: time interval or unit null!");
+                    "Skip invalid SedimentLoadLS: time interval or unit null!");
             return null;
         }
 
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
 
-            String sqtquery = sqTimeInterval == null ?
-                "sq_time_interval_id is null" :
-                "sqTimeInterval = :sqTimeInterval";
-            Query query = session.createQuery("from SedimentLoadLS where "
-                + "   river=:river and "
-                + "   grainFraction=:grainFraction and "
-                + "   unit=:unit and "
-                + "   timeInterval=:timeInterval and "
-                + "   description=:description and "
-                + "   kind = :kind and " +
-                      sqtquery);
+            final String sqtquery = this.sqTimeInterval == null ?
+                    "sq_time_interval_id is null" :
+                        "sqTimeInterval = :sqTimeInterval";
+            final Query query = session.createQuery("from SedimentLoadLS where "
+                    + "   river=:river and "
+                    + "   grainFraction=:grainFraction and "
+                    + "   unit=:unit and "
+                    + "   timeInterval=:timeInterval and "
+                    + "   description=:description and "
+                    + "   kind = :kind and " +
+                    sqtquery);
 
             query.setParameter("river", river);
             query.setParameter("grainFraction", gf);
@@ -131,23 +131,25 @@
             if (sqti != null) {
                 query.setParameter("sqTimeInterval", sqti);
             }
-            query.setParameter("description", description);
-            query.setParameter("kind", kind);
+            query.setParameter("description", this.description);
+            query.setParameter("kind", this.kind);
 
-            List<SedimentLoadLS> loads = query.list();
+            final List<SedimentLoadLS> loads = query.list();
             if (loads.isEmpty()) {
                 log.debug("create new SedimentLoadLS");
 
-                peer = new SedimentLoadLS(river, u, ti, sqti, gf, description);
-                peer.setKind(this.kind);
-                session.save(peer);
+                this.peer = new SedimentLoadLS(river, u, ti, sqti, gf, this.description);
+                this.peer.setKind(this.kind);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = loads.get(0);
+                this.peer = loads.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
 
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoadLSValue.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoadLSValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,58 +10,60 @@
 
 import java.util.List;
 
-import org.hibernate.Session;
-import org.hibernate.Query;
-
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.SedimentLoadLS;
 import org.dive4elements.river.model.SedimentLoadLSValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportSedimentLoadLSValue {
 
-    private Double station;
-    private Double value;
+    private final Double station;
+    private final Double value;
 
     private SedimentLoadLSValue peer;
 
 
-    public ImportSedimentLoadLSValue(Double station, Double value) {
+    public ImportSedimentLoadLSValue(final Double station, final Double value) {
         this.station = station;
         this.value   = value;
     }
 
 
-    public void storeDependencies(SedimentLoadLS sedimentLoadLS) {
-        getPeer(sedimentLoadLS);
+    public void storeDependencies(final SedimentLoadLS sedimentLoadLS, final StoreMode parentStoreMode) {
+        getPeer(sedimentLoadLS, parentStoreMode);
     }
 
 
-    public SedimentLoadLSValue getPeer(SedimentLoadLS sedimentLoadLS) {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from SedimentLoadLSValue where " +
-                "   sedimentLoadLS=:sedimentLoadLS and " +
-                "   station=:station and " +
-                "   value=:value"
-            );
-
-            query.setParameter("sedimentLoadLS", sedimentLoadLS);
-            query.setParameter("station", station);
-            query.setParameter("value", value);
-
-            List<SedimentLoadLSValue> values = query.list();
-            if (values.isEmpty()) {
-                peer = new SedimentLoadLSValue(sedimentLoadLS, station, value);
-                session.save(peer);
+    public SedimentLoadLSValue getPeer(final SedimentLoadLS sedimentLoadLS, final StoreMode parentStoreMode) {
+        if (this.peer == null) {
+            List<SedimentLoadLSValue> values;
+            final Session session = ImporterSession.getInstance().getDatabaseSession();
+            if (parentStoreMode == StoreMode.INSERT)
+                values = null;
+            else {
+                final Query query = session.createQuery(
+                        "from SedimentLoadLSValue where " +
+                                "   sedimentLoadLS=:sedimentLoadLS and " +
+                                "   station=:station and " +
+                                "   value=:value"
+                        );
+                query.setParameter("sedimentLoadLS", sedimentLoadLS);
+                query.setParameter("station", this.station);
+                query.setParameter("value", this.value);
+                values = query.list();
+            }
+            if ((values == null) || values.isEmpty()) {
+                this.peer = new SedimentLoadLSValue(sedimentLoadLS, this.station, this.value);
+                session.save(this.peer);
             }
             else {
-                peer = values.get(0);
+                this.peer = values.get(0);
             }
         }
 
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoadValue.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentLoadValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,6 +10,7 @@
 
 import java.util.List;
 
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.MeasurementStation;
 import org.dive4elements.river.model.SedimentLoad;
 import org.dive4elements.river.model.SedimentLoadValue;
@@ -27,43 +28,48 @@
     }
 
     public ImportSedimentLoadValue(
-        MeasurementStation station,
-        Double             value
-    ) {
+            final MeasurementStation station,
+            final Double             value
+            ) {
         this.station      = station;
         this.value        = value;
     }
 
-    protected SedimentLoadValue getPeer(SedimentLoad sedimentLoad) {
+    protected SedimentLoadValue getPeer(final SedimentLoad sedimentLoad, final StoreMode parentStoreMode) {
 
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from SedimentLoadValue where " +
-                "   measurementStation = :station and " +
-                "   sedimentLoad = :sedimentLoad and " +
-                "   value = :value");
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            List<SedimentLoadValue> values;
+            if (parentStoreMode == StoreMode.INSERT)
+                values = null;
+            else {
+                final Query query = session.createQuery(
+                        "from SedimentLoadValue where " +
+                                "   measurementStation = :station and " +
+                                "   sedimentLoad = :sedimentLoad and " +
+                        "   value = :value");
 
-            query.setParameter("station", station);
-            query.setParameter("sedimentLoad", sedimentLoad);
-            query.setParameter("value", value);
+                query.setParameter("station", this.station);
+                query.setParameter("sedimentLoad", sedimentLoad);
+                query.setParameter("value", this.value);
 
-            List<SedimentLoadValue> values = query.list();
-            if (values.isEmpty()) {
-                peer = new SedimentLoadValue(sedimentLoad, station, value);
-                session.save(peer);
+                values = query.list();
+            }
+            if ((values == null) || values.isEmpty()) {
+                this.peer = new SedimentLoadValue(sedimentLoad, this.station, this.value);
+                session.save(this.peer);
             }
             else {
-                peer = values.get(0);
+                this.peer = values.get(0);
             }
         }
 
-        return peer;
+        return this.peer;
     }
 
-    public void storeDependencies(SedimentLoad sedimentLoad) {
-        getPeer(sedimentLoad);
+    public void storeDependencies(final SedimentLoad sedimentLoad, final StoreMode parentStoreMode) {
+        getPeer(sedimentLoad, parentStoreMode);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportWst.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportWst.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,16 +8,15 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.Wst;
-import org.dive4elements.river.model.River;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.Wst;
 import org.hibernate.Query;
-
-import java.util.ArrayList;
-import java.util.List;
+import org.hibernate.Session;
 
 /** Not (yet) db-mapped WST object. */
 public class ImportWst
@@ -29,12 +28,12 @@
     }
 
     public static final ImportWstColumnFactory COLUMN_FACTORY =
-        new ImportWstColumnFactory() {
-            @Override
-            public ImportWstColumn create(ImportWst importWst, int position) {
-                return new ImportWstColumn(importWst, null, null, position);
-            }
-        };
+            new ImportWstColumnFactory() {
+        @Override
+        public ImportWstColumn create(final ImportWst importWst, final int position) {
+            return new ImportWstColumn(importWst, null, null, position);
+        }
+    };
 
     protected String description;
 
@@ -48,6 +47,8 @@
 
     protected boolean kmUp;
 
+    protected StoreMode storeMode;
+
     /** Wst as in db. */
     protected Wst peer;
 
@@ -55,123 +56,126 @@
         this(COLUMN_FACTORY);
     }
 
-    public ImportWst(ImportWstColumnFactory columnFactory) {
+    public ImportWst(final ImportWstColumnFactory columnFactory) {
         this.columnFactory = columnFactory;
-        kind = 0;
-        columns = new ArrayList<ImportWstColumn>();
+        this.kind = 0;
+        this.columns = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
-    public ImportWst(String description) {
+    public ImportWst(final String description) {
         this(description, COLUMN_FACTORY);
     }
 
     public ImportWst(
-        String description,
-        ImportWstColumnFactory columnFactory
-    ) {
+            final String description,
+            final ImportWstColumnFactory columnFactory
+            ) {
         this(columnFactory);
         this.description = description;
     }
 
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
     public Integer getKind() {
-        return kind;
+        return this.kind;
     }
 
-    public void setKind(Integer kind) {
+    public void setKind(final Integer kind) {
         this.kind = kind;
     }
 
     public boolean getKmUp() {
-        return kmUp;
+        return this.kmUp;
     }
 
-    public void setKmUp(boolean kmUp) {
+    public void setKmUp(final boolean kmUp) {
         this.kmUp = kmUp;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
     /** Create columns that can be accessed with getColumn. */
-    public void setNumberColumns(int numColumns) {
+    public void setNumberColumns(final int numColumns) {
         for (int i = 0; i < numColumns; ++i) {
-            columns.add(columnFactory.create(this, i));
+            this.columns.add(this.columnFactory.create(this, i));
         }
     }
 
     public int getNumberColumns() {
-        return columns.size();
+        return this.columns.size();
     }
 
-    public ImportWstColumn getColumn(int index) {
-        return columns.get(index);
+    public ImportWstColumn getColumn(final int index) {
+        return this.columns.get(index);
     }
 
     public List<ImportWstColumn> getColumns() {
-        return columns;
+        return this.columns;
     }
 
     /** Adds a column. Assumes that columns wst is this instance. */
-    public void addColumn(ImportWstColumn column) {
-        columns.add(column);
+    public void addColumn(final ImportWstColumn column) {
+        this.columns.add(column);
     }
 
     public ImportUnit getUnit() {
-        return unit;
+        return this.unit;
     }
 
-    public void setUnit(ImportUnit unit) {
+    public void setUnit(final ImportUnit unit) {
         this.unit = unit;
     }
 
-    public void storeDependencies(River river) {
+    public void storeDependencies(final River river) {
 
-        log.info("store '" + description + "'");
+        log.info("store '" + this.description + "'");
         getPeer(river);
 
-        for (ImportWstColumn column: columns) {
+        for (final ImportWstColumn column: this.columns) {
             column.storeDependencies(river);
         }
 
-        Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
         session.flush();
     }
 
     public boolean guessWaterLevelIncreasing() {
         int up = 0;
-        for (ImportWstColumn column: columns) {
+        for (final ImportWstColumn column: this.columns) {
             if (column.guessWaterLevelIncreasing()) ++up;
         }
-        return up > columns.size() - up;
+        return up > this.columns.size() - up;
     }
 
     /** Get corresponding mapped wst (from database). */
-    public Wst getPeer(River river) {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from Wst where " +
-                "river=:river and description=:description and kind=:kind");
+    public Wst getPeer(final River river) {
+        if (this.peer == null) {
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            final Query query = session.createQuery(
+                    "from Wst where " +
+                    "river=:river and description=:description and kind=:kind");
             query.setParameter("river",       river);
-            query.setParameter("description", description);
-            query.setParameter("kind",        kind);
-            List<Wst> wsts = query.list();
+            query.setParameter("description", this.description);
+            query.setParameter("kind",        this.kind);
+            final List<Wst> wsts = query.list();
             if (wsts.isEmpty()) {
-                peer = new Wst(river, description, kind);
-                session.save(peer);
+                this.peer = new Wst(river, this.description, this.kind);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = wsts.get(0);
+                this.peer = wsts.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
 
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportWstColumn.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportWstColumn.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,21 +8,19 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.river.model.Wst;
-import org.dive4elements.river.model.WstColumn;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.StoreMode;
 import org.dive4elements.river.model.River;
 import org.dive4elements.river.model.TimeInterval;
-
-import org.hibernate.Session;
+import org.dive4elements.river.model.Wst;
+import org.dive4elements.river.model.WstColumn;
 import org.hibernate.Query;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Random;
-
-import java.math.BigDecimal;
-
-import org.apache.log4j.Logger;
+import org.hibernate.Session;
 
 
 /** Unmapped column of a WST. */
@@ -41,20 +39,23 @@
     protected List<ImportWstColumnQRange> columnQRanges;
     protected List<ImportWstColumnValue>  columnValues;
 
+    protected StoreMode storeMode;
+
     protected WstColumn peer;
 
     public ImportWstColumn() {
-        columnQRanges = new ArrayList<ImportWstColumnQRange>();
-        columnValues  = new ArrayList<ImportWstColumnValue>();
+        this.columnQRanges = new ArrayList<>();
+        this.columnValues  = new ArrayList<>();
+        this.storeMode = StoreMode.NONE;
     }
 
     public ImportWstColumn(
-        ImportWst wst,
-        String    name,
-        String    description,
-        Integer   position,
-        String    source
-    ) {
+            final ImportWst wst,
+            final String    name,
+            final String    description,
+            final Integer   position,
+            final String    source
+            ) {
         this();
         this.wst         = wst;
         this.name        = name;
@@ -63,114 +64,114 @@
     }
 
     public ImportWstColumn(
-        ImportWst wst,
-        String    name,
-        String    description,
-        Integer   position
-    ) {
+            final ImportWst wst,
+            final String    name,
+            final String    description,
+            final Integer   position
+            ) {
         this(wst, name, description, position, null);
     }
 
     public ImportWst getWst() {
-        return wst;
+        return this.wst;
     }
 
-    public void setWst(ImportWst wst) {
+    public void setWst(final ImportWst wst) {
         this.wst = wst;
     }
 
     public String getName() {
-        return name;
+        return this.name;
     }
 
-    public void setName(String name) {
+    public void setName(final String name) {
         this.name = name;
     }
 
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
     public Integer getPosition() {
-        return position;
+        return this.position;
     }
 
-    public void setPosition(Integer position) {
+    public void setPosition(final Integer position) {
         this.position = position;
     }
 
     public String getSource() {
-        return source;
+        return this.source;
     }
 
-    public void setSource(String source) {
+    public void setSource(final String source) {
         this.source = source;
     }
 
-    public void addColumnValue(BigDecimal position, BigDecimal w) {
-        columnValues.add(
-            new ImportWstColumnValue(this, position, w));
+    public void addColumnValue(final BigDecimal position, final BigDecimal w) {
+        this.columnValues.add(
+                new ImportWstColumnValue(this, position, w));
     }
 
-    public void addColumnQRange(ImportWstQRange columnQRange) {
-        columnQRanges.add(
-            new ImportWstColumnQRange(this, columnQRange));
+    public void addColumnQRange(final ImportWstQRange columnQRange) {
+        this.columnQRanges.add(
+                new ImportWstColumnQRange(this, columnQRange));
     }
 
 
     /** Get the Column Values stored in this column. */
     public List<ImportWstColumnValue> getColumnValues() {
-        return columnValues;
+        return this.columnValues;
     }
 
 
-    public void storeDependencies(River river) {
-        log.info("store column '" + name + "'");
+    public void storeDependencies(final River river) {
+        log.info("store column '" + this.name + "'");
         getPeer(river);
 
-        for (ImportWstColumnQRange columnQRange: columnQRanges) {
+        for (final ImportWstColumnQRange columnQRange: this.columnQRanges) {
             columnQRange.getPeer(river);
         }
 
-        for (ImportWstColumnValue columnValue: columnValues) {
+        for (final ImportWstColumnValue columnValue: this.columnValues) {
             columnValue.getPeer(river);
         }
     }
 
     public ImportTimeInterval getTimeInterval() {
-        return timeInterval;
+        return this.timeInterval;
     }
 
-    public void setTimeInterval(ImportTimeInterval timeInterval) {
+    public void setTimeInterval(final ImportTimeInterval timeInterval) {
         this.timeInterval = timeInterval;
     }
 
     public boolean guessWaterLevelIncreasing() {
 
-        int N = columnValues.size();
+        final int N = this.columnValues.size();
 
         if (N < 2) {
             return true;
         }
 
-        Random r = new Random();
+        final Random r = new Random();
         int up = 0;
 
-        int S = N < 50 ? N : (int)(0.1f * N)+1;
+        final int S = N < 50 ? N : (int)(0.1f * N)+1;
         for (int s = 0; s < S; ++s) {
             int i1, i2;
             do {
                 i1 = r.nextInt(N-1);
                 i2 = r.nextInt(N-1);
             } while (i1 == i2);
-            ImportWstColumnValue b = columnValues.get(i1);
-            ImportWstColumnValue a = columnValues.get(i2);
+            ImportWstColumnValue b = this.columnValues.get(i1);
+            ImportWstColumnValue a = this.columnValues.get(i2);
             if (b.getPosition().compareTo(a.getPosition()) < 0) {
-                ImportWstColumnValue t = a; a = b; b = t;
+                final ImportWstColumnValue t = a; a = b; b = t;
             }
 
             if (a.getW().compareTo(b.getW()) < 0) ++up;
@@ -180,37 +181,42 @@
     }
 
     /** Get corresponding mapped wst-column (from database). */
-    public WstColumn getPeer(River river) {
-        if (peer == null) {
-            Wst w = wst.getPeer(river);
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from WstColumn where" +
-                " wst=:wst and name=:name" +
-                " and source=:source" +
-                " and position=:position");
-            query.setParameter("wst",      w);
-            query.setParameter("name",     name);
-            query.setParameter("position", position);
-            query.setParameter("source",   source);
+    public WstColumn getPeer(final River river) {
+        if (this.peer == null) {
+            final Wst w = this.wst.getPeer(river);
+            List<WstColumn> columns;
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            if (this.wst.storeMode == StoreMode.INSERT)
+                columns = null;
+            else {
+                final Query query = session.createQuery(
+                        "from WstColumn where" +
+                                " wst=:wst and name=:name" +
+                                " and source=:source" +
+                        " and position=:position");
+                query.setParameter("wst",      w);
+                query.setParameter("name",     this.name);
+                query.setParameter("position", this.position);
+                query.setParameter("source",   this.source);
+                columns = query.list();
+            }
 
-            TimeInterval ti = timeInterval != null
-                ? timeInterval.getPeer()
-                : null;
+            final TimeInterval ti = (this.timeInterval != null) ? this.timeInterval.getPeer() : null;
 
-            List<WstColumn> columns = query.list();
-            if (columns.isEmpty()) {
-                log.debug("source: " + source);
-                peer = new WstColumn(
-                    w, name, description, source, position, ti);
-                session.save(peer);
+            if ((columns == null) || columns.isEmpty()) {
+                log.debug("source: " + this.source);
+                this.peer = new WstColumn(
+                        w, this.name, this.description, this.source, this.position, ti);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = columns.get(0);
+                this.peer = columns.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
-        return peer;
+        return this.peer;
     }
 
 }
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportWstColumnQRange.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportWstColumnQRange.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,71 +8,81 @@
 
 package org.dive4elements.river.importer;
 
+import java.util.List;
+
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.WstColumn;
 import org.dive4elements.river.model.WstColumnQRange;
 import org.dive4elements.river.model.WstQRange;
-import org.dive4elements.river.model.WstColumn;
-import org.dive4elements.river.model.River;
-
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import java.util.List;
 
 public class ImportWstColumnQRange
 {
     protected ImportWstColumn wstColumn;
     protected ImportWstQRange qRange;
 
+    protected StoreMode storeMode;
+
     protected WstColumnQRange peer;
 
     public ImportWstColumnQRange() {
     }
 
     public ImportWstColumnQRange(
-        ImportWstColumn wstColumn,
-        ImportWstQRange qRange
-    ) {
+            final ImportWstColumn wstColumn,
+            final ImportWstQRange qRange
+            ) {
         this.wstColumn = wstColumn;
         this.qRange    = qRange;
+        this.storeMode = StoreMode.NONE;
     }
 
     public ImportWstColumn getWstColumn() {
-        return wstColumn;
+        return this.wstColumn;
     }
 
-    public void setWstColumn(ImportWstColumn wstColumn) {
+    public void setWstColumn(final ImportWstColumn wstColumn) {
         this.wstColumn = wstColumn;
     }
 
     public ImportWstQRange getQRange() {
-        return qRange;
+        return this.qRange;
     }
 
-    public void setQRange(ImportWstQRange qRange) {
+    public void setQRange(final ImportWstQRange qRange) {
         this.qRange = qRange;
     }
 
-    public WstColumnQRange getPeer(River river) {
-        if (peer == null) {
-            WstColumn c = wstColumn.getPeer(river);
-            WstQRange q = qRange.getPeer(river);
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-            Query query = session.createQuery(
-                "from WstColumnQRange where " +
-                "wstColumn=:c and wstQRange=:q");
-            query.setParameter("c", c);
-            query.setParameter("q", q);
-            List<WstColumnQRange> cols = query.list();
-            if (cols.isEmpty()) {
-                peer = new WstColumnQRange(c, q);
-                session.save(peer);
+    public WstColumnQRange getPeer(final River river) {
+        if (this.peer == null) {
+            final WstColumn c = this.wstColumn.getPeer(river);
+            final WstQRange q = this.qRange.getPeer(river);
+            List<WstColumnQRange> cols;
+            final Session session = ImporterSession.getInstance()
+                    .getDatabaseSession();
+            if (this.wstColumn.storeMode == StoreMode.INSERT)
+                cols = null;
+            else {
+                final Query query = session.createQuery(
+                        "from WstColumnQRange where " +
+                        "wstColumn=:c and wstQRange=:q");
+                query.setParameter("c", c);
+                query.setParameter("q", q);
+                cols = query.list();
+            }
+            if ((cols == null) || cols.isEmpty()) {
+                this.peer = new WstColumnQRange(c, q);
+                session.save(this.peer);
+                this.storeMode = StoreMode.INSERT;
             }
             else {
-                peer = cols.get(0);
+                this.peer = cols.get(0);
+                this.storeMode = StoreMode.UPDATE;
             }
         }
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/Importer.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/Importer.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,33 +8,31 @@
 
 package org.dive4elements.river.importer;
 
-import org.dive4elements.artifacts.common.utils.XMLUtils;
-
-import org.dive4elements.river.importer.parsers.AnnotationClassifier;
-import org.dive4elements.river.importer.parsers.BundesWasserStrassenParser;
-import org.dive4elements.river.importer.parsers.InfoGewParser;
-
 import java.io.File;
 import java.io.IOException;
-
+import java.net.MalformedURLException;
+import java.sql.SQLException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import java.sql.SQLException;
-
 import org.apache.log4j.Logger;
-
+import org.apache.log4j.PropertyConfigurator;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.backend.utils.StringUtil;
+import org.dive4elements.river.importer.parsers.AnnotationClassifier;
+import org.dive4elements.river.importer.parsers.BundesWasserStrassenParser;
+import org.dive4elements.river.importer.parsers.InfoGewParser;
+import org.hibernate.HibernateException;
 import org.hibernate.Transaction;
-import org.hibernate.HibernateException;
-
+import org.slf4j.bridge.SLF4JBridgeHandler;
 import org.w3c.dom.Document;
 
-import org.dive4elements.river.backend.utils.StringUtil;
-
 /** Data Importer. Further processing happens per-river. */
 public class Importer
 {
+    static final String VERSION = "3.3.0";
+
     /** Private log. */
     private static final Logger log = Logger.getLogger(Importer.class);
 
@@ -45,15 +43,15 @@
     public Importer() {
     }
 
-    public Importer(List<ImportRiver> rivers) {
+    public Importer(final List<ImportRiver> rivers) {
         this.rivers = rivers;
     }
 
     public List<ImportRiver> getRivers() {
-        return rivers;
+        return this.rivers;
     }
 
-    public void setRivers(List<ImportRiver> rivers) {
+    public void setRivers(final List<ImportRiver> rivers) {
         this.rivers = rivers;
     }
 
@@ -61,7 +59,7 @@
     public void writeRivers() {
         log.debug("write rivers started");
 
-        for (ImportRiver river: rivers) {
+        for (final ImportRiver river: this.rivers) {
             log.debug("writing river '" + river.getName() + "'");
             river.storeDependencies();
             ImporterSession.getInstance().getDatabaseSession().flush();
@@ -75,16 +73,15 @@
         Transaction tx = null;
 
         try {
-            tx = ImporterSession.getInstance()
-                .getDatabaseSession().beginTransaction();
+            tx = ImporterSession.getInstance().getDatabaseSession().beginTransaction();
 
             try {
                 writeRivers();
             }
-            catch (HibernateException he) {
+            catch (final HibernateException he) {
                 Throwable t = he.getCause();
                 while (t instanceof SQLException) {
-                    SQLException sqle = (SQLException) t;
+                    final SQLException sqle = (SQLException) t;
                     log.error("SQL exeception chain:", sqle);
                     t = sqle.getNextException();
                 }
@@ -93,7 +90,7 @@
 
             tx.commit();
         }
-        catch (RuntimeException re) {
+        catch (final RuntimeException re) {
             if (tx != null) {
                 tx.rollback();
             }
@@ -102,14 +99,14 @@
     }
 
     public static AnnotationClassifier getAnnotationClassifier() {
-        String annotationTypes = Config.INSTANCE.getAnnotationTypes();
+        final String annotationTypes = Config.INSTANCE.getAnnotationTypes();
 
         if (annotationTypes == null) {
             log.info("no annotation types file configured.");
             return null;
         }
 
-        File file = new File(annotationTypes);
+        final File file = new File(annotationTypes);
 
         log.info("use annotation types file '" + file + "'");
 
@@ -118,7 +115,7 @@
             return null;
         }
 
-        Document rules = XMLUtils.parseDocument(file, false, null);
+        final Document rules = XMLUtils.parseDocument(file, false, null);
 
         if (rules == null) {
             log.warn("cannot parse annotation types file.");
@@ -130,77 +127,80 @@
 
 
     /** Starting point for importing river data. */
-    public static void main(String [] args) {
+    public static void main(final String [] args) {
 
-        InfoGewParser infoGewParser = new InfoGewParser(
-            getAnnotationClassifier());
+        configureLogging();
 
-        log.info("Start parsing rivers...");
+        log.info("IMPORTER version " + VERSION);
+        log.info("START parsing rivers...");
+
+        final InfoGewParser infoGewParser = new InfoGewParser(getAnnotationClassifier());
 
         File bwastrFile = null;
 
-        for (String gew: args) {
-            log.info("parsing info gew file: " + gew);
-            File gewFile = new File(gew);
+        // Main parsing loop for all river gew file paths in args
+        // FIXME: Multiple rivers lead to reparsing the already parsed rivers again in InfoGewParser.parse...
+        for (final String gew : args) {
+            log.info("Parsing info gew file: " + gew);
+            final File gewFile = new File(gew);
             if (bwastrFile == null) {
-                bwastrFile = new File(
-                    gewFile.getParentFile(), BWASTR_ID_CSV_FILE);
+                bwastrFile = new File(gewFile.getParentFile(), BWASTR_ID_CSV_FILE);
             }
             try {
                 infoGewParser.parse(gewFile);
             }
-            catch (IOException ioe) {
-                log.error("error while parsing gew: " + gew, ioe);
+            catch (final IOException ioe) {
+                log.error("error parsing gew: " + gew, ioe);
                 System.exit(1);
             }
         }
 
-        String gew = Config.INSTANCE.getInfoGewFile();
+        // Parse a single river gew file specified in the flys.backend.importer.infogew.file property
+        // (seems to be an alternative to the args way)
+        final String gew = Config.INSTANCE.getInfoGewFile();
         if (gew != null && gew.length() > 0) {
-            log.info("parsing info gew file: " + gew);
-            File gewFile = new File(gew);
+            log.info("Parsing info gew file: " + gew);
+            final File gewFile = new File(gew);
             if (bwastrFile == null) {
-                bwastrFile = new File(
-                    gewFile.getParentFile(), BWASTR_ID_CSV_FILE);
+                bwastrFile = new File(gewFile.getParentFile(), BWASTR_ID_CSV_FILE);
             }
             try {
                 infoGewParser.parse(gewFile);
             }
-            catch (IOException ioe) {
-                log.error("error while parsing gew: " + gew, ioe);
+            catch (final IOException ioe) {
+                log.error("error parsing gew: " + gew, ioe);
                 System.exit(1);
             }
         }
 
         // Look for official numbers.
-        BundesWasserStrassenParser bwastrIdParser =
-            new BundesWasserStrassenParser();
+        final BundesWasserStrassenParser bwastrIdParser = new BundesWasserStrassenParser();
 
         // Read bwastFile (river-dir + BWASTR_ID_CSV_FILE).
         if (!Config.INSTANCE.skipBWASTR()) {
             try{
                 bwastrIdParser.parse(bwastrFile);
-                HashMap<String,Long> map = bwastrIdParser.getMap();
+                final HashMap<String,Long> map = bwastrIdParser.getMap();
 
                 // Now link rivers with official numbers.
-                for(ImportRiver river: infoGewParser.getRivers()) {
-                    for(Map.Entry<String, Long> entry: map.entrySet()) {
-                        if (StringUtil.containsIgnoreCase(
-                                river.getName(), entry.getKey())) {
+                for(final ImportRiver river: infoGewParser.getRivers()) {
+                    for(final Map.Entry<String, Long> entry: map.entrySet()) {
+                        if (StringUtil.containsIgnoreCase(river.getName(), entry.getKey())) {
                             river.setOfficialNumber(entry.getValue());
-                            log.debug(river.getName()
-                                + " is mapped to bwastr " + entry.getValue());
+                            log.debug(river.getName() + " is mapped to bwastr " + entry.getValue());
                         }
                     }
                 }
-            } catch (IOException ioe) {
-                log.warn("BWASTR-file could not be loaded.");
+            }
+            catch (final IOException ioe) {
+                log.warn("BWASTR-file could not be loaded: " + ioe.getMessage());
             }
         }
         else {
-            log.debug("skip reading BWASTR_ID.csv");
+            log.debug("Skip reading BWASTR_ID.csv");
         }
 
+        // Write all parsed objects to the database
         if (!Config.INSTANCE.dryRun()) {
             new Importer(infoGewParser.getRivers()).writeToDatabase();
         }
@@ -208,5 +208,28 @@
             log.info("Dry run, not writing to database.");
         }
     }
+
+    /**
+     * Tries to load the Log4j configuration from the property 'log4j.configuration'.
+     */
+    private static final void configureLogging() {
+        final String configPath = System.getProperty("log4j.configuration");
+        try {
+            final File propFile = new File(configPath);
+            if (propFile.isFile() && propFile.canRead()) {
+                try {
+                    PropertyConfigurator.configure(propFile.toURI().toURL());
+                    SLF4JBridgeHandler.install();
+                }
+                catch (final MalformedURLException mue) {
+                    mue.printStackTrace(System.err);
+                }
+            }
+        }
+        catch (final Exception e) {
+            e.printStackTrace(System.err);
+        }
+    }
+
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/common/AbstractKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,89 @@
+/* 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.importer.common;
+
+import org.dive4elements.river.importer.ImporterSession;
+import org.hibernate.Session;
+
+/**
+ * Abstract base class of a river station with associated data importing from a file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public abstract class AbstractKmLineImport<SERIES, KMTUPLE> {
+
+    /***** FIELDS *****/
+
+    protected double station;
+
+    private KMTUPLE peer;
+
+    protected StoreMode storeMode;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public AbstractKmLineImport(final double km) {
+        this.station = km;
+        this.storeMode = StoreMode.NONE;
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Stores the station value record in the database
+     */
+    public StoreMode store(final SERIES parent, final StoreMode parentStoreMode) {
+        getPeer(parent, parentStoreMode);
+        return this.storeMode;
+    }
+
+    public double getStation() {
+        return this.station;
+    }
+
+    /**
+     * Gets the station value record from the database if existing, or creates a database record from this object and adds
+     * it
+     */
+    protected KMTUPLE getPeer(final SERIES parent, final StoreMode parentStoreMode) {
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        KMTUPLE value = null;
+        if (parentStoreMode != StoreMode.INSERT) {
+            value = queryValueItem(session, parent);
+        }
+        if (value == null) {
+            this.peer = createValueItem(parent);
+            session.save(this.peer);
+            this.storeMode = StoreMode.INSERT;
+        } else {
+            this.peer = value;
+            this.storeMode = StoreMode.UPDATE;
+        }
+        return this.peer;
+    }
+
+    /**
+     * Queries the (first matching) value item from the database
+     *
+     * @return first matching database value item, or null
+     */
+    protected abstract KMTUPLE queryValueItem(final Session session, final SERIES parent);
+
+    /**
+     * Creates a new value item
+     */
+    protected abstract KMTUPLE createValueItem(final SERIES parent);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/common/AbstractParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,457 @@
+/* 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.importer.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.backend.utils.EpsilonComparator;
+import org.dive4elements.river.importer.ImportRiver;
+
+/**
+ * Abstract base class for a parser of one FLYS csv data file.<br />
+ * The {@link parse} method creates a SERIES object for the meta data
+ * and a list of KMLINE objects for the km value lines read from the file.<br />
+ * The {@link store} method gets or creates the corresponding database objects
+ * by the hibernate binding classes DB_SERIES and DB_KMTUPLE,
+ * and updates or inserts them in the database.
+ * DB_SERIES has a one-to-many relationship with DB_KMTUPLE.<br />
+ * <br />
+ * The structure of the file is as follows:<br />
+ * <ul>
+ * <li>one or more comment lines (#) with the meta info of the data series</li>
+ * <li>the comment line with the column titles of values table, starting with the km column</li>
+ * <li>the rows of the values table, each one on its own line</li>
+ * </ul>
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public abstract class AbstractParser<DB_SERIES, DB_KMTUPLE, KMLINE extends AbstractKmLineImport<DB_SERIES, DB_KMTUPLE>, HEADER extends AbstractSeriesImport<DB_SERIES, DB_KMTUPLE, KMLINE>> implements ImportParser {
+
+    /***** FIELDS *****/
+
+    public static final String ENCODING = "ISO-8859-1";
+
+    protected static final Locale DEFAULT_LOCALE = Locale.GERMAN;
+
+    public static final String START_META_CHAR = "#";
+
+    protected static final String SEPARATOR_CHAR = ";";
+
+    protected static final Pattern META_RIVERNAME = Pattern.compile("^#\\s*((Gew.sser)|(Gewaesser)):\\s*(\\S[^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    protected static final Pattern META_KMRANGE_INFO = Pattern.compile("^#\\s*Strecke:\\s*(\\S[^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    protected static final Pattern META_COMMENTS = Pattern.compile("^#\\s*weitere Bemerkungen:\\s*(\\S[^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_COLUMNTITLES = Pattern.compile("^#*\\s*Fluss.km\\s*;.+", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_SUBGROUP = Pattern.compile("^##.*", Pattern.CASE_INSENSITIVE);
+
+    private static NumberFormat numberFormat = NumberFormat.getInstance(Locale.ROOT);
+
+    private static DecimalFormat bigDecimalFormat;
+
+    static {
+        bigDecimalFormat = (DecimalFormat) NumberFormat.getInstance(Locale.ROOT);
+        bigDecimalFormat.setParseBigDecimal(true);
+    }
+
+    /**
+     * How the km column and its content are expected
+     */
+    protected enum KmMode {
+        NONE, UNIQUE, DUPLICATES
+    }
+
+    /**
+     * Path of the file or directory to import from
+     */
+    protected final File importPath;
+
+    /**
+     * Part of {@link importPath} without the river root dir
+     */
+    protected final File rootRelativePath;
+
+    /**
+     * River for which the import runs
+     */
+    protected final ImportRiver river;
+
+    /**
+     * Reader during parse
+     */
+    protected LineNumberReader in;
+
+    /**
+     * Last line read from in
+     */
+    protected String currentLine;
+
+    /**
+     * State of the header lines parse loop
+     */
+    protected ParsingState headerParsingState;
+
+    /**
+     * Series header of the stations table, with the imported meta info.
+     */
+    protected HEADER seriesHeader;
+
+    /**
+     * List of meta info Pattern matched during {@link handleMetaLine}
+     */
+    protected final List<Pattern> metaPatternsMatched;
+
+    /**
+     * Column titles of the stations table, starting with the km column.
+     * All strings have been trimmed.
+     */
+    protected final List<String> columnTitles;
+
+    /**
+     * List of the km value tuples imported, no duplicate km
+     */
+    protected final List<KMLINE> values;
+
+    /**
+     * Ordered list with the imported km to check for duplicates.
+     */
+    protected final TreeSet<Double> kmExists;
+
+
+    /***** CONSTRUCTORS *****/
+
+    /**
+     * Constructs a parser for an import file
+     */
+    public AbstractParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        this.importPath = importPath;
+        this.rootRelativePath = rootRelativePath;
+        this.river = river;
+        this.metaPatternsMatched = new ArrayList<>();
+        this.kmExists = new TreeSet<>(EpsilonComparator.CMP);
+        this.columnTitles = new ArrayList<>();
+        this.values = new ArrayList<>();
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Lists all files from a directory having a type extension (starting with dot)
+     */
+    protected static List<File> listFiles(final File importDir, final String extension) {
+        final File[] files = importDir.listFiles(new FilenameFilter() {
+            @Override
+            public boolean accept(final File dir, final String name) {
+                return name.toLowerCase().endsWith(extension);
+            }
+        });
+        final List<File> fl = new ArrayList<>();
+        if (files != null)
+            for (final File file : files)
+                fl.add(file);
+        return fl;
+    }
+
+    /**
+     * Parses a file and adds series and values to the parser's collection
+     */
+    @Override
+    public void parse() throws IOException {
+        logStartInfo();
+        this.seriesHeader = createSeriesImport(this.importPath.getName().replaceAll("\\.csv", ""));
+        this.metaPatternsMatched.clear();
+        this.kmExists.clear();
+        this.headerParsingState = ParsingState.CONTINUE;
+        try {
+            try {
+                this.in = new LineNumberReader(new InputStreamReader(new FileInputStream(this.importPath), ENCODING));
+            }
+            catch (final Exception e) {
+                logError("Could not open (" + e.getMessage() + ")");
+                this.headerParsingState = ParsingState.STOP;
+            }
+            this.currentLine = null;
+            while (this.headerParsingState != ParsingState.STOP) {
+                this.currentLine = this.in.readLine();
+                if (this.currentLine == null)
+                    break;
+                this.currentLine = this.currentLine.trim();
+                if (this.currentLine.isEmpty())
+                    continue;
+                if (this.headerParsingState == ParsingState.CONTINUE)
+                    handleMetaLine();
+                else
+                    handleDataLine();
+            }
+            if (this.headerParsingState != ParsingState.STOP)
+                getLog().info("Number of values found: " + this.seriesHeader.getValueCount());
+        }
+        finally {
+            if (this.in != null) {
+                this.in.close();
+                this.in = null;
+            }
+        }
+        if (this.headerParsingState == ParsingState.STOP)
+            logError("Parsing of the file stopped due to a severe error");
+    }
+
+    /**
+     * Writes the parse start info to the log
+     */
+    protected void logStartInfo() {
+        getLog().info("Start parsing:;'" + this.rootRelativePath + "'");
+    }
+
+    /**
+     * Stores the parsed series and values in the database
+     */
+    @Override
+    public void store() {
+        if (this.headerParsingState != ParsingState.STOP) {
+            this.seriesHeader.store(this.river.getPeer());
+            final String counts = String.format("parse=%d, insert=%d, update/ignore=%d", this.seriesHeader.getValueCount(),
+                    this.seriesHeader.getValueStoreCount(StoreMode.INSERT), this.seriesHeader.getValueStoreCount(StoreMode.UPDATE));
+            if (this.seriesHeader.getValueCount() > this.seriesHeader.getValueStoreCount(StoreMode.INSERT))
+                logWarning("Number of value inserts less than number parsed: " + counts);
+            else
+                getLog().info("Number of values records: " + counts);
+        }
+        else
+            logWarning("Severe parsing errors, not storing series '" + this.seriesHeader.getFilename() + "'");
+    }
+
+    /**
+     * Strips separator chars from a meta info text, and trims leading and trailing whitespace
+     */
+    public static String parseMetaInfo(final String text) {
+        return text.replace(SEPARATOR_CHAR, "").trim();
+    }
+
+    /**
+     * Parses a number string with dot or comma as decimal char, and returning null in case of an error
+     */
+    public static Number parseDoubleWithNull(final String text) {
+        try {
+            return parseDouble(text);
+        }
+        catch (final Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * Parses a number string with dot or comma as decimal char
+     *
+     * @throws ParseException
+     */
+    public static Number parseDouble(final String text) throws ParseException {
+        return numberFormat.parse(text.replace(',', '.'));
+    }
+
+    /**
+     * Parses a number string as a BigDecimal, replacing a comma with a dot first
+     */
+    public static BigDecimal parseDecimal(final String text) throws ParseException {
+        return (BigDecimal) bigDecimalFormat.parse(text.replace(',', '.'));
+    }
+
+    /**
+     * Gets the class's logger
+     */
+    protected abstract Logger getLog();
+
+    /**
+     * Logs an error message, appending the relative file path
+     */
+    protected void logError(final String message) {
+        getLog().error(message + ";" + this.rootRelativePath);
+    }
+
+    /**
+     * Logs a warning message, appending the relative file path
+     */
+    protected void logWarning(final String message) {
+        getLog().warn(message + ";" + this.rootRelativePath);
+    }
+
+    /**
+     * Logs an info message, appending the relative file path
+     */
+    protected void logInfo(final String message) {
+        getLog().info(message + ";" + this.rootRelativePath);
+    }
+
+    /**
+     * Logs a debug message, appending the relative file path
+     */
+    protected void logDebug(final String message) {
+        getLog().debug(message + ";" + this.rootRelativePath);
+    }
+
+    /**
+     * Logs a trace message, appending the relative file path
+     */
+    protected void logTrace(final String message) {
+        getLog().trace(message + ";" + this.rootRelativePath);
+    }
+
+    /**
+     * Creates a new series import object
+     */
+    protected abstract HEADER createSeriesImport(final String filename);
+
+    protected void handleMetaLine() {
+        if (META_SUBGROUP.matcher(this.currentLine).matches())
+            return;
+        else if (handleMetaRivername())
+            return;
+        else if (handleMetaKmrange_info())
+            return;
+        else if (handleMetaComment())
+            return;
+        else if (handleMetaOther())
+            return;
+        else if (handleMetaColumnTitles()) {
+            if (this.headerParsingState != ParsingState.STOP)
+                this.headerParsingState = ParsingState.DONE;
+            return;
+        }
+        else {
+            if (this.currentLine.startsWith(START_META_CHAR)) {
+                if (this.headerParsingState != ParsingState.IGNORE)
+                    logWarning("Not matching any known meta type in line " + this.in.getLineNumber() + ", ignored");
+                else
+                    this.headerParsingState = ParsingState.CONTINUE;
+            }
+        }
+    }
+
+    private boolean handleMetaRivername() {
+        if (META_RIVERNAME.matcher(this.currentLine).matches()) {
+            this.metaPatternsMatched.add(META_RIVERNAME);
+            return true;
+        }
+        else
+            return false;
+    }
+
+    private boolean handleMetaKmrange_info() {
+        final Matcher m = META_KMRANGE_INFO.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_KMRANGE_INFO);
+            this.seriesHeader.setKmrange_info(parseMetaInfo(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaComment() {
+        final Matcher m = META_COMMENTS.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_COMMENTS);
+            this.seriesHeader.setNotes(parseMetaInfo(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Parses currentLine for non-default meta info
+     *
+     * @return Whether the line has been handled
+     */
+    protected boolean handleMetaOther() {
+        return false;
+    }
+
+    /**
+     * Parses a header line for the km table column header line
+     *
+     * @return Whether the line has been handled and we are ready for reading the km values lines
+     */
+    protected boolean handleMetaColumnTitles() {
+        if (META_COLUMNTITLES.matcher(this.currentLine).matches()) {
+            this.metaPatternsMatched.add(META_COLUMNTITLES);
+            this.columnTitles.clear();
+            final String[] titles = this.currentLine.split(SEPARATOR_CHAR, 0);
+            for (int i = 0; i <= titles.length - 1; i++)
+                this.columnTitles.add(titles[i].trim());
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Parses a values line and adds the values record
+     */
+    protected void handleDataLine() {
+        final String[] values = this.currentLine.split(SEPARATOR_CHAR, 0);
+        // Skip import line without data or only km
+        if (values.length < 2)
+            return;
+        Double km = Double.NaN;
+        if (kmMode() != KmMode.NONE) {
+            try {
+                km = Double.valueOf(parseDouble(values[0]).doubleValue());
+                if (kmMode() == KmMode.UNIQUE) {
+                    if (this.kmExists.contains(km)) {
+                        logWarning("Ignoring duplicate station '" + values[0] + "' in line " + this.in.getLineNumber());
+                        return;
+                    }
+                    this.kmExists.add(km);
+                }
+            }
+            catch (final Exception e) {
+                logError("Not parseable km in line " + this.in.getLineNumber() + ": " + e.getMessage());
+                return;
+            }
+        }
+        final KMLINE value = createKmLineImport(km, values);
+        if (value != null)
+            this.seriesHeader.addValue(value);
+    }
+
+    /**
+     * How {@link handleDataLine} shall handle the km column (if any)
+     */
+    protected KmMode kmMode() {
+        return KmMode.UNIQUE;
+    }
+
+    /**
+     * Creates a value import item with the km and other fields of the current line;
+     * the km has been validated
+     *
+     * @return value item, or null if parse error
+     */
+    protected abstract KMLINE createKmLineImport(final Double km, final String[] values);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/common/AbstractSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,169 @@
+/* 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.importer.common;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImporterSession;
+import org.dive4elements.river.model.River;
+import org.hibernate.Session;
+
+/**
+ * Abstract base class of a km bound data series of a river importing from a file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public abstract class AbstractSeriesImport<SERIES, KMTUPLE, KMLINE extends AbstractKmLineImport<SERIES, KMTUPLE>>
+{
+    /***** FIELDS *****/
+
+    /**
+     * Name of the imported file without type extension
+     */
+    protected String filename;
+
+    protected String kmrange_info;
+
+    protected String notes;
+
+    protected final List<KMLINE> values;
+
+    protected SERIES peer;
+
+    protected Map<StoreMode, Integer> valueStoreCount;
+
+    protected StoreMode storeMode;
+
+
+    /***** CONSTRUCTORS *****/
+
+    AbstractSeriesImport() {
+        this.values = new ArrayList<>();
+        this.valueStoreCount = new EnumMap<>(StoreMode.class);
+        for (final StoreMode mode : StoreMode.values())
+            this.valueStoreCount.put(mode, Integer.valueOf(0));
+        this.storeMode = StoreMode.NONE;
+    }
+
+    public AbstractSeriesImport(final String filename) {
+        this();
+        setFilename(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Gets the class's logger
+     */
+    public abstract Logger getLog();
+
+    void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    public int getValueCount() {
+        return this.values.size();
+    }
+
+    public void addValue(final KMLINE value) {
+        this.values.add(value);
+    }
+
+    public int getValueStoreCount(final StoreMode mode) {
+        return this.valueStoreCount.get(mode).intValue();
+    }
+
+    /**
+     * Stores the data series and their values in the database
+     *
+     * @param river
+     */
+    public StoreMode store(final River river) {
+        logStoreInfo();
+        for (final StoreMode mode : StoreMode.values())
+            this.valueStoreCount.put(mode, Integer.valueOf(0));
+        final SERIES peer = getPeer(river);
+        if (peer != null) {
+            for (final KMLINE value : this.values) {
+                incrementValueStoreCount(value.store(peer, this.storeMode));
+            }
+        }
+        ImporterSession.getInstance().getDatabaseSession().flush();
+        return this.storeMode;
+    }
+
+    /**
+     * Writes the store start info to the log
+     */
+    protected void logStoreInfo() {
+        getLog().info("Store series '" + getFilename() + "'");
+    }
+
+    private void incrementValueStoreCount(final StoreMode mode) {
+        this.valueStoreCount.put(mode, Integer.valueOf(this.valueStoreCount.get(mode).intValue() + 1));
+    }
+
+    /**
+     * Gets the model object of the data series, inserting it into the database if not already existing
+     */
+    protected SERIES getPeer(final River river) {
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final List<SERIES> rows = querySeriesItem(session, river);
+        if (rows.isEmpty()) {
+            getLog().info("Create new database instance");
+            this.peer = createSeriesItem(river);
+            session.save(this.peer);
+            this.storeMode = StoreMode.INSERT;
+        } else {
+            this.peer = rows.get(0);
+            this.storeMode = StoreMode.UPDATE;
+        }
+        return this.peer;
+    }
+
+    /**
+     * Queries the series item(s) from the database
+     */
+    public abstract List<SERIES> querySeriesItem(final Session session, final River river);
+
+    /**
+     * Creates a new value item
+     */
+    public abstract SERIES createSeriesItem(final River river);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/common/ImportParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,33 @@
+/* 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.importer.common;
+
+import java.io.IOException;
+
+/**
+ * Parser interface
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public interface ImportParser {
+
+    /**
+     * Parses a file and adds the parsed objects to the parsers state
+     */
+    void parse() throws IOException;
+
+    /**
+     * Stores the parsed objects in the database with reference to a river
+     */
+    void store();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/common/ParsingState.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,23 @@
+/* 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.importer.common;
+
+/**
+ * Return of a parser's line handling method
+ *
+ * @author Matthias Schäfer
+ */
+public enum ParsingState {
+    CONTINUE, // no match, continue with other handlers
+    IGNORE, // match, content ignored
+    DONE, // match, content handled
+    STOP // severe error, stop the parsing loop
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/common/StoreMode.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.importer.common;
+
+/**
+ * The way a database record has been stored
+ * 
+ * @author Matthias Schäfer
+ */
+public enum StoreMode {
+    NONE, INSERT, UPDATE
+}
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,45 +9,41 @@
 package org.dive4elements.river.importer.parsers;
 
 import java.io.File;
-
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
 import java.math.BigDecimal;
-
 import java.text.NumberFormat;
 import java.text.ParseException;
-
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.EnumMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.TreeSet;
-import java.util.Locale;
-
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import java.io.IOException;
-import java.io.LineNumberReader;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.backend.utils.EpsilonComparator;
 import org.dive4elements.river.importer.ImportBedHeight;
+import org.dive4elements.river.importer.ImportBedHeightType;
 import org.dive4elements.river.importer.ImportBedHeightValue;
-import org.dive4elements.river.importer.ImportBedHeightType;
 import org.dive4elements.river.importer.ImportElevationModel;
 import org.dive4elements.river.importer.ImportLocationSystem;
 import org.dive4elements.river.importer.ImportRange;
 import org.dive4elements.river.importer.ImportTimeInterval;
 import org.dive4elements.river.importer.ImportUnit;
-import org.dive4elements.river.model.BedHeightType;
 import org.dive4elements.river.importer.ImporterSession;
-import org.dive4elements.river.backend.utils.EpsilonComparator;
-import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.model.BedHeightType;
 
 public class BedHeightParser {
 
     private static final Logger log =
-        Logger.getLogger(BedHeightParser.class);
+            Logger.getLogger(BedHeightParser.class);
 
     public static final String ENCODING = "ISO-8859-1";
 
@@ -57,41 +53,79 @@
     public static final String SEPERATOR_CHAR  = ";";
 
     public static final Pattern META_YEAR =
-        Pattern.compile("^Jahr: [^0-9]*(\\d*).*");
+            Pattern.compile("^Jahr: [^0-9]*(\\d*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_TIMEINTERVAL =
-        Pattern.compile("^Zeitraum: Epoche (\\d*)-(\\d*).*");
+            Pattern.compile("^Zeitraum: Epoche (\\d*)-(\\d*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_TYPE =
-        Pattern.compile("^Aufnahmeart: (.*).*");
+            Pattern.compile("^Aufnahmeart: (.*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_LOCATION_SYSTEM =
-        Pattern.compile("^Lagesystem: (.*).*");
+            Pattern.compile("^Lagesystem: (.*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_CUR_ELEVATION_SYSTEM =
-        Pattern.compile("^H.hensystem:\\s(.*)?? \\[(.*)\\].*");
+            Pattern.compile("^H.hensystem:\\s(.*)?? \\[(.*)\\].*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_OLD_ELEVATION_SYSTEM =
-        Pattern.compile("^urspr.ngliches H.hensystem:\\s(.*)?? \\[(.*)\\].*");
+            Pattern.compile("^urspr.ngliches H.hensystem:\\s(.*)?? \\[(.*)\\].*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_RANGE =
-        Pattern.compile("^Strecke:\\D*(\\d++.?\\d*) ?- ?(\\d++.?\\d*).*");
+            Pattern.compile("^Strecke:\\D*(\\d++.?\\d*) ?- ?(\\d++.?\\d*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_EVALUATION_BY =
-        Pattern.compile("^Auswerter: (.*).*");
+            Pattern.compile("^Auswerter: (.*).*", Pattern.CASE_INSENSITIVE);
+
+    public static final Pattern META_SOUNDING_WIDTH = Pattern.compile("^ausgewertete Peilbreite:\\s*(\\S.*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_COMMENTS =
-        Pattern.compile("^Weitere Bemerkungen: (.*).*");
+            Pattern.compile("^Weitere Bemerkungen: (.*).*", Pattern.CASE_INSENSITIVE);
 
+    private static final Pattern META_COLUMNTITLES = Pattern.compile("^Fluss-km\\s*;.+", Pattern.CASE_INSENSITIVE);
 
-    protected static NumberFormat nf = NumberFormat.getInstance(
-        DEFAULT_LOCALE);
+    private enum ColTitlePattern {
+        KM("Fluss-km.*"), //
+        HEIGHT("mittlere Sohlh.he\\s*\\[(.*)\\].*"), //
+        UNCERTAINTY("Unsicherheit\\s*\\[(.*)\\].*"), //
+        GAP("Datenl.cke.*"), //
+        WIDTH("Peilbreite\\s*\\[(.*)\\].*"), //
+        MINHEIGHT("Minimale Sohlh.he\\s*\\[(.*)\\].*"), //
+        MAXHEIGHT("Maximale Sohlh.he\\s*\\[(.*)\\].*"), //
+        HEIGHT01("Feld\\s*1\\s*\\[(.*)\\].*"), //
+        HEIGHT02("Feld\\s*2\\s*\\[(.*)\\].*"), //
+        HEIGHT03("Feld\\s*3\\s*\\[(.*)\\].*"), //
+        HEIGHT04("Feld\\s*4\\s*\\[(.*)\\].*"), //
+        HEIGHT05("Feld\\s*5\\s*\\[(.*)\\].*"), //
+        HEIGHT06("Feld\\s*6\\s*\\[(.*)\\].*"), //
+        HEIGHT07("Feld\\s*7\\s*\\[(.*)\\].*"), //
+        HEIGHT08("Feld\\s*8\\s*\\[(.*)\\].*"), //
+        HEIGHT09("Feld\\s*9\\s*\\[(.*)\\].*"), //
+        HEIGHT10("Feld\\s*10\\s*\\[(.*)\\].*");
+
+        private final Pattern pattern;
+
+        private ColTitlePattern(final String regexp) {
+            this.pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
+        }
+
+        public Pattern getPattern() {
+            return this.pattern;
+        }
+
+        public static ColTitlePattern getSectionPattern(final int index) {
+            return ColTitlePattern.valueOf(String.format("HEIGHT%02d", index));
+        }
+    }
+
+    private final EnumMap<ColTitlePattern, Integer> cols = new EnumMap<>(ColTitlePattern.class);
+
+    protected static NumberFormat nf = NumberFormat.getInstance(DEFAULT_LOCALE);
 
 
     protected List<ImportBedHeight> bedHeights;
 
 
-    protected ImportBedHeight newImportBedHeight(String description) {
+    protected ImportBedHeight newImportBedHeight(final String description) {
         return new ImportBedHeight(description);
     }
 
@@ -99,30 +133,26 @@
     protected TreeSet<Double> kmExists;
 
     public BedHeightParser() {
-        bedHeights = new ArrayList<ImportBedHeight>();
-        kmExists = new TreeSet<Double>(EpsilonComparator.CMP);
+        this.bedHeights = new ArrayList<>();
+        this.kmExists = new TreeSet<>(EpsilonComparator.CMP);
     }
 
 
     public List<ImportBedHeight> getBedHeights() {
-        return bedHeights;
+        return this.bedHeights;
     }
 
 
-    public void parse(File file) throws IOException {
+    public void parse(final File file) throws IOException {
         log.info("Parsing bed height single file '" + file + "'");
-
-        ImportBedHeight obj = newImportBedHeight(
-            file.getName().replaceAll("\\.csv", ""));
-
-        kmExists.clear();
-
+        final ImportBedHeight obj = newImportBedHeight(file.getName().replaceAll("\\.csv", ""));
+        this.kmExists.clear();
+        this.cols.clear();
+        for (final ColTitlePattern col : ColTitlePattern.values())
+            this.cols.put(col, -1);
         LineNumberReader in = null;
         try {
-            in =
-                new LineNumberReader(
-                new InputStreamReader(
-                new FileInputStream(file), ENCODING));
+            in = new LineNumberReader(new InputStreamReader(new FileInputStream(file), ENCODING));
 
             String line = null;
             while ((line = in.readLine()) != null) {
@@ -139,7 +169,7 @@
             }
 
             log.info("File contained " + obj.getValueCount() + " values.");
-            bedHeights.add(obj);
+            this.bedHeights.add(obj);
         }
         finally {
             if (in != null) {
@@ -149,8 +179,8 @@
     }
 
 
-    protected static String stripMetaLine(String line) {
-        String tmp = line.substring(1, line.length());
+    protected static String stripMetaLine(final String line) {
+        final String tmp = line.substring(1, line.length());
 
         if (tmp.startsWith(" ")) {
             return tmp.substring(1, tmp.length());
@@ -161,8 +191,8 @@
     }
 
 
-    protected void handleMetaLine(ImportBedHeight obj, String line) {
-        String meta = stripMetaLine(line);
+    protected void handleMetaLine(final ImportBedHeight obj, final String line) {
+        final String meta = stripMetaLine(line);
 
         if (handleMetaYear(obj, meta)) {
             return;
@@ -191,17 +221,22 @@
         else if (handleMetaOldElevationModel(obj, meta)) {
             return;
         }
+        else if (handleMetaSoundingWidth(obj, meta)) {
+            return;
+        }
+        else if (handleMetaColumnTitles(obj, meta)) {
+            return;
+        }
         else {
             log.warn("BHP: Meta line did not match any known type: " + line);
         }
     }
 
 
-    protected boolean handleMetaYear(ImportBedHeight obj, String line) {
-        Matcher m = META_YEAR.matcher(line);
-
+    protected boolean handleMetaYear(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_YEAR.matcher(line);
         if (m.matches()) {
-            String tmp = m.group(1);
+            final String tmp = m.group(1).trim();
             if (tmp.length() > 0) {
                 obj.setYear(Integer.parseInt(tmp));
             }
@@ -210,232 +245,192 @@
             }
             return true;
         }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaTimeInterval(
-        ImportBedHeight obj,
-        String line
-    ) {
-        Matcher m = META_TIMEINTERVAL.matcher(line);
-
-        if (m.matches()) {
-            String lo = m.group(1);
-            String up = m.group(2);
-
-            log.debug("Found time interval: " + lo + " - " + up);
-
-            try {
-                int lower = Integer.valueOf(lo);
-                int upper = Integer.valueOf(up);
-
-                Date fromYear = DateUtil.getStartDateFromYear(lower);
-                Date toYear   = DateUtil.getEndDateFromYear(upper);
-
-                obj.setTimeInterval(new ImportTimeInterval(fromYear, toYear));
-            }
-            catch (NumberFormatException e) {
-                log.warn("BHP: could not parse timeinterval", e);
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaComment(ImportBedHeight obj, String line) {
-        Matcher m = META_COMMENTS.matcher(line);
-
-        if (m.matches()) {
-            String tmp = m.group(1);
-
-            obj.setDescription(tmp);
-
-            return true;
-        }
-
         return false;
     }
 
 
-    protected boolean handleMetaEvaluationBy(
-        ImportBedHeight obj,
-        String                line
-    ) {
-        Matcher m = META_EVALUATION_BY.matcher(line);
-
+    protected boolean handleMetaTimeInterval(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_TIMEINTERVAL.matcher(line);
         if (m.matches()) {
-            String tmp = m.group(1);
-            tmp = tmp.replace(";", "");
-
-            obj.setEvaluationBy(tmp);
-
+            final String lo = m.group(1).trim();
+            final String up = m.group(2).trim();
+            log.debug("Found time interval: " + lo + " - " + up);
+            try {
+                final int lower = Integer.valueOf(lo);
+                final int upper = Integer.valueOf(up);
+                final Date fromYear = DateUtil.getStartDateFromYear(lower);
+                final Date toYear   = DateUtil.getEndDateFromYear(upper);
+                obj.setTimeInterval(new ImportTimeInterval(fromYear, toYear));
+            }
+            catch (final NumberFormatException e) {
+                log.warn("BHP: could not parse timeinterval", e);
+            }
             return true;
         }
-
         return false;
     }
 
 
-    protected boolean handleMetaRange(ImportBedHeight obj, String line) {
-        Matcher m = META_RANGE.matcher(line);
-
-        if (m.matches() && m.groupCount() >= 2) {
-            String a = m.group(1).replace(";", "");
-            String b = m.group(2).replace(";", "");
-
-            try {
-                BigDecimal lower = new BigDecimal(nf.parse(a).doubleValue());
-                BigDecimal upper = new BigDecimal(nf.parse(b).doubleValue());
-
-                obj.setRange(new ImportRange(lower, upper));
-
-                return true;
-            }
-            catch (ParseException e) {
-                log.warn("BHP: could not parse range", e);
-            }
+    protected boolean handleMetaComment(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_COMMENTS.matcher(line);
+        if (m.matches()) {
+            final String tmp = m.group(1).replace(SEPERATOR_CHAR, "").trim();
+            obj.setNotes(tmp);
+            return true;
         }
-
         return false;
     }
 
 
-    protected boolean handleMetaType(ImportBedHeight obj, String line) {
-        Matcher m = META_TYPE.matcher(line);
-
+    protected boolean handleMetaEvaluationBy(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_EVALUATION_BY.matcher(line);
         if (m.matches()) {
-            String tmp = m.group(1).replace(";", "").trim();
+            final String tmp = m.group(1).replace(";", "").trim();
+            obj.setEvaluationBy(tmp);
+            return true;
+        }
+        return false;
+    }
 
-            BedHeightType bht = BedHeightType.fetchBedHeightTypeForType(
-                tmp,
-                ImporterSession.getInstance().getDatabaseSession());
 
+    protected boolean handleMetaRange(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_RANGE.matcher(line);
+        if (m.matches() && m.groupCount() >= 2) {
+            final String a = m.group(1).replace(";", "").trim();
+            final String b = m.group(2).replace(";", "").trim();
+            try {
+                final BigDecimal lower = AbstractParser.parseDecimal(a);
+                final BigDecimal upper = AbstractParser.parseDecimal(b);
+                obj.setRange(new ImportRange(lower, upper));
+                return true;
+            }
+            catch (final Exception e) {
+                log.warn("BHP: could not parse range", e);
+            }
+        }
+        return false;
+    }
+
+
+    protected boolean handleMetaType(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_TYPE.matcher(line);
+        if (m.matches()) {
+            final String tmp = m.group(1).replace(";", "").trim();
+            final BedHeightType bht = BedHeightType.fetchBedHeightTypeForType(tmp, ImporterSession.getInstance().getDatabaseSession());
             if (bht != null) {
                 obj.setType(new ImportBedHeightType(bht));
                 return true;
             }
-
             log.error("Unknown bed height type: '" + tmp + "'. File ignored.");
         }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaLocationSystem(
-        ImportBedHeight obj,
-        String          line
-    ) {
-        Matcher m = META_LOCATION_SYSTEM.matcher(line);
-
-        if (m.matches()) {
-            String tmp = m.group(1).replace(";", "");
-
-            obj.setLocationSystem(new ImportLocationSystem(tmp, tmp));
-
-            return true;
-        }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaCurElevationModel(
-        ImportBedHeight obj,
-        String          line
-    ) {
-        Matcher m = META_CUR_ELEVATION_SYSTEM.matcher(line);
-
-        if (m.matches()) {
-            String name = m.group(1);
-            String unit = m.group(2);
-
-            obj.setCurElevationModel(new ImportElevationModel(
-                name,
-                new ImportUnit(unit)
-            ));
-
-            return true;
-        }
-
         return false;
     }
 
 
-    protected boolean handleMetaOldElevationModel(
-        ImportBedHeight obj,
-        String          line
-    ) {
-        Matcher m = META_OLD_ELEVATION_SYSTEM.matcher(line);
-
+    protected boolean handleMetaLocationSystem(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_LOCATION_SYSTEM.matcher(line);
         if (m.matches()) {
-            String name = m.group(1);
-            String unit = m.group(2);
-
-            obj.setOldElevationModel(new ImportElevationModel(
-                name,
-                new ImportUnit(unit)
-            ));
-
+            final String tmp = m.group(1).replace(";", "").trim();
+            obj.setLocationSystem(new ImportLocationSystem(tmp, tmp));
             return true;
         }
-
         return false;
     }
 
-    private Double parse(String []values, int idx, String msg)  {
 
-        if (idx >= 0 && idx < values.length && !values[idx].isEmpty()) {
-            try {
-                return nf.parse(values[idx]).doubleValue();
-            }
-            catch (ParseException e) {
-                log.warn("BSP: unparseable " + msg + " '" + values[idx] + "'");
-            }
+    protected boolean handleMetaCurElevationModel(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_CUR_ELEVATION_SYSTEM.matcher(line);
+        if (m.matches()) {
+            final String name = m.group(1).trim();
+            final String unit = m.group(2).trim();
+            obj.setCurElevationModel(new ImportElevationModel(name, new ImportUnit(unit)));
+            return true;
         }
-
-        return null;
+        return false;
     }
 
-    protected void handleDataLine(ImportBedHeight obj, String line) {
-        String[] values = line.split(SEPERATOR_CHAR, 0);
 
+    protected boolean handleMetaOldElevationModel(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_OLD_ELEVATION_SYSTEM.matcher(line);
+        if (m.matches()) {
+            final String name = m.group(1).trim();
+            final String unit = m.group(2).trim();
+            obj.setOldElevationModel(new ImportElevationModel(name, new ImportUnit(unit)));
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean handleMetaSoundingWidth(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_SOUNDING_WIDTH.matcher(line);
+        if (m.matches()) {
+            final String tmp = m.group(1).replace(SEPERATOR_CHAR, "").trim();
+            obj.setSoundingWidthInfo(tmp);
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * Tries to parse a line as column titles line
+     */
+    protected boolean handleMetaColumnTitles(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_COLUMNTITLES.matcher(line);
+        if (m.matches()) {
+            final Matcher cm;
+            final String[] titles = line.split(SEPERATOR_CHAR, 0);
+            for (int i = 0; i <= titles.length - 1; i++) {
+                for (final ColTitlePattern col : ColTitlePattern.values()) {
+                    if (col.getPattern().matcher(titles[i]).matches()) {
+                        this.cols.put(col, i);
+                        break;
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    protected void handleDataLine(final ImportBedHeight obj, final String line) {
+        final String[] values = line.split(SEPERATOR_CHAR, 0);
         if (values.length < 2) {
             // Do not import line without data or only km
             return;
         }
-
         Double km;
         try {
             km = new Double(nf.parse(values[0]).doubleValue());
-
-            if (kmExists.contains(km)) {
-                log.warn("duplicate station '" + km + "': -> ignored");
+            if (this.kmExists.contains(km)) {
+                log.warn("duplicate station '" + values[0] + "': -> ignored");
                 return;
             }
-
-            kmExists.add(km);
+            this.kmExists.add(km);
         }
-        catch (ParseException e) {
-            log.error("Error parsing km '" + values[0] + "': " +
-                e.getMessage());
+        catch (final ParseException e) {
+            log.error("Error parsing km '" + values[0] + "': " + e.getMessage());
             return;
         }
-
-        ImportBedHeightValue value = new ImportBedHeightValue(
-            (ImportBedHeight) obj,
-            km,
-            parse(values, 1, "height"),
-            parse(values, 2, "uncertainty"),
-            parse(values, 3, "data gap"),
-            parse(values, 4, "sounding width"));
+        final ImportBedHeightValue value = new ImportBedHeightValue(obj, km, parse(values, ColTitlePattern.HEIGHT),
+                parse(values, ColTitlePattern.UNCERTAINTY), parse(values, ColTitlePattern.GAP), parse(values, ColTitlePattern.WIDTH),
+                parse(values, ColTitlePattern.MINHEIGHT), parse(values, ColTitlePattern.MAXHEIGHT));
+        for (int i = 1; i <= 10; i++)
+            value.setSectionHeight(i, parse(values, ColTitlePattern.getSectionPattern(i)));
 
         obj.addValue(value);
     }
+
+    private Double parse(final String[] values, final ColTitlePattern col) {
+        final int idx = this.cols.get(col).intValue();
+        if ((idx >= 0) && (idx < values.length) && !values[idx].trim().isEmpty()) {
+            try {
+                return nf.parse(values[idx]).doubleValue();
+            }
+            catch (final ParseException e) {
+                log.warn("unparseable " + col.toString() + " '" + values[idx] + "'");
+            }
+        }
+        return null;
+    }
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/FlowVelocityMeasurementParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/FlowVelocityMeasurementParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,61 +8,58 @@
 
 package org.dive4elements.river.importer.parsers;
 
-import org.dive4elements.river.importer.ImportFlowVelocityMeasurement;
-import org.dive4elements.river.importer.ImportFlowVelocityMeasurementValue;
-
 import java.math.BigDecimal;
-
 import java.text.DateFormat;
 import java.text.NumberFormat;
-import java.text.ParseException;
 import java.text.SimpleDateFormat;
-
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImportFlowVelocityMeasurement;
+import org.dive4elements.river.importer.ImportFlowVelocityMeasurementValue;
+import org.dive4elements.river.importer.common.AbstractParser;
 public class FlowVelocityMeasurementParser extends LineParser {
 
     private static final Logger log =
-        Logger.getLogger(FlowVelocityMeasurementParser.class);
+            Logger.getLogger(FlowVelocityMeasurementParser.class);
 
     private static final NumberFormat nf =
-        NumberFormat.getInstance(DEFAULT_LOCALE);
+            NumberFormat.getInstance(DEFAULT_LOCALE);
 
     private static final DateFormat df =
-        new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
+            new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
 
 
-    private List<ImportFlowVelocityMeasurement> measurements;
+    private final List<ImportFlowVelocityMeasurement> measurements;
 
     private ImportFlowVelocityMeasurement current;
 
 
     public FlowVelocityMeasurementParser() {
-        measurements = new ArrayList<ImportFlowVelocityMeasurement>();
+        this.measurements = new ArrayList<>();
     }
 
 
     public List<ImportFlowVelocityMeasurement> getMeasurements() {
-        return measurements;
+        return this.measurements;
     }
 
     @Override
     protected void reset() {
-        current = new ImportFlowVelocityMeasurement();
+        this.current = new ImportFlowVelocityMeasurement();
     }
 
 
     @Override
     protected void finish() {
-        current.setDescription(fileName);
-        measurements.add(current);
+        this.current.setDescription(this.fileName);
+        this.measurements.add(this.current);
     }
 
 
     @Override
-    protected void handleLine(int lineNum, String line) {
+    protected void handleLine(final int lineNum, final String line) {
         if (line.startsWith(START_META_CHAR)) {
             handleMetaLine(stripMetaLine(line));
         }
@@ -72,12 +69,12 @@
     }
 
 
-    public void handleMetaLine(String line) {
+    public void handleMetaLine(final String line) {
     }
 
 
-    public void handleDataLine(String line) {
-        String[] cols = line.split(SEPERATOR_CHAR);
+    public void handleDataLine(final String line) {
+        final String[] cols = line.split(SEPERATOR_CHAR);
 
         if (cols.length < 8) {
             log.warn("skip invalid data line: '" + line + "'");
@@ -85,24 +82,17 @@
         }
 
         try {
-            double km     = nf.parse(cols[1]).doubleValue();
-            double w      = nf.parse(cols[5]).doubleValue();
-            double q      = nf.parse(cols[6]).doubleValue();
-            double v      = nf.parse(cols[7]).doubleValue();
-
-            String timestr     = cols[3] + " " + cols[4];
-            String description = cols.length > 8 ? cols[8] : null;
+            final BigDecimal km = AbstractParser.parseDecimal(cols[1]);
+            final BigDecimal w = AbstractParser.parseDecimal(cols[5]);
+            final BigDecimal q = AbstractParser.parseDecimal(cols[6]);
+            final BigDecimal v = AbstractParser.parseDecimal(cols[7]);
 
-            current.addValue(new ImportFlowVelocityMeasurementValue(
-                df.parse(timestr),
-                new BigDecimal(km),
-                new BigDecimal(w),
-                new BigDecimal(q),
-                new BigDecimal(v),
-                description
-            ));
+            final String timestr     = cols[3] + " " + cols[4];
+            final String description = cols.length > 8 ? cols[8] : null;
+
+            this.current.addValue(new ImportFlowVelocityMeasurementValue(df.parse(timestr), km, w, q, v, description));
         }
-        catch (ParseException pe) {
+        catch (final Exception pe) {
             log.warn("Unparseable flow velocity values:", pe);
         }
     }
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/FlowVelocityModelParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/FlowVelocityModelParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,7 +10,6 @@
 
 import java.io.File;
 import java.io.IOException;
-
 import java.math.BigDecimal;
 import java.text.NumberFormat;
 import java.text.ParseException;
@@ -21,48 +20,48 @@
 import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.utils.EpsilonComparator;
 import org.dive4elements.river.importer.ImportDischargeZone;
 import org.dive4elements.river.importer.ImportFlowVelocityModel;
 import org.dive4elements.river.importer.ImportFlowVelocityModelValue;
-import org.dive4elements.river.backend.utils.EpsilonComparator;
+import org.dive4elements.river.importer.common.AbstractParser;
 
 
 public class FlowVelocityModelParser extends LineParser {
 
     private static final Logger log =
-        Logger.getLogger(FlowVelocityModelParser.class);
+            Logger.getLogger(FlowVelocityModelParser.class);
 
     private static final Pattern META_REGEX =
-        Pattern.compile(".*Rechnung [unter ]*(.*) \\(Pegel (.*)\\).*");
+            Pattern.compile(".*Rechnung [unter ]*(.*) \\(Pegel (.*)\\).*");
 
     private static final Pattern META_GAUGE =
-        Pattern.compile("(.*) Q=(\\w*)m3/s");
+            Pattern.compile("(.*) Q=(\\w*)m3/s");
 
     private static final Pattern META_MAINVALUE_A =
-        Pattern.compile("([a-zA-Z]+)+(\\d+)*[\\w()]*");
+            Pattern.compile("([a-zA-Z]+)+(\\d+)*[\\w()]*");
 
     private static final Pattern META_MAINVALUE_B =
-        Pattern.compile(
-            "(([a-zA-Z]+)+(\\d+)*)\\s*-\\s*(([a-zA-Z]+)+(\\d+)*\\S*)");
+            Pattern.compile(
+                    "(([a-zA-Z]+)+(\\d+)*)\\s*-\\s*(([a-zA-Z]+)+(\\d+)*\\S*)");
 
     private static final Pattern META_MAINVALUE_C =
-        Pattern.compile("([0-9]++)\\s?(\\S*)|([0-9]++,[0-9]++)\\s?(\\S*)");
+            Pattern.compile("([0-9]++)\\s?(\\S*)|([0-9]++,[0-9]++)\\s?(\\S*)");
 
     private static final Pattern META_MAINVALUE_D =
-        Pattern.compile(
-            "(([0-9]*)\\s?(\\w*)|([0-9]++,[0-9]++)\\s?(\\w*))\\s*"
-            + "bis (([0-9]*)\\s?(\\S*)|([0-9]++,[0-9]++)\\s?(\\S*))");
+            Pattern.compile(
+                    "(([0-9]*)\\s?(\\w*)|([0-9]++,[0-9]++)\\s?(\\w*))\\s*"
+                            + "bis (([0-9]*)\\s?(\\S*)|([0-9]++,[0-9]++)\\s?(\\S*))");
 
     private static final Pattern META_MAINVALUE_E =
-        Pattern.compile(
-            "(([a-zA-Z]+)+(\\d+)*)\\s*bis (([a-zA-Z]+)+(\\d+)*\\S*)");
+            Pattern.compile(
+                    "(([a-zA-Z]+)+(\\d+)*)\\s*bis (([a-zA-Z]+)+(\\d+)*\\S*)");
 
     private static final NumberFormat nf =
-        NumberFormat.getInstance(DEFAULT_LOCALE);
+            NumberFormat.getInstance(DEFAULT_LOCALE);
 
 
-    private List<ImportFlowVelocityModel> models;
+    private final List<ImportFlowVelocityModel> models;
 
     private ImportFlowVelocityModel current;
 
@@ -72,38 +71,38 @@
 
 
     public FlowVelocityModelParser() {
-        models = new ArrayList<ImportFlowVelocityModel>();
-        kmExists = new TreeSet<Double>(EpsilonComparator.CMP);
+        this.models = new ArrayList<>();
+        this.kmExists = new TreeSet<>(EpsilonComparator.CMP);
     }
 
 
     public List<ImportFlowVelocityModel> getModels() {
-        return models;
+        return this.models;
     }
 
     @Override
-    public void parse(File file) throws IOException {
-        description = file.getName();
+    public void parse(final File file) throws IOException {
+        this.description = file.getName();
 
         super.parse(file);
     }
 
     @Override
     protected void reset() {
-        current = new ImportFlowVelocityModel(description);
-        kmExists.clear();
+        this.current = new ImportFlowVelocityModel(this.description);
+        this.kmExists.clear();
     }
 
 
     @Override
     protected void finish() {
-        models.add(current);
+        this.models.add(this.current);
         // description = null;
     }
 
 
     @Override
-    protected void handleLine(int lineNum, String line) {
+    protected void handleLine(final int lineNum, final String line) {
         if (line.startsWith(START_META_CHAR)) {
             handleMetaLine(stripMetaLine(line));
         }
@@ -113,16 +112,16 @@
     }
 
 
-    protected void handleMetaLine(String line) {
-        Matcher m = META_REGEX.matcher(line);
+    protected void handleMetaLine(final String line) {
+        final Matcher m = META_REGEX.matcher(line);
 
         if (m.matches()) {
-            String mainValueStr = m.group(1);
+            final String mainValueStr = m.group(1);
             log.debug("mainValueStr = '" + mainValueStr + "'");
-            String gaugeStr     = m.group(2);
+            final String gaugeStr     = m.group(2);
 
-            Object[] valueData = handleMainValueString(mainValueStr);
-            Object[] gaugeData = handleGaugeString(gaugeStr);
+            final Object[] valueData = handleMainValueString(mainValueStr);
+            final Object[] gaugeData = handleGaugeString(gaugeStr);
 
             if (valueData == null || valueData.length < 2) {
                 log.warn("skip invalid MainValue part in '" + line + "'");
@@ -142,102 +141,102 @@
                 log.debug("   upper: " + valueData[1]);
             }
 
-            current.setDischargeZone(new ImportDischargeZone(
-                (String) gaugeData[0],
-                (BigDecimal) gaugeData[1],
-                (String) valueData[0],
-                (String) valueData[1]
-            ));
+            this.current.setDischargeZone(new ImportDischargeZone(
+                    (String) gaugeData[0],
+                    (BigDecimal) gaugeData[1],
+                    (String) valueData[0],
+                    (String) valueData[1]
+                    ));
         }
     }
 
 
-    protected Object[] handleMainValueString(String mainValueStr) {
-        Matcher mA = META_MAINVALUE_A.matcher(mainValueStr.trim());
+    protected Object[] handleMainValueString(final String mainValueStr) {
+        final Matcher mA = META_MAINVALUE_A.matcher(mainValueStr.trim());
         if (mA.matches()) {
             log.debug("mainValueStr matches META_MAINVALUE_A");
-            String name = mA.group(0);
+            final String name = mA.group(0);
 
             return new Object[] { name, name };
         }
 
-        Matcher mB = META_MAINVALUE_B.matcher(mainValueStr.trim());
+        final Matcher mB = META_MAINVALUE_B.matcher(mainValueStr.trim());
         if (mB.matches()) {
             log.debug("mainValueStr matches META_MAINVALUE_B");
-            String lower = mB.group(1);
-            String upper = mB.group(4);
+            final String lower = mB.group(1);
+            final String upper = mB.group(4);
 
             return new Object[] { lower, upper };
         }
 
-        Matcher mC = META_MAINVALUE_C.matcher(mainValueStr.trim());
+        final Matcher mC = META_MAINVALUE_C.matcher(mainValueStr.trim());
         if (mC.matches()) {
             log.debug("mainValueStr matches META_MAINVALUE_C");
-            String facA  = mC.group(1);
-            String nameA = mC.group(2);
-            String facB  = mC.group(3);
-            String nameB = mC.group(4);
+            final String facA  = mC.group(1);
+            final String nameA = mC.group(2);
+            final String facB  = mC.group(3);
+            final String nameB = mC.group(4);
 
-            String fac  = facA  != null ? facA  : facB;
-            String name = nameA != null ? nameA : nameB;
+            final String fac  = facA  != null ? facA  : facB;
+            final String name = nameA != null ? nameA : nameB;
 
-            String mainValue = fac + " " + name;
+            final String mainValue = fac + " " + name;
 
             return new Object[] { mainValue, mainValue };
         }
 
-        Matcher mD = META_MAINVALUE_D.matcher(mainValueStr.trim());
+        final Matcher mD = META_MAINVALUE_D.matcher(mainValueStr.trim());
         if (mD.matches()) {
             log.debug("mainValueStr matches META_MAINVALUE_D");
-            String loFacA  = mD.group(2);
-            String loNameA = mD.group(3);
-            String loFacB  = mD.group(4);
-            String loNameB = mD.group(5);
+            final String loFacA  = mD.group(2);
+            final String loNameA = mD.group(3);
+            final String loFacB  = mD.group(4);
+            final String loNameB = mD.group(5);
 
-            String upFacA  = mD.group(7);
-            String upNameA = mD.group(8);
-            String upFacB  = mD.group(9);
-            String upNameB = mD.group(10);
+            final String upFacA  = mD.group(7);
+            final String upNameA = mD.group(8);
+            final String upFacB  = mD.group(9);
+            final String upNameB = mD.group(10);
 
-            String loFac  = loFacA  != null ? loFacA  : loFacB;
-            String loName = loNameA != null ? loNameA : loNameB;
+            final String loFac  = loFacA  != null ? loFacA  : loFacB;
+            final String loName = loNameA != null ? loNameA : loNameB;
 
-            String upFac  = upFacA  != null ? upFacA  : upFacB;
-            String upName = upNameA != null ? upNameA : upNameB;
+            final String upFac  = upFacA  != null ? upFacA  : upFacB;
+            final String upName = upNameA != null ? upNameA : upNameB;
 
-            String loMainValue = loFac + " " + loName;
-            String upMainValue = upFac + " " + upName;
+            final String loMainValue = loFac + " " + loName;
+            final String upMainValue = upFac + " " + upName;
 
             return new Object[] { loMainValue, upMainValue };
         }
 
-        Matcher mE = META_MAINVALUE_E.matcher(mainValueStr.trim());
+        final Matcher mE = META_MAINVALUE_E.matcher(mainValueStr.trim());
         if (mE.matches()) {
             log.debug("mainValueStr matches META_MAINVALUE_E");
-            String lower = mE.group(1);
-            String upper = mE.group(4);
+            final String lower = mE.group(1);
+            final String upper = mE.group(4);
 
             return new Object[] { lower, upper };
         }
 
-    log.debug("mainValueStr not matched");
+        log.debug("mainValueStr not matched");
         return null;
     }
 
 
-    protected Object[] handleGaugeString(String gaugeStr) {
-        Matcher m = META_GAUGE.matcher(gaugeStr);
+    protected Object[] handleGaugeString(final String gaugeStr) {
+        final Matcher m = META_GAUGE.matcher(gaugeStr);
 
         if (m.matches()) {
-            String name = m.group(1);
-            String qStr = m.group(2);
+            final String name = m.group(1);
+            final String qStr = m.group(2);
 
             try {
                 return new Object[] {
-                    name,
-                    new BigDecimal(nf.parse(qStr).doubleValue()) };
+                        name,
+                        AbstractParser.parseDecimal(qStr) };
             }
-            catch (ParseException pe) {
+            catch (final ParseException pe) {
                 log.warn("Could not parse Q value: '" + qStr + "'");
             }
         }
@@ -246,8 +245,8 @@
     }
 
 
-    protected void handleDataLine(String line) {
-        String[] cols = line.split(SEPERATOR_CHAR);
+    protected void handleDataLine(final String line) {
+        final String[] cols = line.split(SEPERATOR_CHAR);
 
         if (cols.length < 5) {
             log.warn("skip invalid data line: '" + line + "'");
@@ -255,31 +254,25 @@
         }
 
         try {
-            double km = nf.parse(cols[0]).doubleValue();
+            final BigDecimal km = AbstractParser.parseDecimal(cols[0]);
 
-            Double key = Double.valueOf(km);
+            final Double key = Double.valueOf(km.doubleValue());
 
-            if (kmExists.contains(key)) {
+            if (this.kmExists.contains(key)) {
                 log.warn("duplicate station '" + km + "': -> ignored");
                 return;
             }
 
-            double q      = nf.parse(cols[1]).doubleValue();
-            double total  = nf.parse(cols[2]).doubleValue();
-            double main   = nf.parse(cols[3]).doubleValue();
-            double stress = nf.parse(cols[4]).doubleValue();
+            final BigDecimal q = AbstractParser.parseDecimal(cols[1]);
+            final BigDecimal total = AbstractParser.parseDecimal(cols[2]);
+            final BigDecimal main = AbstractParser.parseDecimal(cols[3]);
+            final BigDecimal stress = AbstractParser.parseDecimal(cols[4]);
 
-            current.addValue(new ImportFlowVelocityModelValue(
-                new BigDecimal(km),
-                new BigDecimal(q),
-                new BigDecimal(total),
-                new BigDecimal(main),
-                new BigDecimal(stress)
-            ));
+            this.current.addValue(new ImportFlowVelocityModelValue(km, q, total, main, stress));
 
-            kmExists.add(key);
+            this.kmExists.add(key);
         }
-        catch (ParseException pe) {
+        catch (final ParseException pe) {
             log.warn("Unparseable flow velocity values:", pe);
         }
     }
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/MeasurementStationsParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/MeasurementStationsParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,19 +8,17 @@
 
 package org.dive4elements.river.importer.parsers;
 
-import java.math.BigDecimal;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.dive4elements.river.model.MeasurementStation;
-
 import org.dive4elements.river.importer.ImportMeasurementStation;
 import org.dive4elements.river.importer.ImportRange;
 import org.dive4elements.river.importer.ImportTimeInterval;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.model.MeasurementStation;
 
 
 public class MeasurementStationsParser extends LineParser {
@@ -29,7 +27,7 @@
 
         private static final long serialVersionUID = 1L;
 
-        public MeasurementStationParserException(String msg) {
+        public MeasurementStationParserException(final String msg) {
             super(msg);
         }
     }
@@ -39,14 +37,14 @@
     public static final int MAX_COMMENT_LENGTH = 512;
 
     private static final Logger log = Logger
-        .getLogger(MeasurementStationsParser.class);
+            .getLogger(MeasurementStationsParser.class);
 
     private List<ImportMeasurementStation> measurementStations;
     private ImportMeasurementStation current;
 
     @Override
     protected void reset() {
-        this.measurementStations = new ArrayList<ImportMeasurementStation>();
+        this.measurementStations = new ArrayList<>();
     }
 
     @Override
@@ -54,114 +52,109 @@
     }
 
     @Override
-    protected void handleLine(int lineNum, String line) {
+    protected void handleLine(final int lineNum, final String line) {
         if (line == null || line.startsWith(START_META_CHAR)) {
             log.info("skip meta information at line " + lineNum);
             return;
         }
 
         try {
-            current = new ImportMeasurementStation();
+            this.current = new ImportMeasurementStation();
             handleDataLine(lineNum, line);
-            measurementStations.add(current);
+            this.measurementStations.add(this.current);
         }
-        catch (MeasurementStationParserException e) {
+        catch (final MeasurementStationParserException e) {
             log.warn("Problem in line " + lineNum + ": " + e.getMessage());
         }
     }
 
     public List<ImportMeasurementStation> getMeasurementStations() {
-        return measurementStations;
+        return this.measurementStations;
     }
 
-    protected void handleDataLine(int lineNum, String line)
-        throws MeasurementStationParserException {
-        String[] cols = line.split(SEPERATOR_CHAR);
+    protected void handleDataLine(final int lineNum, final String line)
+            throws MeasurementStationParserException {
+        final String[] cols = line.split(SEPERATOR_CHAR);
 
         if (cols == null || cols.length < MIN_COLUMNS) {
-            int num = cols != null ? cols.length : 0;
+            final int num = cols != null ? cols.length : 0;
             throw new MeasurementStationParserException("Not enough columns: "
-                + num);
+                    + num);
         }
 
-        current.name = getName(cols, lineNum);
-        current.range = getRange(cols, lineNum);
-        current.measurementType = getMeasurementType(cols, lineNum);
-        current.riverside = getRiverside(cols, lineNum);
-        current.gauge = getGauge(cols, lineNum);
-        current.observationTimerange = getObservationTimerange(cols, lineNum);
-        current.operator = getOperator(cols, lineNum);
-        current.comment = getComment(cols, lineNum);
+        this.current.name = getName(cols, lineNum);
+        this.current.range = getRange(cols, lineNum);
+        this.current.measurementType = getMeasurementType(cols, lineNum);
+        this.current.riverside = getRiverside(cols, lineNum);
+        this.current.gauge = getGauge(cols, lineNum);
+        this.current.observationTimerange = getObservationTimerange(cols, lineNum);
+        this.current.operator = getOperator(cols, lineNum);
+        this.current.comment = getComment(cols, lineNum);
     }
 
-    protected String getName(String[] cols, int lineNum)
-        throws MeasurementStationParserException {
+    protected String getName(final String[] cols, final int lineNum)
+            throws MeasurementStationParserException {
         if (cols[0] == null || cols[0].length() == 0) {
             throw new MeasurementStationParserException("invalid name in line "
-                + lineNum);
+                    + lineNum);
         }
 
         return cols[0];
     }
 
-    protected ImportRange getRange(String[] cols, int lineNum) {
-        String from = cols[1];
-        String to   = cols[4];
+    protected ImportRange getRange(final String[] cols, final int lineNum) {
+        final String from = cols[1];
+        final String to   = cols[4];
         if (from == null || from.length() == 0) {
             log.error("No station found in line" + lineNum);
             return null;
         }
 
         try {
-            double lower = getDouble(from);
-
             if (to == null || to.length() == 0) {
                 log.warn("No end km found in line " + lineNum);
-                return new ImportRange(new BigDecimal(lower));
+                return new ImportRange(AbstractParser.parseDecimal(from));
             }
 
             try {
-                double upper = getDouble(to);
-
-                return new ImportRange(new BigDecimal(lower),
-                    new BigDecimal(upper));
+                return new ImportRange(AbstractParser.parseDecimal(from), AbstractParser.parseDecimal(to));
             }
-            catch (ParseException e) {
+            catch (final NumberFormatException e) {
                 log.warn("Unparseable end km in line " + lineNum +
-                    ". Error: " + e.getMessage());
-                return new ImportRange(new BigDecimal(lower));
+                        ". Error: " + e.getMessage());
+                return new ImportRange(AbstractParser.parseDecimal(from));
             }
 
         }
-        catch (ParseException e) {
+        catch (final ParseException e) {
             log.error("Unparseable station in line " + lineNum +
                     ". Error: " + e.getMessage());
             return null;
         }
     }
 
-    protected String getMeasurementType(String[] cols, int lineNum)
-        throws MeasurementStationParserException {
-        String mtype = cols[2].trim();
+    protected String getMeasurementType(final String[] cols, final int lineNum)
+            throws MeasurementStationParserException {
+        final String mtype = cols[2].trim();
         if (!(MeasurementStation.MEASUREMENT_TYPE_BEDLOAD.equals(mtype) ||
                 MeasurementStation.MEASUREMENT_TYPE_SUSP.equals(mtype))) {
             throw new MeasurementStationParserException(
-                "invalid measurement type in line " + lineNum);
+                    "invalid measurement type in line " + lineNum);
         }
 
         return mtype;
     }
 
-    protected String getRiverside(String[] cols, int lineNum) {
-        String col = cols[3];
+    protected String getRiverside(final String[] cols, final int lineNum) {
+        final String col = cols[3];
         if (col == null || col.length() == 0) {
             log.warn("No river side given in line " + lineNum);
         }
         return col;
     }
 
-    protected String getGauge(String[] cols, int lineNum) {
-        String col = cols[5];
+    protected String getGauge(final String[] cols, final int lineNum) {
+        final String col = cols[5];
         if (col == null || col.length() == 0) {
             log.warn("Invalid gauge found in line " + lineNum);
         }
@@ -169,45 +162,45 @@
     }
 
     protected ImportTimeInterval getObservationTimerange(
-        String[] cols,
-        int lineNum
-    ) {
-        String col = cols[7];
+            final String[] cols,
+            final int lineNum
+            ) {
+        final String col = cols[7];
         if (col == null || col.length() == 0) {
             log.warn("Observation time invalid in line " + lineNum);
             return null;
         }
 
         try {
-            Date date = getDate(col);
+            final Date date = getDate(col);
 
             if (date != null) {
                 return new ImportTimeInterval(date);
             }
             log.warn("Observation time invalid in line " + lineNum);
         }
-        catch (ParseException pe) {
+        catch (final ParseException pe) {
             log.warn("Unparseable observation time '" + col +
-                "' in line " + lineNum);
+                    "' in line " + lineNum);
         }
         return null;
     }
 
-    protected String getOperator(String[] cols, int lineNum) {
-        String col = cols[8];
+    protected String getOperator(final String[] cols, final int lineNum) {
+        final String col = cols[8];
         if (col == null || col.length() == 0) {
             log.warn("No operator given in line " + lineNum);
         }
         return col;
     }
 
-    protected String getComment(String[] cols, int lineNum) {
+    protected String getComment(final String[] cols, final int lineNum) {
         if (cols.length > MIN_COLUMNS) {
-            String col = cols[9];
+            final String col = cols[9];
             if (col.length() > MAX_COMMENT_LENGTH) {
                 log.warn("Comment in line " + lineNum +
-                    " longer than allowed " + MAX_COMMENT_LENGTH +
-                    " characters. Truncated.");
+                        " longer than allowed " + MAX_COMMENT_LENGTH +
+                        " characters. Truncated.");
                 return col.substring(0, MAX_COMMENT_LENGTH);
             }
             return col;
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/MorphologicalWidthParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/MorphologicalWidthParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,32 +9,30 @@
 package org.dive4elements.river.importer.parsers;
 
 import java.math.BigDecimal;
-
 import java.text.NumberFormat;
 import java.text.ParseException;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
-
 import org.dive4elements.river.importer.ImportMorphWidth;
 import org.dive4elements.river.importer.ImportMorphWidthValue;
 import org.dive4elements.river.importer.ImportUnit;
+import org.dive4elements.river.importer.common.AbstractParser;
 
 
 public class MorphologicalWidthParser extends LineParser {
 
     private static final Logger log =
-        Logger.getLogger(MorphologicalWidthParser.class);
+            Logger.getLogger(MorphologicalWidthParser.class);
 
     public static final NumberFormat nf = NumberFormat.getInstance(
-        DEFAULT_LOCALE);
+            DEFAULT_LOCALE);
 
     public static final Pattern META_UNIT =
-        Pattern.compile("^Einheit: \\[(.*)\\].*");
+            Pattern.compile("^Einheit: \\[(.*)\\].*");
 
     protected List<ImportMorphWidth> morphWidths;
 
@@ -42,26 +40,26 @@
 
 
     public MorphologicalWidthParser() {
-        morphWidths = new ArrayList<ImportMorphWidth>();
+        this.morphWidths = new ArrayList<>();
     }
 
 
     @Override
     protected void reset() {
-        current = new ImportMorphWidth();
+        this.current = new ImportMorphWidth();
     }
 
 
     @Override
     protected void finish() {
-        if (current != null) {
-            morphWidths.add(current);
+        if (this.current != null) {
+            this.morphWidths.add(this.current);
         }
     }
 
 
     @Override
-    protected void handleLine(int lineNum, String line) {
+    protected void handleLine(final int lineNum, final String line) {
         if (line.startsWith(START_META_CHAR)) {
             handleMetaLine(stripMetaLine(line));
         }
@@ -71,7 +69,7 @@
     }
 
 
-    protected void handleMetaLine(String line) {
+    protected void handleMetaLine(final String line) {
         if (handleMetaUnit(line)) {
             return;
         }
@@ -81,13 +79,13 @@
     }
 
 
-    protected boolean handleMetaUnit(String line) {
-        Matcher m = META_UNIT.matcher(line);
+    protected boolean handleMetaUnit(final String line) {
+        final Matcher m = META_UNIT.matcher(line);
 
         if (m.matches()) {
-            String unit = m.group(1);
+            final String unit = m.group(1);
 
-            current.setUnit(new ImportUnit(unit));
+            this.current.setUnit(new ImportUnit(unit));
 
             return true;
         }
@@ -96,8 +94,8 @@
     }
 
 
-    protected void handleDataLine(String line) {
-        String[] vals = line.split(SEPERATOR_CHAR);
+    protected void handleDataLine(final String line) {
+        final String[] vals = line.split(SEPERATOR_CHAR);
 
         if (vals == null || vals.length < 2) {
             log.warn("MWP: skip invalid data line: '" + line + "'");
@@ -105,25 +103,25 @@
         }
 
         try {
-            BigDecimal km    = new BigDecimal(nf.parse(vals[0]).doubleValue());
-            BigDecimal width = new BigDecimal(nf.parse(vals[1]).doubleValue());
-
-            String desc = vals.length > 2 ? vals[2] : null;
+            final BigDecimal km = AbstractParser.parseDecimal(vals[0]);
+            final BigDecimal width = AbstractParser.parseDecimal(vals[1]);
 
-            current.addValue(new ImportMorphWidthValue(
-                km,
-                width,
-                desc
-            ));
+            final String desc = vals.length > 2 ? vals[2] : null;
+
+            this.current.addValue(new ImportMorphWidthValue(
+                    km,
+                    width,
+                    desc
+                    ));
         }
-        catch (ParseException pe) {
+        catch (final ParseException pe) {
             log.warn("MWP: unparseable number in data row: " + line);
         }
     }
 
 
     public List<ImportMorphWidth> getMorphologicalWidths() {
-        return morphWidths;
+        return this.morphWidths;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/SedimentDensityParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/SedimentDensityParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,39 +8,35 @@
 
 package org.dive4elements.river.importer.parsers;
 
-import org.dive4elements.river.importer.ImportDepth;
-import org.dive4elements.river.importer.ImportSedimentDensity;
-import org.dive4elements.river.importer.ImportSedimentDensityValue;
-
 import java.io.File;
 import java.io.IOException;
-
 import java.math.BigDecimal;
-
 import java.text.NumberFormat;
 import java.text.ParseException;
-
 import java.util.ArrayList;
 import java.util.List;
-
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImportDepth;
+import org.dive4elements.river.importer.ImportSedimentDensity;
+import org.dive4elements.river.importer.ImportSedimentDensityValue;
+import org.dive4elements.river.importer.common.AbstractParser;
 
 public class SedimentDensityParser extends LineParser {
 
     private static final Logger log =
-        Logger.getLogger(SedimentDensityParser.class);
+            Logger.getLogger(SedimentDensityParser.class);
 
     public static final NumberFormat nf =
-        NumberFormat.getInstance(DEFAULT_LOCALE);
+            NumberFormat.getInstance(DEFAULT_LOCALE);
 
     public static final Pattern META_DEPTH =
-        Pattern.compile("^Tiefe: (\\d++)-(\\d++).*");
+            Pattern.compile("^Tiefe: (\\d++)-(\\d++).*");
 
     public static final Pattern META_YEAR =
-        Pattern.compile("^Jahr: (\\d{4}).*");
+            Pattern.compile("^Jahr: (\\d{4}).*");
 
     protected List<ImportSedimentDensity> sedimentDensities;
 
@@ -51,13 +47,13 @@
     protected String yearString;
 
     public SedimentDensityParser() {
-        sedimentDensities = new ArrayList<ImportSedimentDensity>();
+        this.sedimentDensities = new ArrayList<>();
     }
 
 
     @Override
-    public void parse(File file) throws IOException {
-        currentDescription = file.getName();
+    public void parse(final File file) throws IOException {
+        this.currentDescription = file.getName();
 
         super.parse(file);
     }
@@ -65,20 +61,20 @@
 
     @Override
     protected void reset() {
-        current = new ImportSedimentDensity(currentDescription);
+        this.current = new ImportSedimentDensity(this.currentDescription);
     }
 
 
     @Override
     protected void finish() {
-        if (current != null) {
-            sedimentDensities.add(current);
+        if (this.current != null) {
+            this.sedimentDensities.add(this.current);
         }
     }
 
 
     @Override
-    protected void handleLine(int lineNum, String line) {
+    protected void handleLine(final int lineNum, final String line) {
         if (line.startsWith(START_META_CHAR)) {
             handleMetaLine(stripMetaLine(line));
         }
@@ -88,7 +84,7 @@
     }
 
 
-    protected void handleMetaLine(String line) {
+    protected void handleMetaLine(final String line) {
         if (handleMetaDepth(line)) {
             return;
         }
@@ -99,27 +95,26 @@
     }
 
 
-    protected boolean handleMetaDepth(String line) {
-        Matcher m = META_DEPTH.matcher(line);
+    protected boolean handleMetaDepth(final String line) {
+        final Matcher m = META_DEPTH.matcher(line);
 
         if (m.matches()) {
-            String lo   = m.group(1);
-            String up   = m.group(2);
+            final String lo   = m.group(1);
+            final String up   = m.group(2);
 
             log.info("Found sediment density depth: "
-                + lo + " - " + up + " cm");
+                    + lo + " - " + up + " cm");
 
             try {
-                ImportDepth depth = new ImportDepth(
-                    new BigDecimal(nf.parse(lo).doubleValue()),
-                    new BigDecimal(nf.parse(up).doubleValue())
-                );
+                final ImportDepth depth = new ImportDepth(
+                        AbstractParser.parseDecimal(lo),
+                        AbstractParser.parseDecimal(up));
 
-                current.setDepth(depth);
+                this.current.setDepth(depth);
 
                 return true;
             }
-            catch (ParseException pe) {
+            catch (final ParseException pe) {
                 log.warn("Unparseable numbers in: '" + line + "'");
             }
         }
@@ -130,13 +125,13 @@
         return false;
     }
 
-    protected boolean handleMetaYear(String line) {
-        Matcher m = META_YEAR.matcher(line);
+    protected boolean handleMetaYear(final String line) {
+        final Matcher m = META_YEAR.matcher(line);
 
         if (m.matches()) {
-            yearString = m.group(1);
+            this.yearString = m.group(1);
 
-            log.info("Found sediment density year: " + yearString);
+            log.info("Found sediment density year: " + this.yearString);
 
             return true;
         }
@@ -147,8 +142,8 @@
     }
 
 
-    protected void handleDataLine(String line) {
-        String[] vals = line.split(SEPERATOR_CHAR);
+    protected void handleDataLine(final String line) {
+        final String[] vals = line.split(SEPERATOR_CHAR);
 
         if (vals == null || vals.length < 3) {
             log.warn("skip invalid data line: '" + line + "'");
@@ -159,13 +154,13 @@
         BigDecimal shoreOffset = null;
         BigDecimal density = null;
         try {
-            km          = new BigDecimal(nf.parse(vals[0]).doubleValue());
-            density     = new BigDecimal(nf.parse(vals[2]).doubleValue());
+            km = AbstractParser.parseDecimal(vals[0]);
+            density = AbstractParser.parseDecimal(vals[2]);
             if (!vals[1].isEmpty()) {
-                shoreOffset = new BigDecimal(nf.parse(vals[1]).doubleValue());
+                shoreOffset = AbstractParser.parseDecimal(vals[1]);
             }
         }
-        catch (ParseException pe) {
+        catch (final ParseException pe) {
             log.warn("Unparseable numbers in '" + line + "'");
         }
 
@@ -175,26 +170,26 @@
         }
 
         BigDecimal year = null;
-        if (yearString != null) {
+        if (this.yearString != null) {
             try {
-                year = new BigDecimal(nf.parse(yearString).doubleValue());
+                year = AbstractParser.parseDecimal(this.yearString);
             }
-            catch (ParseException pe) {
+            catch (final ParseException pe) {
                 log.warn("Unparseable year string");
             }
         }
 
-        current.addValue(new ImportSedimentDensityValue(
-            km,
-            shoreOffset,
-            density,
-            year,
-            currentDescription));
+        this.current.addValue(new ImportSedimentDensityValue(
+                km,
+                shoreOffset,
+                density,
+                year,
+                this.currentDescription));
     }
 
 
     public List<ImportSedimentDensity> getSedimentDensities() {
-        return sedimentDensities;
+        return this.sedimentDensities;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -19,15 +19,14 @@
 import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.utils.DateUtil;
 import org.dive4elements.river.importer.ImportTimeInterval;
 import org.dive4elements.river.importer.ImportUnit;
-
 import org.dive4elements.river.importer.ImportWst;
-import org.dive4elements.river.importer.ImportWstQRange;
 import org.dive4elements.river.importer.ImportWstColumn;
 import org.dive4elements.river.importer.ImportWstColumnValue;
-import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.importer.ImportWstQRange;
+import org.dive4elements.river.importer.common.AbstractParser;
 
 
 /**
@@ -36,21 +35,21 @@
 public class WaterlevelDifferencesParser extends LineParser {
 
     private static final Logger log =
-        Logger.getLogger(WaterlevelDifferencesParser.class);
+            Logger.getLogger(WaterlevelDifferencesParser.class);
 
     private static final NumberFormat nf =
-        NumberFormat.getInstance(DEFAULT_LOCALE);
+            NumberFormat.getInstance(DEFAULT_LOCALE);
 
     public static final Pattern META_UNIT =
-        Pattern.compile("^Einheit: \\[(.*)\\].*");
+            Pattern.compile("^Einheit: \\[(.*)\\].*");
 
     public static final Pattern YEARS_IN_COLUMN =
-        Pattern.compile(".*(\\d{4})-(\\d{4})$");
+            Pattern.compile(".*(\\d{4})-(\\d{4})$");
 
-    public static final double INTERVAL_GAP = 0.00001d;
+    public static final BigDecimal INTERVAL_GAP = new BigDecimal("0.00001");
 
     /** List of parsed differences as ImportWst s. */
-    private List<ImportWst> differences;
+    private final List<ImportWst> differences;
 
     private ImportWstColumn[] columns;
 
@@ -59,13 +58,13 @@
 
 
     public WaterlevelDifferencesParser() {
-        differences = new ArrayList<ImportWst>();
+        this.differences = new ArrayList<>();
     }
 
 
     /** Get the differences as wst parsed so far. */
     public List<ImportWst> getDifferences() {
-        return differences;
+        return this.differences;
     }
 
 
@@ -74,9 +73,9 @@
      * from it.
      */
     @Override
-    public void parse(File file) throws IOException {
-        current = new ImportWst(file.getName());
-        current.setKind(6);
+    public void parse(final File file) throws IOException {
+        this.current = new ImportWst(file.getName());
+        this.current.setKind(6);
 
         super.parse(file);
     }
@@ -90,14 +89,14 @@
 
     @Override
     protected void finish() {
-        if (columns != null && current != null) {
+        if (this.columns != null && this.current != null) {
             // TODO figure out if its needed, as the columns
             //      are registered at their construction time.
-            for (ImportWstColumn col: columns) {
+            for (final ImportWstColumn col: this.columns) {
                 // TODO place a current.addColumn(col); here?
             }
 
-            differences.add(current);
+            this.differences.add(this.current);
         }
 
         // For all differences columns, add a single Q-Range with
@@ -106,27 +105,27 @@
         // TODO: should otherwise be extended to
         // (first station of next range - INTERVAL_GAP),
         // assuming always ascending stations
-        for (ImportWstColumn column: columns) {
-            List<ImportWstColumnValue> cValues = column.getColumnValues();
-            BigDecimal a = cValues.get(0).getPosition();
+        for (final ImportWstColumn column: this.columns) {
+            final List<ImportWstColumnValue> cValues = column.getColumnValues();
+            final BigDecimal a = cValues.get(0).getPosition();
             BigDecimal b = cValues.get(cValues.size() - 1).getPosition();
             if (a.compareTo(b) == 0) {
-                b = new BigDecimal(b.doubleValue() + INTERVAL_GAP);
+                b = b.add(INTERVAL_GAP);
             }
             column.addColumnQRange(
-                new ImportWstQRange(
-                    a,
-                    b,
-                    new BigDecimal(-1d))
-                );
+                    new ImportWstQRange(
+                            a,
+                            b,
+                            new BigDecimal(-1d))
+                    );
         }
-        current = null;
-        columns = null;
+        this.current = null;
+        this.columns = null;
     }
 
 
     @Override
-    protected void handleLine(int lineNum, String line) {
+    protected void handleLine(final int lineNum, final String line) {
         if (line.startsWith(START_META_CHAR)) {
             handleMetaLine(stripMetaLine(line));
         }
@@ -136,7 +135,7 @@
     }
 
 
-    private void handleMetaLine(String meta) {
+    private void handleMetaLine(final String meta) {
         if (handleMetaUnit(meta)) {
             return;
         }
@@ -146,14 +145,14 @@
     }
 
 
-    private boolean handleMetaUnit(String meta) {
-        Matcher m = META_UNIT.matcher(meta);
+    private boolean handleMetaUnit(final String meta) {
+        final Matcher m = META_UNIT.matcher(meta);
 
         if (m.matches()) {
-            String unit = m.group(1);
+            final String unit = m.group(1);
             log.debug("Found unit: '" + unit + "'");
 
-            current.setUnit(new ImportUnit(unit));
+            this.current.setUnit(new ImportUnit(unit));
 
             return true;
         }
@@ -162,13 +161,13 @@
     }
 
 
-    private boolean handleMetaColumnNames(String meta) {
-        Pattern META_COLUMN_NAMES = Pattern.compile("Fluss-km;(.*)");
-        Matcher m = META_COLUMN_NAMES.matcher(meta);
+    private boolean handleMetaColumnNames(final String meta) {
+        final Pattern META_COLUMN_NAMES = Pattern.compile("Fluss-km;(.*)");
+        final Matcher m = META_COLUMN_NAMES.matcher(meta);
 
         if (m.matches()) {
-            String colStr = m.group(1);
-            String[] cols = colStr.split(SEPERATOR_CHAR);
+            final String colStr = m.group(1);
+            final String[] cols = colStr.split(SEPERATOR_CHAR);
 
             log.debug("Found " + cols.length + " columns.");
 
@@ -182,28 +181,28 @@
 
 
     /** Setup column structures with name, description and time interval. */
-    private void initColumns(String[] cols) {
-        current.setNumberColumns(cols.length);
-        columns = current.getColumns().toArray(
-            new ImportWstColumn[cols.length]);
+    private void initColumns(final String[] cols) {
+        this.current.setNumberColumns(cols.length);
+        this.columns = this.current.getColumns().toArray(
+                new ImportWstColumn[cols.length]);
 
         for (int i = 0; i < cols.length; i++) {
-            String name = cols[i].replace("\"", "");
+            final String name = cols[i].replace("\"", "");
 
             log.debug("Create new column '" + name + "'");
-            ImportWstColumn column = current.getColumn(i);
+            final ImportWstColumn column = this.current.getColumn(i);
             column.setName(name);
             column.setDescription(name);
 
-            Matcher m = YEARS_IN_COLUMN.matcher(name);
+            final Matcher m = YEARS_IN_COLUMN.matcher(name);
 
             if (m.matches()) {
-                int startYear = Integer.parseInt(m.group(1));
-                int endYear   = Integer.parseInt(m.group(2));
-                ImportTimeInterval time = new ImportTimeInterval(
-                    DateUtil.getStartDateFromYear(startYear),
-                    DateUtil.getEndDateFromYear(endYear)
-                );
+                final int startYear = Integer.parseInt(m.group(1));
+                final int endYear   = Integer.parseInt(m.group(2));
+                final ImportTimeInterval time = new ImportTimeInterval(
+                        DateUtil.getStartDateFromYear(startYear),
+                        DateUtil.getEndDateFromYear(endYear)
+                        );
                 column.setTimeInterval(time);
             } else {
                 log.debug("No time interval in column header found: " + name);
@@ -215,9 +214,9 @@
     /** Handle one line of data, add one value for all columns.
      * @param line the line to parse
      */
-    private void handleDataLine(String line) {
+    private void handleDataLine(final String line) {
         // Split by separator, do not exclude trailing empty string.
-        String[] cols = line.split(SEPERATOR_CHAR, -1);
+        final String[] cols = line.split(SEPERATOR_CHAR, -1);
 
         if (cols == null || cols.length < 2) {
             log.warn("skip invalid waterlevel-diff line: '" + line + "'");
@@ -227,31 +226,31 @@
         try {
             // The first value in a line like 12,9;4,3;4,5 is the station,
             // later real values.
-            Double station = nf.parse(cols[0]).doubleValue();
+            final BigDecimal station = AbstractParser.parseDecimal(cols[0]);
 
-            for (int i = 0; i < columns.length; i++) {
-                int idx = i+1;
+            for (int i = 0; i < this.columns.length; i++) {
+                final int idx = i+1;
 
                 if (idx >= cols.length) {
                     log.warn("Insufficient column numbers: " + line);
                     continue;
                 }
 
-                String value = cols[idx];
+                final String value = cols[idx];
 
                 if (value != null && !value.equals("")) {
                     try {
-                        columns[i].addColumnValue(
-                            new BigDecimal(station),
-                            new BigDecimal(nf.parse(value).doubleValue()));
+                        this.columns[i].addColumnValue(
+                                station,
+                                AbstractParser.parseDecimal(value));
                     }
-                    catch (ParseException pe) {
+                    catch (final ParseException pe) {
                         log.warn("Could not parse value: '" + value + "'");
                     }
                 }
             }
         }
-        catch (ParseException pe) {
+        catch (final ParseException pe) {
             log.warn("Could not parse station: '" + line + "'");
         }
     }
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -19,16 +19,15 @@
 import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.importer.ImportRange;
 import org.dive4elements.river.importer.ImportTimeInterval;
 import org.dive4elements.river.importer.ImportUnit;
-
-import org.dive4elements.river.importer.ImportRange;
 import org.dive4elements.river.importer.ImportWst;
 import org.dive4elements.river.importer.ImportWstColumn;
 import org.dive4elements.river.importer.ImportWstColumnValue;
 import org.dive4elements.river.importer.ImportWstQRange;
-import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.importer.common.AbstractParser;
 
 
 /**
@@ -43,17 +42,17 @@
     private static final Logger log = Logger.getLogger(WaterlevelParser.class);
 
     private static final NumberFormat nf =
-        NumberFormat.getInstance(DEFAULT_LOCALE);
+            NumberFormat.getInstance(DEFAULT_LOCALE);
 
     private static final Pattern META_Q_RANGE =
-        Pattern.compile("Abfluss\\s\\[(.*)\\];(.*)");
+            Pattern.compile("Abfluss\\s\\[(.*)\\];(.*)");
 
     public static final Pattern META_UNIT =
-        Pattern.compile("^Einheit: \\[(.*)\\].*");
+            Pattern.compile("^Einheit: \\[(.*)\\].*");
 
-    public static final double INTERVAL_GAP = 0.00001d;
+    public static final BigDecimal INTERVAL_GAP = new BigDecimal("0.00001");
 
-    private List<ImportWst> waterlevels;
+    private final List<ImportWst> waterlevels;
 
     private ImportWst current;
 
@@ -70,18 +69,18 @@
 
 
     public WaterlevelParser() {
-        waterlevels = new ArrayList<ImportWst>();
+        this.waterlevels = new ArrayList<>();
     }
 
 
     public List<ImportWst> getWaterlevels() {
-        return waterlevels;
+        return this.waterlevels;
     }
 
 
     @Override
-    public void parse(File file) throws IOException {
-        currentDescription = file.getName();
+    public void parse(final File file) throws IOException {
+        this.currentDescription = file.getName();
 
         super.parse(file);
     }
@@ -89,64 +88,63 @@
 
     @Override
     protected void reset() {
-        currentQRange = null;
-        current       = new ImportWst(currentDescription);
-        current.setNumberColumns(1);
-        column        = current.getColumn(0);
-        column.setName(currentDescription);
-        column.setDescription(currentDescription);
+        this.currentQRange = null;
+        this.current       = new ImportWst(this.currentDescription);
+        this.current.setNumberColumns(1);
+        this.column        = this.current.getColumn(0);
+        this.column.setName(this.currentDescription);
+        this.column.setDescription(this.currentDescription);
 
         // Try to extract and set the TimeInterval.
-        Matcher m = WaterlevelDifferencesParser.YEARS_IN_COLUMN.matcher(
-            currentDescription);
+        final Matcher m = WaterlevelDifferencesParser.YEARS_IN_COLUMN.matcher(
+                this.currentDescription);
 
         if (m.matches()) {
-            int startYear = Integer.parseInt(m.group(1));
-            int endYear   = Integer.parseInt(m.group(2));
-            ImportTimeInterval time = new ImportTimeInterval(
-                DateUtil.getStartDateFromYear(startYear),
-                DateUtil.getEndDateFromYear(endYear)
-            );
-            column.setTimeInterval(time);
+            final int startYear = Integer.parseInt(m.group(1));
+            final int endYear   = Integer.parseInt(m.group(2));
+            final ImportTimeInterval time = new ImportTimeInterval(
+                    DateUtil.getStartDateFromYear(startYear),
+                    DateUtil.getEndDateFromYear(endYear)
+                    );
+            this.column.setTimeInterval(time);
         } else {
             log.debug("No time interval in column header found: "
-                + currentDescription);
+                    + this.currentDescription);
         }
 
-        current.setKind(7);
+        this.current.setKind(7);
     }
 
 
     @Override
     protected void finish() {
-        if (current != null) {
-            if (currentQRange != null) {
-                List<ImportWstColumnValue> cValues = column.getColumnValues();
+        if (this.current != null) {
+            if (this.currentQRange != null) {
+                final List<ImportWstColumnValue> cValues = this.column.getColumnValues();
                 // Set end of range to last station
                 // or expand range to minimal length in case it would be 0
                 // TODO: should otherwise be extended to
                 // (first station of next range - INTERVAL_GAP),
                 // assuming always ascending stations
-                BigDecimal lastStation = cValues.get(cValues.size() -1)
-                    .getPosition();
-                if (lastStation.compareTo(currentRange.getA()) == 0) {
-                    currentRange.setB(new BigDecimal(lastStation.doubleValue()
-                        + INTERVAL_GAP));
+                final BigDecimal lastStation = cValues.get(cValues.size() -1)
+                        .getPosition();
+                if (lastStation.compareTo(this.currentRange.getA()) == 0) {
+                    this.currentRange.setB(lastStation.add(INTERVAL_GAP));
                 }
                 else {
-                    currentRange.setB(lastStation);
+                    this.currentRange.setB(lastStation);
                 }
 
-                currentQRange.setRange(currentRange);
-                column.addColumnQRange(currentQRange);
+                this.currentQRange.setRange(this.currentRange);
+                this.column.addColumnQRange(this.currentQRange);
             }
 
-            waterlevels.add(current);
+            this.waterlevels.add(this.current);
         }
     }
 
     @Override
-    protected void handleLine(int lineNum, String line) {
+    protected void handleLine(final int lineNum, final String line) {
         if (line.startsWith(START_META_CHAR)) {
             handleMetaLine(stripMetaLine(line));
             return;
@@ -161,44 +159,44 @@
     }
 
 
-    private void handleMetaLine(String meta) {
-        Matcher m = META_UNIT.matcher(meta);
+    private void handleMetaLine(final String meta) {
+        final Matcher m = META_UNIT.matcher(meta);
 
         if (m.matches()) {
-            String unit = m.group(1);
+            final String unit = m.group(1);
             log.debug("Found unit: '" + unit + "'");
 
-            current.setUnit(new ImportUnit(unit));
+            this.current.setUnit(new ImportUnit(unit));
         }
     }
 
 
-    private boolean handleQRange(String line) {
-        Matcher m = META_Q_RANGE.matcher(line);
+    private boolean handleQRange(final String line) {
+        final Matcher m = META_Q_RANGE.matcher(line);
 
         if (m.matches()) {
-            String unitStr  = m.group(1);
-            String valueStr = m.group(2);
+            final String unitStr  = m.group(1);
+            final String valueStr = m.group(2);
             try {
-                if (currentQRange != null) {
+                if (this.currentQRange != null) {
                     // Finish off the last one.
-                    List<ImportWstColumnValue> cValues = column
-                        .getColumnValues();
+                    final List<ImportWstColumnValue> cValues = this.column
+                            .getColumnValues();
                     // Set end of range to last station.
-                    currentRange.setB(cValues.get(cValues.size() -1)
-                        .getPosition());
-                    currentQRange.setRange(currentRange);
-                    column.addColumnQRange(currentQRange);
+                    this.currentRange.setB(cValues.get(cValues.size() -1)
+                            .getPosition());
+                    this.currentQRange.setRange(this.currentRange);
+                    this.column.addColumnQRange(this.currentQRange);
                 }
-                currentQRange = new ImportWstQRange(null,
-                    new BigDecimal(nf.parse(valueStr).doubleValue()));
-                currentRange = new ImportRange();
+                this.currentQRange = new ImportWstQRange(null,
+                        AbstractParser.parseDecimal(valueStr));
+                this.currentRange = new ImportRange();
 
                 log.debug("Found new Q range: Q=" + valueStr);
 
                 return true;
             }
-            catch (ParseException pe) {
+            catch (final ParseException pe) {
                 log.warn("Unparseable Q range: '" + line + "'");
             }
         }
@@ -207,8 +205,8 @@
     }
 
 
-    private void handleDataLine(String line) {
-        String[] cols = line.split(SEPERATOR_CHAR);
+    private void handleDataLine(final String line) {
+        final String[] cols = line.split(SEPERATOR_CHAR);
 
         if (cols == null || cols.length < 2) {
             log.warn("skip invalid waterlevel line: '" + line + "'");
@@ -217,18 +215,16 @@
 
         try {
             // Store the value and remember the position for QRange, if needed.
-            Double station = nf.parse(cols[0]).doubleValue();
-            Double value   = nf.parse(cols[1]).doubleValue();
+            final BigDecimal station = AbstractParser.parseDecimal(cols[0]);
+            final BigDecimal value = AbstractParser.parseDecimal(cols[1]);
 
-            BigDecimal stationBD = new BigDecimal(station);
+            this.column.addColumnValue(station, value);
 
-            column.addColumnValue(stationBD, new BigDecimal(value));
-
-            if (currentRange.getA() == null) {
-                currentRange.setA(stationBD);
+            if (this.currentRange.getA() == null) {
+                this.currentRange.setA(station);
             }
         }
-        catch (ParseException pe) {
+        catch (final ParseException pe) {
             log.warn("Unparseable number in data row: " + line);
         }
     }
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,34 +8,28 @@
 
 package org.dive4elements.river.importer.parsers;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Arrays;
-
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.LineNumberReader;
 import java.io.InputStreamReader;
-import java.io.FileInputStream;
-
+import java.io.LineNumberReader;
+import java.math.BigDecimal;
 import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
-
-import org.dive4elements.river.backend.utils.StringUtil;
 import org.dive4elements.river.backend.utils.DateGuesser;
-
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-
-import java.math.BigDecimal;
-
-import org.dive4elements.river.importer.ImportWstQRange;
-import org.dive4elements.river.importer.ImportWstColumn;
+import org.dive4elements.river.backend.utils.StringUtil;
+import org.dive4elements.river.importer.ImportRange;
 import org.dive4elements.river.importer.ImportTimeInterval;
-import org.dive4elements.river.importer.ImportRange;
 import org.dive4elements.river.importer.ImportUnit;
 import org.dive4elements.river.importer.ImportWst;
+import org.dive4elements.river.importer.ImportWstColumn;
+import org.dive4elements.river.importer.ImportWstQRange;
 
 public class WstParser
 {
@@ -47,24 +41,24 @@
     public static final String COLUMN_DATUM      = "column-datum";
 
     public static final BigDecimal UNDEFINED_ZERO =
-        new BigDecimal(0.0);
+            new BigDecimal(0.0);
     public static final BigDecimal MIN_RANGE =
-        new BigDecimal(-Double.MAX_VALUE);
+            new BigDecimal(-Double.MAX_VALUE);
     public static final BigDecimal MAX_RANGE =
-        new BigDecimal(Double.MAX_VALUE);
+            new BigDecimal(Double.MAX_VALUE);
 
     public static final String ENCODING = "ISO-8859-1";
 
     public static final Pattern UNIT_COMMENT =
-        Pattern.compile("\\*\\s*[kK][mM]\\s+(.+)");
+            Pattern.compile("\\*\\s*[kK][mM]\\s+(.+)");
 
     public static final Pattern UNIT =
-        Pattern.compile("[^\\[]*\\[([^]]+)\\].*");
+            Pattern.compile("[^\\[]*\\[([^]]+)\\].*");
 
     public static final Pattern YEAR_INTERVAL =
-        Pattern.compile("(\\d{4})\\s*[-/]\\s*(\\d{4})");
+            Pattern.compile("(\\d{4})\\s*[-/]\\s*(\\d{4})");
 
-    public static final double INTERVAL_GAP = 0.00001d;
+    public static final BigDecimal INTERVAL_GAP = new BigDecimal("0.00001");
 
     protected ImportWst wst;
 
@@ -75,15 +69,15 @@
     public WstParser() {
     }
 
-    public WstParser(ImportWst wst) {
+    public WstParser(final ImportWst wst) {
         this.wst = wst;
     }
 
     public ImportWst getWst() {
-        return wst;
+        return this.wst;
     }
 
-    public void setWst(ImportWst wst) {
+    public void setWst(final ImportWst wst) {
         this.wst = wst;
     }
 
@@ -91,46 +85,46 @@
         public ParseException() {
         }
 
-        public ParseException(String msg) {
+        public ParseException(final String msg) {
             super(msg);
         }
     } // class ParseException
 
     /** Returns a new ImportTimeInterval with a date guessed from string. */
-    public static ImportTimeInterval guessDate(String string) {
+    public static ImportTimeInterval guessDate(final String string) {
         try {
-            Matcher m = YEAR_INTERVAL.matcher(string);
+            final Matcher m = YEAR_INTERVAL.matcher(string);
             if (m.matches()) {
                 return new ImportTimeInterval(
-                    DateGuesser.guessDate(m.group(1)),
-                    DateGuesser.guessDate(m.group(2)));
+                        DateGuesser.guessDate(m.group(1)),
+                        DateGuesser.guessDate(m.group(2)));
             }
 
             return new ImportTimeInterval(
-                DateGuesser.guessDate(string));
+                    DateGuesser.guessDate(string));
         }
-        catch (IllegalArgumentException iae) {
+        catch (final IllegalArgumentException iae) {
             log.warn("WST: String '" + string +
-                     "' could not be interpreted as valid timestamp");
+                    "' could not be interpreted as valid timestamp");
         }
         return null;
     }
 
-    public void parse(File file) throws IOException, ParseException {
+    public void parse(final File file) throws IOException, ParseException {
 
         log.info("Parsing WST file '" + file + "'");
 
-        if (wst == null) {
-            wst = new ImportWst(file.getName());
+        if (this.wst == null) {
+            this.wst = new ImportWst(file.getName());
         }
         else {
-            wst.setDescription(file.getName());
+            this.wst.setDescription(file.getName());
         }
 
-        LineNumberReader in =
-            new LineNumberReader(
-            new InputStreamReader(
-            new FileInputStream(file), ENCODING));
+        final LineNumberReader in =
+                new LineNumberReader(
+                        new InputStreamReader(
+                                new FileInputStream(file), ENCODING));
         try {
             String input;
             boolean first = true;
@@ -158,7 +152,7 @@
             String einheit = "m ü. unbekannte Referenz";
             boolean unitFound = false;
 
-            HashSet<BigDecimal> kms = new HashSet<BigDecimal>();
+            final HashSet<BigDecimal> kms = new HashSet<>();
 
             while ((input = in.readLine()) != null) {
                 String line = input;
@@ -170,13 +164,13 @@
                         columnCount = Integer.parseInt(line);
                         if (columnCount <= 0) {
                             throw new NumberFormatException(
-                                "number of columns <= 0");
+                                    "number of columns <= 0");
                         }
                         log.debug("Number of columns: " + columnCount);
-                        wst.setNumberColumns(columnCount);
+                        this.wst.setNumberColumns(columnCount);
                         lsBezeichner = new String[columnCount];
                     }
-                    catch (NumberFormatException nfe) {
+                    catch (final NumberFormatException nfe) {
                         log.warn("WST: invalid number.", nfe);
                         continue;
                     }
@@ -188,15 +182,15 @@
 
                 // handle Q-lines
                 if (line.startsWith("*\u001f")) {
-                    BigDecimal [] data = parseLineAsDouble(
-                        line, columnCount, false, true);
+                    final BigDecimal [] data = parseLineAsDouble(
+                            line, columnCount, false, true);
 
                     if (aktAbfluesse != null) {
                         // add Q-ranges obtained from previous lines
                         if (kmHist1 != null && kmHist2 != null
-                        && kmHist1.compareTo(kmHist2) < 0) {
+                                && kmHist1.compareTo(kmHist2) < 0) {
                             // stations descending in file
-                            BigDecimal t = minKm; minKm = maxKm; maxKm = t;
+                            final BigDecimal t = minKm; minKm = maxKm; maxKm = t;
                         }
                         addInterval(minKm, maxKm, aktAbfluesse);
                         minKm = MAX_RANGE;
@@ -216,7 +210,7 @@
                     // remember Q-values from first Q-line
                     // for header generation
                     if (firstAbfluesse == null) {
-                        firstAbfluesse = (BigDecimal [])aktAbfluesse.clone();
+                        firstAbfluesse = aktAbfluesse.clone();
                     }
                     continue;
                 }
@@ -231,7 +225,7 @@
 
                     if (spezial.startsWith(COLUMN_BEZ_TEXT)) {
                         spezial = spezial.substring(
-                            COLUMN_BEZ_TEXT.length()).trim();
+                                COLUMN_BEZ_TEXT.length()).trim();
                         if (spezial.length() == 0) {
                             continue;
                         }
@@ -239,13 +233,13 @@
                     }
                     else if (spezial.startsWith(COLUMN_BEZ_BREITE)) {
                         spezial = spezial.substring(
-                            COLUMN_BEZ_BREITE.length()).trim();
+                                COLUMN_BEZ_BREITE.length()).trim();
 
                         if (spezial.length() == 0) {
                             continue;
                         }
 
-                        String[] split = spezial.split("\\s+");
+                        final String[] split = spezial.split("\\s+");
 
                         colNaWidths = new int[split.length];
                         for (int i=0; i < split.length; i++) {
@@ -254,7 +248,7 @@
                     }
                     else if (spezial.startsWith(COLUMN_QUELLE)) {
                         spezial = spezial.substring(
-                            COLUMN_QUELLE.length()).trim();
+                                COLUMN_QUELLE.length()).trim();
                         if (spezial.length() == 0) {
                             continue;
                         }
@@ -263,7 +257,7 @@
                     }
                     else if (spezial.startsWith(COLUMN_DATUM)) {
                         spezial = spezial.substring(
-                            COLUMN_DATUM.length()).trim();
+                                COLUMN_DATUM.length()).trim();
                         if (spezial.length() == 0) {
                             continue;
                         }
@@ -283,7 +277,7 @@
                         log.debug("unit comment found");
                         // XXX: This hack is needed because desktop
                         // FLYS is broken figuring out the unit
-                        String [] units = m.group(1).split("\\s{2,}");
+                        final String [] units = m.group(1).split("\\s{2,}");
                         m = UNIT.matcher(units[0]);
                         einheit = m.matches() ? m.group(1) : units[0];
                         log.debug("unit: " + einheit);
@@ -296,69 +290,69 @@
                 if (firstAbfluesse != null) {
                     if (!columnHeaderChecked) {
                         int unknownCount = 0;
-                        HashSet<String> uniqueColumnNames =
-                            new HashSet<String>();
+                        final HashSet<String> uniqueColumnNames =
+                                new HashSet<>();
                         if (langBezeichner != null) {
                             // use column name from '*!column-bez-text'-line
                             lsBezeichner = StringUtil.fitArray(
-                                langBezeichner, lsBezeichner);
+                                    langBezeichner, lsBezeichner);
                         }
                         for (int i = 0; i < lsBezeichner.length; ++i) {
                             if (lsBezeichner[i] == null
-                            || lsBezeichner[i].length() == 0) {
+                                    || lsBezeichner[i].length() == 0) {
                                 // generate alternative column names
-                                double q = firstAbfluesse.length > i ?
-                                    firstAbfluesse[i].doubleValue() : 0d;
-                                if (q < 0.001) {
-                                    lsBezeichner[i] =
-                                        "<unbekannt #" + unknownCount + ">";
-                                    ++unknownCount;
-                                }
-                                else {
-                                    lsBezeichner[i] = "Q="+format(q);
-                                }
+                                final double q = firstAbfluesse.length > i ?
+                                        firstAbfluesse[i].doubleValue() : 0d;
+                                        if (q < 0.001) {
+                                            lsBezeichner[i] =
+                                                    "<unbekannt #" + unknownCount + ">";
+                                            ++unknownCount;
+                                        }
+                                        else {
+                                            lsBezeichner[i] = "Q="+format(q);
+                                        }
                             }
                             String candidate = lsBezeichner[i];
                             int collision = 1;
                             while (!uniqueColumnNames.add(candidate)) {
                                 candidate = lsBezeichner[i] +
-                                    " (" + collision + ")";
+                                        " (" + collision + ")";
                                 ++collision;
                             }
-                            ImportWstColumn iwc = wst.getColumn(i);
+                            final ImportWstColumn iwc = this.wst.getColumn(i);
                             iwc.setName(candidate);
                             if (quellen != null && i < quellen.length) {
                                 iwc.setSource(quellen[i]);
                             }
-                            String potentialDate =
-                                daten != null && i < daten.length
-                                ? daten[i]
-                                : candidate;
-                            iwc.setTimeInterval(guessDate(potentialDate));
+                            final String potentialDate =
+                                    daten != null && i < daten.length
+                                    ? daten[i]
+                                            : candidate;
+                                    iwc.setTimeInterval(guessDate(potentialDate));
                         }
                         columnHeaderChecked = true;
                     }
 
-                    BigDecimal [] data = parseLineAsDouble(
-                        line, columnCount, true, false);
+                    final BigDecimal [] data = parseLineAsDouble(
+                            line, columnCount, true, false);
 
-                    BigDecimal kaem = data[0];
+                    final BigDecimal kaem = data[0];
 
                     if (!kms.add(kaem)) {
                         log.warn(
-                            "WST: km " + kaem +
-                            " (line " + in.getLineNumber() +
-                            ") found more than once. -> ignored");
+                                "WST: km " + kaem +
+                                " (line " + in.getLineNumber() +
+                                ") found more than once. -> ignored");
                         continue;
                     }
 
                     // check consistence of station ordering in file
                     if (kmHist2 != null &&
-                        kmHist2.compareTo(kmHist1) != kmHist1.compareTo(kaem)
-                    ) {
+                            kmHist2.compareTo(kmHist1) != kmHist1.compareTo(kaem)
+                            ) {
                         throw new ParseException("WST: Stations in " + file +
-                            " near line " + in.getLineNumber() +
-                            " not ordered. File rejected.");
+                                " near line " + in.getLineNumber() +
+                                " not ordered. File rejected.");
                     }
 
                     // remember stations in two previous lines
@@ -385,25 +379,25 @@
                     }
                     else if (colNaWidths != null) {
                         for (int j = 0, i = 0, N = input.length();
-                             j < colNaWidths.length && i < N;
-                             i += colNaWidths[j++]
-                        ) {
+                                j < colNaWidths.length && i < N;
+                                i += colNaWidths[j++]
+                                ) {
                             lsBezeichner[j] = input.substring(
-                                i, i+colNaWidths[j]).trim();
+                                    i, i+colNaWidths[j]).trim();
                         }
                     }
                     else { // fetch column names from non-comment header line
-                           // (above first Qs)
+                        // (above first Qs)
                         // first column begins at position 8 in line
                         for (int i = 8, col = 0; i < input.length(); i += 9) {
                             // one column header is 9 chars wide
                             // but the last one may be shorter
                             if (col < lsBezeichner.length) {
                                 lsBezeichner[col++] =
-                                    input.substring(
-                                        i,
-                                        Math.min(i + 9, input.length())
-                                    ).trim();
+                                        input.substring(
+                                                i,
+                                                Math.min(i + 9, input.length())
+                                                ).trim();
                             }
                             if (col == lsBezeichner.length) {
                                 break;
@@ -417,16 +411,16 @@
             if (!unitFound) {
                 log.warn("no unit and height reference found. Using default.");
             }
-            wst.setUnit(new ImportUnit(einheit));
+            this.wst.setUnit(new ImportUnit(einheit));
 
             // add Q-ranges obtained from previous lines
             // in case there was no further Q-line
             // but only if there were values following the last Q-line
             if (minKm != MAX_RANGE && maxKm != MIN_RANGE) {
                 if (kmHist1 != null && kmHist2 != null
-                && kmHist1.compareTo(kmHist2) < 0) {
+                        && kmHist1.compareTo(kmHist2) < 0) {
                     // stations descending in file
-                    BigDecimal t = minKm; minKm = maxKm; maxKm = t;
+                    final BigDecimal t = minKm; minKm = maxKm; maxKm = t;
                 }
                 addInterval(minKm, maxKm, aktAbfluesse);
             }
@@ -436,9 +430,9 @@
         }
     }
 
-    protected void addValue(BigDecimal km, BigDecimal w, int index) {
+    protected void addValue(final BigDecimal km, final BigDecimal w, final int index) {
         if (w != null) {
-            ImportWstColumn column = wst.getColumn(index);
+            final ImportWstColumn column = this.wst.getColumn(index);
             column.addColumnValue(km, w);
         }
     }
@@ -446,21 +440,20 @@
     private static final NumberFormat NF = getNumberFormat();
 
     private static final NumberFormat getNumberFormat() {
-        NumberFormat nf = NumberFormat.getInstance();
+        final NumberFormat nf = NumberFormat.getInstance();
         nf.setMinimumFractionDigits(2);
         nf.setMaximumFractionDigits(2);
         return nf;
     }
 
-    protected static String format(double value) {
+    protected static String format(final double value) {
         return NF.format(value);
     }
 
     protected void addInterval(
-        BigDecimal    from,
-        BigDecimal    to,
-        BigDecimal [] values
-    ) {
+            final BigDecimal from,
+            BigDecimal to,
+            final BigDecimal[] values) {
         log.debug("addInterval: " + from + " " + to);
 
         if (values == null || from == MAX_RANGE || from == MIN_RANGE) {
@@ -469,55 +462,52 @@
 
         // expand single-line i.e. 0-lenght Q-range to minimal length
         if (from == to) {
-            if (lastRange != null && lastA > lastB) {
-                to = new BigDecimal(from.doubleValue() - INTERVAL_GAP);
+            if (this.lastRange != null && this.lastA > this.lastB) {
+                to = from.subtract(INTERVAL_GAP);
             }
             else {
-                to = new BigDecimal(from.doubleValue() + INTERVAL_GAP);
+                to = from.add(INTERVAL_GAP);
             }
         }
 
-        ImportRange range = new ImportRange(from, to);
+        final ImportRange range = new ImportRange(from, to);
 
         // little workaround to make the q ranges tightly fit.
         // Leave a very small gap to ensure that the range queries
         // still work.
 
-        if (lastRange != null) {
-            double a2 = range.getA().doubleValue();
-            double b2 = range.getB().doubleValue();
-
-            if (lastA < lastB) {
-                lastRange.setB(new BigDecimal(a2 - INTERVAL_GAP));
+        if (this.lastRange != null) {
+            if (this.lastA < this.lastB) {
+                this.lastRange.setB(range.getA().subtract(INTERVAL_GAP));
             }
             else { // lastA >= lastB
-                lastRange.setA(new BigDecimal(b2 + INTERVAL_GAP));
+                this.lastRange.setA(range.getB().add(INTERVAL_GAP));
             }
         }
 
         for (int i = 0; i < values.length; ++i) {
-            ImportWstColumn column = wst.getColumn(i);
-            ImportWstQRange wstQRange = new ImportWstQRange(range, values[i]);
+            final ImportWstColumn column = this.wst.getColumn(i);
+            final ImportWstQRange wstQRange = new ImportWstQRange(range, values[i]);
             column.addColumnQRange(wstQRange);
         }
 
-        lastA = from.doubleValue();
-        lastB = to.doubleValue();
-        lastRange = range;
+        this.lastA = from.doubleValue();
+        this.lastB = to.doubleValue();
+        this.lastRange = range;
     }
 
     private static final BigDecimal [] parseLineAsDouble(
-        String  line,
-        int     count,
-        boolean bStation,
-        boolean bParseEmptyAsZero
-    ) throws ParseException {
-        String [] tokens = parseLine(line, count, bStation);
+            final String  line,
+            final int     count,
+            final boolean bStation,
+            final boolean bParseEmptyAsZero
+            ) throws ParseException {
+        final String [] tokens = parseLine(line, count, bStation);
 
-        BigDecimal [] doubles = new BigDecimal[tokens.length];
+        final BigDecimal [] doubles = new BigDecimal[tokens.length];
 
         for (int i = 0; i < doubles.length; ++i) {
-            String token = tokens[i].trim();
+            final String token = tokens[i].trim();
             if (token.length() != 0) {
                 doubles[i] = new BigDecimal(token);
             }
@@ -530,11 +520,11 @@
     }
 
     private static String [] parseLine(
-        String  line,
-        int     tokenCount,
-        boolean bParseStation
-    ) throws ParseException {
-        ArrayList<String> strings = new ArrayList<String>();
+            final String  line,
+            final int     tokenCount,
+            final boolean bParseStation
+            ) throws ParseException {
+        final ArrayList<String> strings = new ArrayList<>();
 
         if (bParseStation) {
             if (line.length() < 8) {
@@ -550,7 +540,7 @@
                 break;
             }
             strings.add(line.substring(pos,
-                Math.min(pos + 8, line.length())));
+                    Math.min(pos + 8, line.length())));
         }
 
         return strings.toArray(new String[strings.size()]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/SInfoImporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,199 @@
+/* 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.importer.sinfo;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.ImportParser;
+import org.dive4elements.river.importer.sinfo.parsers.BedMobilityParser;
+import org.dive4elements.river.importer.sinfo.parsers.ChannelParser;
+import org.dive4elements.river.importer.sinfo.parsers.CollisionParser;
+import org.dive4elements.river.importer.sinfo.parsers.DailyDischargeParser;
+import org.dive4elements.river.importer.sinfo.parsers.DepthEvolutionParser;
+import org.dive4elements.river.importer.sinfo.parsers.FlowDepthParser;
+import org.dive4elements.river.importer.sinfo.parsers.InfrastructureParser;
+import org.dive4elements.river.importer.sinfo.parsers.SelectedAdditionalParser;
+import org.dive4elements.river.importer.sinfo.parsers.TkhParser;
+
+/**
+ * Import all S-INFO files of a river from its import directory and subdirectories<br />
+ * <br />
+ * Requires river and its gauges to exist in the database already
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class SInfoImporter
+{
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(SInfoImporter.class);
+
+    private static final String SINFO_DIR = "Schifffahrt";
+
+    private enum SInfoDirName {
+        BASICS("Basisdaten"), //
+        SELECTED_ADDITIONAL("Selektierte_Zusaetzliche_Laengsschnitte"), //
+        INFRASTRUCTURE("Infrastrukturen_BWaStr"), //
+        CHANNEL("Zu_gewaehrleistende_Fahrrinnenverhaeltnisse"), //
+        COLLISION_EINZEL("Grundberuehrungen" + File.separator + "Einzeljahre"), //
+        TKH_NATUR("Transportkoerperhoehen" + File.separator + "Naturmessungen"), //
+        TKH_BERECHNUNG("Transportkoerperhoehen" + File.separator + "Berechnungsergebnisse"), //
+        FLOW_DEPTH("Modellierte_Datensaetze" + File.separator + "Fliesstiefen"), //
+        DEPTH_EVOLUTION_AKTUELL("Fliesstiefenentwicklung" + File.separator + "Bezug_aktueller_GlW"), //
+        DEPTH_EVOLUTION_ETAPPEN("Fliesstiefenentwicklung" + File.separator + "GlW-Etappen");
+
+        private final String dirname;
+
+        SInfoDirName(final String dirname) {
+            this.dirname = dirname;
+        }
+
+        public String getDir() {
+            return this.dirname;
+        }
+        public File getFile() {
+            return new File(getDir());
+        }
+
+        public File buildPath(final File rootDir) {
+            return new File(rootDir, getDir());
+        }
+    }
+
+    /**
+     * Series of river's stations with bed mobility flag.
+     */
+    private final List<ImportParser> parsers;
+
+    /**
+     * Path of the S-INFO data directory of the importing river.
+     */
+    private File rootDir;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public SInfoImporter() {
+        this.parsers = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Inits the parser list regarding the skip flags.
+     */
+    public void setup(final File riverDir, final ImportRiver river) {
+        this.rootDir = new File(riverDir, SINFO_DIR);
+        log.info("Parse S-INFO files from " + this.rootDir);
+        this.parsers.clear();
+        if (!BedMobilityParser.shallSkip()) {
+            if (!this.parsers.addAll(BedMobilityParser.createParsers(SInfoDirName.BASICS.buildPath(this.rootDir), SInfoDirName.BASICS.getFile(), river)))
+                log.info("Bed mobility: no files found");
+        }
+        else {
+            log.info("Bed mobility: skipped");
+        }
+        if (!SelectedAdditionalParser.shallSkip()) {
+            if (!this.parsers.addAll(SelectedAdditionalParser.createParsers(SInfoDirName.SELECTED_ADDITIONAL.buildPath(this.rootDir),
+                    SInfoDirName.SELECTED_ADDITIONAL.getFile(), river)))
+                log.info("Selected additionals: no files found");
+        }
+        else {
+            log.info("Selected additionals: skipped");
+        }
+        if (!InfrastructureParser.shallSkip()) {
+            if (!this.parsers.addAll(InfrastructureParser.createParsers(SInfoDirName.INFRASTRUCTURE.buildPath(this.rootDir),
+                    SInfoDirName.INFRASTRUCTURE.getFile(), river)))
+                log.info("Infrastructure: no files found");
+        }
+        else {
+            log.info("Infrastructure: skipped");
+        }
+        if (!ChannelParser.shallSkip()) {
+            if (!this.parsers.addAll(ChannelParser.createParsers(SInfoDirName.CHANNEL.buildPath(this.rootDir), SInfoDirName.CHANNEL.getFile(), river)))
+                log.info("Channel: no files found");
+        }
+        else {
+            log.info("Channel: skipped");
+        }
+        if (!CollisionParser.shallSkip()) {
+            boolean added = false;
+            added = this.parsers.addAll(CollisionParser.createParsers(SInfoDirName.COLLISION_EINZEL.buildPath(this.rootDir),
+                    SInfoDirName.COLLISION_EINZEL.getFile(), river));
+            if (!added)
+                log.info("Collision: no files found");
+        }
+        else {
+            log.info("Collision: skipped");
+        }
+        if (!DailyDischargeParser.shallSkip()) {
+            if (!this.parsers.addAll(DailyDischargeParser.createParsers(SInfoDirName.BASICS.buildPath(this.rootDir), SInfoDirName.BASICS.getFile(), river)))
+                log.info("Daily discharge: no files found");
+        }
+        else {
+            log.info("Daily discharge: skipped");
+        }
+        if (!TkhParser.shallSkip()) {
+            boolean added = false;
+            added = this.parsers.addAll(TkhParser.createParsers(SInfoDirName.TKH_NATUR.buildPath(this.rootDir),
+                    SInfoDirName.TKH_NATUR.getFile(), river));
+            added |= this.parsers.addAll(TkhParser.createParsers(SInfoDirName.TKH_BERECHNUNG.buildPath(this.rootDir),
+                    SInfoDirName.TKH_BERECHNUNG.getFile(), river));
+            if (!added)
+                log.info("Tkh: no files found");
+        }
+        else {
+            log.info("Tkh: skipped");
+        }
+        if (!FlowDepthParser.shallSkip()) {
+            if (!this.parsers.addAll(FlowDepthParser.createParsers(SInfoDirName.FLOW_DEPTH.buildPath(this.rootDir), SInfoDirName.FLOW_DEPTH.getFile(), river)))
+                log.info("FlowDepth: no files found");
+        }
+        else {
+            log.info("FlowDepth: skipped");
+        }
+        if (!DepthEvolutionParser.shallSkip()) {
+            boolean added = false;
+            added = this.parsers.addAll(DepthEvolutionParser.createParsers(SInfoDirName.DEPTH_EVOLUTION_AKTUELL.buildPath(this.rootDir),
+                    SInfoDirName.DEPTH_EVOLUTION_AKTUELL.getFile(), river));
+            added |= this.parsers.addAll(DepthEvolutionParser.createParsers(SInfoDirName.DEPTH_EVOLUTION_ETAPPEN.buildPath(this.rootDir),
+                    SInfoDirName.DEPTH_EVOLUTION_ETAPPEN.getFile(), river));
+            if (!added)
+                log.info("Depth evolution: no files found");
+        }
+        else {
+            log.info("Depth evolution: skipped");
+        }
+    }
+
+    /**
+     * Imports the files according to the active parser list
+     */
+    public void parse() throws IOException {
+        for (final ImportParser parser : this.parsers)
+            parser.parse();
+    }
+
+    /**
+     * Stores all pending import objects
+     */
+    public void store() {
+        for (final ImportParser parser : this.parsers)
+            parser.store();
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/BedMobilityKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.BedMobility;
+import org.dive4elements.river.model.sinfo.BedMobilityValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported bed mobility value of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class BedMobilityKmLineImport extends AbstractKmLineImport<BedMobility, BedMobilityValue> {
+
+    /***** FIELDS *****/
+
+    private boolean bedMoving;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public BedMobilityKmLineImport(final Double km, final boolean bedMoving) {
+        super(km.doubleValue());
+        this.bedMoving = bedMoving;
+    }
+
+    /***** METHODS *****/
+
+    public void setBedMoving(final boolean bedMoving) {
+        this.bedMoving = bedMoving;
+    }
+
+    @Override
+    protected BedMobilityValue queryValueItem(final Session session, final BedMobility parent) {
+        final Query query = session.createQuery("FROM BedMobilityValue WHERE (bedMobility=:parent) AND (station=:station)");
+        query.setParameter("parent", parent);
+        query.setParameter("station", this.station);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (BedMobilityValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected BedMobilityValue createValueItem(final BedMobility parent) {
+        return new BedMobilityValue(parent, this.station, this.bedMoving);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/BedMobilitySeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,62 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.BedMobility;
+import org.dive4elements.river.model.sinfo.BedMobilityValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported bed mobility data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class BedMobilitySeriesImport extends AbstractSeriesImport<BedMobility, BedMobilityValue, BedMobilityKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(BedMobilitySeriesImport.class);
+
+
+    /***** CONSTRUCTORS *****/
+
+    public BedMobilitySeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<BedMobility> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM BedMobility WHERE river=:river");
+        query.setParameter("river", river);
+        return query.list();
+    }
+
+
+    @Override
+    public BedMobility createSeriesItem(final River river) {
+        return new BedMobility(river, this.filename, this.kmrange_info, this.notes);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/ChannelKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,71 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.Channel;
+import org.dive4elements.river.model.sinfo.ChannelValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported channel size of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class ChannelKmLineImport extends AbstractKmLineImport<Channel, ChannelValue> {
+
+    /***** FIELDS *****/
+
+    private double width;
+
+    private double depth;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public ChannelKmLineImport(final Double km, final double width, final double depth) {
+        super(km.doubleValue());
+        this.width = width;
+        this.depth = depth;
+    }
+
+    /***** METHODS *****/
+
+    public void setWidth(final double width) {
+        this.width = width;
+    }
+
+    public void setDepth(final double depth) {
+        this.depth = depth;
+    }
+
+    @Override
+    protected ChannelValue queryValueItem(final Session session, final Channel parent) {
+        final Query query = session.createQuery("FROM ChannelValue WHERE (channel=:parent) AND (station=:station)");
+        query.setParameter("parent", parent);
+        query.setParameter("station", this.station);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (ChannelValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected ChannelValue createValueItem(final Channel parent) {
+        return new ChannelValue(parent, this.station, this.width, this.depth);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/ChannelSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,74 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.Channel;
+import org.dive4elements.river.model.sinfo.ChannelValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported channel data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class ChannelSeriesImport extends AbstractSeriesImport<Channel, ChannelValue, ChannelKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(ChannelSeriesImport.class);
+
+    private Integer year_from;
+
+    private Integer year_to;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public ChannelSeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    public void setYear_from(final Integer year_from) {
+        this.year_from = year_from;
+    }
+
+    public void setYear_to(final Integer year_to) {
+        this.year_to = year_to;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<Channel> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM Channel WHERE river=:river");
+        query.setParameter("river", river);
+        return query.list();
+    }
+
+
+    @Override
+    public Channel createSeriesItem(final River river) {
+        return new Channel(river, this.filename, this.kmrange_info, this.notes, this.year_from, this.year_to);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/CollisionKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.importer.sinfo.importitem;
+
+import java.util.Date;
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.dive4elements.river.model.sinfo.CollisionValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported collision event of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class CollisionKmLineImport extends AbstractKmLineImport<Collision, CollisionValue> {
+
+    /***** FIELDS *****/
+
+    private final CollisionTypeImport collisionType;
+
+    private final Date eventDate;
+
+    private final String gaugeName;
+
+    private final double gaugeW;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public CollisionKmLineImport(final Double km, final CollisionTypeImport collisionType, final Date eventDate, final String gaugeName, final double gaugeW) {
+        super(km.doubleValue());
+        this.collisionType = collisionType;
+        this.eventDate = eventDate;
+        this.gaugeName = gaugeName;
+        this.gaugeW = gaugeW;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected CollisionValue queryValueItem(final Session session, final Collision parent) {
+        final Query query = session.createQuery("FROM CollisionValue WHERE (collision=:parent) AND (eventDate=:eventdate)"
+                + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+        query.setParameter("parent", parent);
+        query.setParameter("station", this.station);
+        query.setParameter("eventdate", this.eventDate);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (CollisionValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected CollisionValue createValueItem(final Collision parent) {
+        return new CollisionValue(parent, this.station, this.collisionType.getPeer(), this.eventDate, this.gaugeName, this.gaugeW);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/CollisionSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,69 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.dive4elements.river.model.sinfo.CollisionValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported collision data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class CollisionSeriesImport extends AbstractSeriesImport<Collision, CollisionValue, CollisionKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(CollisionSeriesImport.class);
+
+    private int year;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public CollisionSeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    public void setYear(final int year) {
+        this.year = year;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<Collision> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM Collision WHERE river=:river AND lower(filename)=:filename");
+        query.setParameter("river", river);
+        query.setParameter("filename", this.filename.toLowerCase());
+        return query.list();
+    }
+
+
+    @Override
+    public Collision createSeriesItem(final River river) {
+        return new Collision(river, this.filename, this.kmrange_info, this.notes, this.year);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/CollisionTypeImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,83 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImporterSession;
+import org.dive4elements.river.model.sinfo.CollisionType;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported collision type
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class CollisionTypeImport implements Comparable<CollisionTypeImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(CollisionTypeImport.class);
+
+    protected String name;
+
+    protected CollisionType peer;
+
+    /***** CONSTRUCTOR *****/
+
+    public CollisionTypeImport() {
+    }
+
+    public CollisionTypeImport(final String name) {
+        this.name = name;
+    }
+
+    /***** METHODS *****/
+
+    @Override
+    public int compareTo(final CollisionTypeImport other) {
+        return this.name.compareTo(other.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public CollisionType getPeer() {
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM CollisionType WHERE lower(name)=:name");
+        query.setParameter("name", this.name.trim().toLowerCase());
+        final List<CollisionType> types = query.list();
+        if (types.isEmpty()) {
+            this.peer = new CollisionType(this.name);
+            session.save(this.peer);
+            log.info(String.format("Create new database instance: %d, '%s'", this.peer.getId(), this.name));
+        }
+        else {
+            this.peer = types.get(0);
+        }
+        return this.peer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/DailyDischargeDayLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.importer.sinfo.importitem;
+
+import java.util.Date;
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.DailyDischarge;
+import org.dive4elements.river.model.sinfo.DailyDischargeValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported daily discharge of a gauge.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class DailyDischargeDayLineImport extends AbstractKmLineImport<DailyDischarge, DailyDischargeValue> {
+
+    /***** FIELDS *****/
+
+    private final Date day;
+
+    private final Double discharge;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public DailyDischargeDayLineImport(final Date day, final Double discharge) {
+        super(Double.NaN);
+        this.day = day;
+        this.discharge = discharge;
+    }
+
+    /***** METHODS *****/
+
+    @Override
+    protected DailyDischargeValue queryValueItem(final Session session, final DailyDischarge parent) {
+        final Query query = session.createQuery("FROM DailyDischargeValue WHERE (DailyDischarge=:parent) AND (day=:day)");
+        query.setParameter("parent", parent);
+        query.setParameter("day", this.day);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (DailyDischargeValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected DailyDischargeValue createValueItem(final DailyDischarge parent) {
+        return new DailyDischargeValue(parent, this.day, this.discharge);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/DailyDischargeSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,93 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.DailyDischarge;
+import org.dive4elements.river.model.sinfo.DailyDischargeValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported daily discharge value series of a gauge
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class DailyDischargeSeriesImport extends AbstractSeriesImport<DailyDischarge, DailyDischargeValue, DailyDischargeDayLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(DailyDischargeSeriesImport.class);
+
+    private String gaugeName;
+
+    private long gaugeNumber;
+
+    private Gauge gauge;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DailyDischargeSeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    public String getGaugeName() {
+        return this.gaugeName;
+    }
+
+    public void setGaugeName(final String gaugeName) {
+        this.gaugeName = gaugeName;
+    }
+
+    public long getGaugeNumber() {
+        return this.gaugeNumber;
+    }
+
+    public void setGaugeNumber(final long gaugeNumber) {
+        this.gaugeNumber = gaugeNumber;
+    }
+
+    public Gauge getGauge() {
+        return this.gauge;
+    }
+
+    public void setGauge(final Gauge gauge) {
+        this.gauge = gauge;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<DailyDischarge> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM DailyDischarge WHERE gauge=:gauge");
+        query.setParameter("gauge", this.gauge);
+        return query.list();
+    }
+
+
+    @Override
+    public DailyDischarge createSeriesItem(final River river) {
+        return new DailyDischarge(this.gauge, this.filename, this.notes);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/DepthEvolutionKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,71 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.DepthEvolution;
+import org.dive4elements.river.model.sinfo.DepthEvolutionValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported depth evolution values of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class DepthEvolutionKmLineImport extends AbstractKmLineImport<DepthEvolution, DepthEvolutionValue> {
+
+    /***** FIELDS *****/
+
+    private double total_change;
+
+    private double change_per_year;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public DepthEvolutionKmLineImport(final Double km, final double total_change, final double change_per_year) {
+        super(km.doubleValue());
+        this.total_change = total_change;
+        this.change_per_year = change_per_year;
+    }
+
+    /***** METHODS *****/
+
+    public void setTotal_change(final double total_change) {
+        this.total_change = total_change;
+    }
+
+    public void setChange_per_year(final double change_per_year) {
+        this.change_per_year = change_per_year;
+    }
+
+    @Override
+    protected DepthEvolutionValue queryValueItem(final Session session, final DepthEvolution parent) {
+        final Query query = session.createQuery("FROM DepthEvolutionValue WHERE (DepthEvolution=:parent) AND (station=:station)");
+        query.setParameter("parent", parent);
+        query.setParameter("station", this.station);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (DepthEvolutionValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected DepthEvolutionValue createValueItem(final DepthEvolution parent) {
+        return new DepthEvolutionValue(parent, this.station, this.total_change, this.change_per_year);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/DepthEvolutionSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,112 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.DepthEvolution;
+import org.dive4elements.river.model.sinfo.DepthEvolution.Group;
+import org.dive4elements.river.model.sinfo.DepthEvolutionValue;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+
+/**
+ * Imported depth evolution data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class DepthEvolutionSeriesImport extends AbstractSeriesImport<DepthEvolution, DepthEvolutionValue, DepthEvolutionKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(DepthEvolutionSeriesImport.class);
+
+    private Group group;
+
+    private Integer start_year;
+
+    private Integer reference_year;
+
+    private String curr_sounding;
+
+    private String old_sounding;
+
+    private String curr_glw;
+
+    private String old_glw;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DepthEvolutionSeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    public void setGroup(final Group group) {
+        this.group = group;
+    }
+
+    public void setStart_year(final Integer start_year) {
+        this.start_year = start_year;
+    }
+
+    public void setReference_year(final Integer reference_year) {
+        this.reference_year = reference_year;
+    }
+
+    public void setCurr_sounding(final String curr_sounding) {
+        this.curr_sounding = curr_sounding;
+    }
+
+    public void setOld_sounding(final String old_sounding) {
+        this.old_sounding = old_sounding;
+    }
+
+    public void setCurr_glw(final String curr_glw) {
+        this.curr_glw = curr_glw;
+    }
+
+    public void setOld_glw(final String old_glw) {
+        this.old_glw = old_glw;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<DepthEvolution> querySeriesItem(final Session session, final River river) {
+        /*
+         * final Query query = session.createQuery("FROM DepthEvolution WHERE river=:river AND lower(filename)=:filename");
+         * query.setParameter("river", river);
+         * query.setParameter("filename", this.filename.toLowerCase());
+         */
+        final SQLQuery query = session.createSQLQuery("SELECT * FROM depth_evolution WHERE (river_id=:river) AND (lower(filename)=:filename)");
+        query.setParameter("river", river.getId());
+        query.setParameter("filename", getFilename().toLowerCase());
+        return query.list();
+    }
+
+
+    @Override
+    public DepthEvolution createSeriesItem(final River river) {
+        return new DepthEvolution(river, this.filename, this.kmrange_info, this.notes, this.start_year, this.reference_year, this.curr_sounding,
+                this.old_sounding, this.curr_glw, this.old_glw, this.group);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/FlowDepthColumnSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,118 @@
+/* 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.importer.sinfo.importitem;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.FlowDepthColumn;
+import org.dive4elements.river.model.sinfo.FlowDepthValue;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+
+/**
+ * Imported flow depth data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class FlowDepthColumnSeriesImport extends AbstractSeriesImport<FlowDepthColumn, FlowDepthValue, FlowDepthKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(FlowDepthColumnSeriesImport.class);
+
+    private int year;
+
+    private String sounding_info;
+
+    private String evaluation_by;
+
+    private final FlowDepthSeriesImport parent;
+
+    private final String colName;
+
+    private final File relativeFilePath;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public FlowDepthColumnSeriesImport(final String filename) {
+        this(filename, null, null, null);
+    }
+
+    public FlowDepthColumnSeriesImport(final String filename, final FlowDepthSeriesImport parent, final String colName, final File relativeFilePath) {
+        super(filename);
+        this.parent = parent;
+        this.colName = colName;
+        this.relativeFilePath = relativeFilePath;
+    }
+
+
+    /***** METHODS *****/
+
+    public int getYear() {
+        return this.year;
+    }
+
+    public void setYear(final int year) {
+        this.year = year;
+    }
+
+    public String getSounding_info() {
+        return this.sounding_info;
+    }
+
+    public void setSounding_info(final String sounding_info) {
+        this.sounding_info = sounding_info;
+    }
+
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<FlowDepthColumn> querySeriesItem(final Session session, final River river) {
+        /*
+         * final Query query = session.createQuery("FROM FlowDepthColumn WHERE (FlowDepth=:parent) AND lower(name)=:colname");
+         * query.setParameter("parent", this.parent.getPeer(river));
+         * query.setParameter("colname", this.colName.toLowerCase());
+         */
+        // FIXME the normal query raises a null pointer exception
+        final SQLQuery query = session.createSQLQuery("SELECT * FROM flow_depth_column WHERE (flow_depth_id=:parent) AND (lower(name)=:colname)");
+        query.setParameter("parent", this.parent.getPeer(river).getId());
+        query.setParameter("colname", this.colName.toLowerCase());
+        return query.list();
+    }
+
+
+    @Override
+    public FlowDepthColumn createSeriesItem(final River river) {
+        return new FlowDepthColumn(this.parent.getPeer(river), this.colName);
+    }
+
+    @Override
+    protected void logStoreInfo() {
+        getLog().info(String.format("Store series column '%s':;'%s'", this.colName, this.relativeFilePath));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/FlowDepthKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,65 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.FlowDepthColumn;
+import org.dive4elements.river.model.sinfo.FlowDepthValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported flow depth value of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class FlowDepthKmLineImport extends AbstractKmLineImport<FlowDepthColumn, FlowDepthValue> {
+
+    /***** FIELDS *****/
+
+    /**
+     * Flow depth in m
+     */
+    private final double depth;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public FlowDepthKmLineImport(final Double km, final double depth) {
+        super(km.doubleValue());
+        this.depth = depth;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected FlowDepthValue queryValueItem(final Session session, final FlowDepthColumn parent) {
+        final Query query = session.createQuery("FROM FlowDepthValue WHERE (FlowDepthColumn=:parent)"
+                + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+        query.setParameter("parent", parent);
+        query.setParameter("station", this.station);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (FlowDepthValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected FlowDepthValue createValueItem(final FlowDepthColumn parent) {
+        return new FlowDepthValue(parent, this.station, this.depth);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/FlowDepthSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,145 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImporterSession;
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.FlowDepth;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported flow depth data series group of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class FlowDepthSeriesImport {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(FlowDepthSeriesImport.class);
+
+    /**
+     * Name of the imported file without type extension
+     */
+    private final String filename;
+
+    private String kmrange_info;
+
+    private String notes;
+
+    private int year;
+
+    private String sounding_info;
+
+    private String evaluation_by;
+
+    private FlowDepth peer;
+
+    private StoreMode storeMode;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public FlowDepthSeriesImport(final String filename) {
+        this.filename = filename;
+    }
+
+
+    /***** METHODS *****/
+
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    public int getYear() {
+        return this.year;
+    }
+
+    public void setYear(final int year) {
+        this.year = year;
+    }
+
+    public String getSounding_info() {
+        return this.sounding_info;
+    }
+
+    public void setSounding_info(final String sounding_info) {
+        this.sounding_info = sounding_info;
+    }
+
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    public StoreMode getStoreMode() {
+        return this.storeMode;
+    }
+
+    /**
+     * Gets the model object of the data series group, inserting it into the database if not already existing
+     */
+    public FlowDepth getPeer(final River river) {
+        if (this.peer != null) {
+            this.storeMode = StoreMode.NONE;
+            return this.peer;
+        }
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final List<FlowDepth> rows = querySeriesItem(session, river);
+        if (rows.isEmpty()) {
+            log.info("Create new database instance");
+            this.peer = createSeriesItem(river);
+            session.save(this.peer);
+            this.storeMode = StoreMode.INSERT;
+        }
+        else {
+            this.peer = rows.get(0);
+            this.storeMode = StoreMode.UPDATE;
+        }
+        return this.peer;
+    }
+
+    private List<FlowDepth> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM FlowDepth WHERE river=:river AND lower(filename)=:filename");
+        query.setParameter("river", river);
+        query.setParameter("filename", this.filename.toLowerCase());
+        return query.list();
+    }
+
+    private FlowDepth createSeriesItem(final River river) {
+        return new FlowDepth(river, this.filename, this.kmrange_info, this.notes, this.year, this.sounding_info, this.evaluation_by);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/InfrastructureKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,72 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.dive4elements.river.importer.ImportAttribute;
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.Infrastructure;
+import org.dive4elements.river.model.sinfo.InfrastructureValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported infrastructure of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class InfrastructureKmLineImport extends AbstractKmLineImport<Infrastructure, InfrastructureValue> {
+
+    /***** FIELDS *****/
+
+    private double height;
+
+    private final ImportAttribute bankAttribute;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public InfrastructureKmLineImport(final Double km, final double height, final ImportAttribute bankAttribute) {
+        super(km.doubleValue());
+        this.height = height;
+        this.bankAttribute = bankAttribute;
+    }
+
+
+    /***** METHODS *****/
+
+    public void setHeight(final double height) {
+        this.height = height;
+    }
+
+    @Override
+    protected InfrastructureValue queryValueItem(final Session session, final Infrastructure parent) {
+        final Query query = session.createQuery("FROM InfrastructureValue WHERE (infrastructure=:parent) AND (attribute=:bank)"
+                + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+        query.setParameter("parent", parent);
+        query.setParameter("station", this.station);
+        query.setParameter("bank", this.bankAttribute.getPeer());
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (InfrastructureValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected InfrastructureValue createValueItem(final Infrastructure parent) {
+        return new InfrastructureValue(parent, this.station, this.bankAttribute.getPeer(), this.height);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/InfrastructureSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImportAnnotationType;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.Infrastructure;
+import org.dive4elements.river.model.sinfo.InfrastructureValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported infrastructure data series of a river and a type
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class InfrastructureSeriesImport extends AbstractSeriesImport<Infrastructure, InfrastructureValue, InfrastructureKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(InfrastructureSeriesImport.class);
+
+    private ImportAnnotationType type;
+
+    private String provider;
+
+    private String evaluation_by;
+
+    private int year;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public InfrastructureSeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    public void setType(final ImportAnnotationType type) {
+        this.type = type;
+    }
+
+    public void setProvider(final String provider) {
+        this.provider = provider;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    public void setYear(final int year) {
+        this.year = year;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<Infrastructure> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM Infrastructure WHERE river=:river AND lower(filename)=:filename");
+        query.setParameter("river", river);
+        query.setParameter("filename", this.filename.toLowerCase());
+        return query.list();
+    }
+
+
+    @Override
+    public Infrastructure createSeriesItem(final River river) {
+        return new Infrastructure(river, this.filename, this.kmrange_info, this.notes, this.type.getPeer(), this.year, this.provider, this.evaluation_by);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/TkhColumnSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,112 @@
+/* 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.importer.sinfo.importitem;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.TkhColumn;
+import org.dive4elements.river.model.sinfo.TkhValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported TKH data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class TkhColumnSeriesImport extends AbstractSeriesImport<TkhColumn, TkhValue, TkhKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(TkhColumnSeriesImport.class);
+
+    private int year;
+
+    private String sounding_info;
+
+    private String evaluation_by;
+
+    private final TkhSeriesImport parent;
+
+    private final String colName;
+
+    private final File relativeFilePath;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public TkhColumnSeriesImport(final String filename) {
+        this(filename, null, null, null);
+    }
+
+    public TkhColumnSeriesImport(final String filename, final TkhSeriesImport parent, final String colName, final File relativeFilePath) {
+        super(filename);
+        this.parent = parent;
+        this.colName = colName;
+        this.relativeFilePath = relativeFilePath;
+    }
+
+
+    /***** METHODS *****/
+
+    public int getYear() {
+        return this.year;
+    }
+
+    public void setYear(final int year) {
+        this.year = year;
+    }
+
+    public String getSounding_info() {
+        return this.sounding_info;
+    }
+
+    public void setSounding_info(final String sounding_info) {
+        this.sounding_info = sounding_info;
+    }
+
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<TkhColumn> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM TkhColumn WHERE tkh=:parent AND lower(name)=:colname");
+        query.setParameter("parent", this.parent.getPeer(river));
+        query.setParameter("colname", this.colName.toLowerCase());
+        return query.list();
+    }
+
+
+    @Override
+    public TkhColumn createSeriesItem(final River river) {
+        return new TkhColumn(this.parent.getPeer(river), this.colName);
+    }
+
+    @Override
+    protected void logStoreInfo() {
+        getLog().info(String.format("Store series column '%s':;'%s'", this.colName, this.relativeFilePath));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/TkhKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,70 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.sinfo.TkhColumn;
+import org.dive4elements.river.model.sinfo.TkhValue;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+
+/**
+ * Imported Transportkörperhöhe value of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class TkhKmLineImport extends AbstractKmLineImport<TkhColumn, TkhValue> {
+
+    /***** FIELDS *****/
+
+    /**
+     * TKH in m
+     */
+    private final double tkheight;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public TkhKmLineImport(final Double km, final double tkheight) {
+        super(km.doubleValue());
+        this.tkheight = tkheight;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected TkhValue queryValueItem(final Session session, final TkhColumn parent) {
+        /*
+         * final Query query = session.createQuery("FROM TkhValue WHERE (TkhColumn=:parent)"
+         * + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+         * query.setParameter("parent", parent);
+         * query.setParameter("station", this.station);
+         */
+        final SQLQuery query = session.createSQLQuery("SELECT * FROM tkh_values WHERE (tkh_column_id=:parent)"
+                + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+        query.setParameter("parent", parent.getId()).setParameter("station", this.station);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (TkhValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    protected TkhValue createValueItem(final TkhColumn parent) {
+        return new TkhValue(parent, this.station, this.tkheight);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/importitem/TkhSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,157 @@
+/* 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.importer.sinfo.importitem;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImporterSession;
+import org.dive4elements.river.importer.common.StoreMode;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.Tkh;
+import org.dive4elements.river.model.sinfo.Tkh.Group;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported Transportkörperhöhe data series group of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class TkhSeriesImport {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(TkhSeriesImport.class);
+
+    /**
+     * Name of the imported file without type extension
+     */
+    private final String filename;
+
+    private Group group;
+
+    private String kmrange_info;
+
+    private String notes;
+
+    private Date day;
+
+    private String sounding_info;
+
+    private String evaluation_by;
+
+    private Tkh peer;
+
+    private StoreMode storeMode;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public TkhSeriesImport(final String filename) {
+        this.filename = filename;
+    }
+
+
+    /***** METHODS *****/
+
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public Group getGroup() {
+        return this.group;
+    }
+
+    public void setGroup(final Group group) {
+        this.group = group;
+    }
+
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    public Date getDay() {
+        return this.day;
+    }
+
+    public void setDay(final Date day) {
+        this.day = day;
+    }
+
+    public String getSounding_info() {
+        return this.sounding_info;
+    }
+
+    public void setSounding_info(final String sounding_info) {
+        this.sounding_info = sounding_info;
+    }
+
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    public StoreMode getStoreMode() {
+        return this.storeMode;
+    }
+
+    /**
+     * Gets the model object of the data series group, inserting it into the database if not already existing
+     */
+    public Tkh getPeer(final River river) {
+        if (this.peer != null) {
+            this.storeMode = StoreMode.NONE;
+            return this.peer;
+        }
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final List<Tkh> rows = querySeriesItem(session, river);
+        if (rows.isEmpty()) {
+            log.info("Create new database instance");
+            this.peer = createSeriesItem(river);
+            session.save(this.peer);
+            this.storeMode = StoreMode.INSERT;
+        }
+        else {
+            this.peer = rows.get(0);
+            this.storeMode = StoreMode.UPDATE;
+        }
+        return this.peer;
+    }
+
+    private List<Tkh> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM Tkh WHERE river=:river AND lower(filename)=:filename");
+        query.setParameter("river", river);
+        query.setParameter("filename", this.filename.toLowerCase());
+        return query.list();
+    }
+
+    private Tkh createSeriesItem(final River river) {
+        return new Tkh(river, this.filename, this.kmrange_info, this.notes, this.day, this.sounding_info, this.evaluation_by, this.group);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/BedMobilityParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,89 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.sinfo.importitem.BedMobilityKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.BedMobilitySeriesImport;
+import org.dive4elements.river.model.sinfo.BedMobility;
+import org.dive4elements.river.model.sinfo.BedMobilityValue;
+
+/**
+ * Reads and parses an bed mobility file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class BedMobilityParser extends AbstractParser<BedMobility, BedMobilityValue, BedMobilityKmLineImport, BedMobilitySeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(BedMobilityParser.class);
+
+    private static final String MOBILE_KEYWORD = "mobil";
+
+    private static final String IMPORT_FILENAME = "Einteilung_der_Gewaessersohle.csv";
+
+
+    /***** CONSTRUCTORS *****/
+
+    public BedMobilityParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoBedMobility();
+    }
+
+    /**
+     * Creates a list of parsers for all bed mobility import files in a directory
+     */
+    public static List<BedMobilityParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<BedMobilityParser> parsers = new ArrayList<>();
+        final File importFile = new File(importDir, IMPORT_FILENAME);
+        if (importFile.exists())
+            parsers.add(new BedMobilityParser(importFile, new File(relativeDir, IMPORT_FILENAME), river));
+        return parsers;
+    }
+
+    @Override
+    protected BedMobilitySeriesImport createSeriesImport(final String filename) {
+        return new BedMobilitySeriesImport(filename);
+    }
+
+    @Override
+    protected BedMobilityKmLineImport createKmLineImport(final Double km, final String[] values) {
+        return new BedMobilityKmLineImport(km, values[1].equalsIgnoreCase(MOBILE_KEYWORD));
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        return super.handleMetaOther();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/ChannelParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,151 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.ChannelKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.ChannelSeriesImport;
+import org.dive4elements.river.model.sinfo.Channel;
+import org.dive4elements.river.model.sinfo.ChannelValue;
+
+/**
+ * Reads and parses a channel size file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class ChannelParser extends AbstractParser<Channel, ChannelValue, ChannelKmLineImport, ChannelSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(ChannelParser.class);
+
+    private static final String IMPORT_FILENAME = "Fahrrinne.csv";
+
+    protected static final Pattern META_YEARS = Pattern.compile("^#\\sZeitraum:\\s*([12]\\d\\d\\d)*\\s*-\\s*([12]\\d\\d\\d)*.*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern WIDTH_COLUMNTITLE = Pattern.compile("Sollbreite\\s*\\[(.*)\\].*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern DEPTH_COLUMNTITLE = Pattern.compile("Solltiefe\\s*\\[(.*)\\].*", Pattern.CASE_INSENSITIVE);
+
+    private int widthColIndex;
+
+    private int depthColIndex;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public ChannelParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+        this.widthColIndex = -1;
+        this.depthColIndex = -1;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoChannel();
+    }
+
+    /**
+     * Creates a list of parsers for all channel import files in a directory
+     */
+    public static List<ChannelParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<ChannelParser> parsers = new ArrayList<>();
+        final File importFile = new File(importDir, IMPORT_FILENAME);
+        if (importFile.exists())
+            parsers.add(new ChannelParser(importFile, new File(relativeDir, IMPORT_FILENAME), river));
+        return parsers;
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaYears())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaYears() {
+        final Matcher m = META_YEARS.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_YEARS);
+            if (m.group(1) != null)
+                this.seriesHeader.setYear_from(Integer.valueOf(m.group(1)));
+            else
+                this.seriesHeader.setYear_from(null);
+            if (m.group(2) != null)
+                this.seriesHeader.setYear_to(Integer.valueOf(m.group(2)));
+            else
+                this.seriesHeader.setYear_to(null);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (super.handleMetaColumnTitles()) {
+            for (int i = 1; i <= this.columnTitles.size() - 1; i++) {
+                if (DEPTH_COLUMNTITLE.matcher(this.columnTitles.get(i)).matches())
+                    this.depthColIndex = i;
+                else if (WIDTH_COLUMNTITLE.matcher(this.columnTitles.get(i)).matches())
+                    this.widthColIndex = i;
+            }
+            if ((this.widthColIndex < 0) || (this.depthColIndex < 0)) {
+                logError("Columns of width and/or depth values could not be identified, missing column title 'Sollbreite...'/'Sollhöhe...'");
+                this.headerParsingState = ParsingState.STOP;
+                return false;
+            }
+            return true;
+        }
+        else
+            return false;
+    }
+
+    @Override
+    protected ChannelSeriesImport createSeriesImport(final String filename) {
+        return new ChannelSeriesImport(filename);
+    }
+
+    @Override
+    protected ChannelKmLineImport createKmLineImport(final Double km, final String[] values) {
+        if (parseDoubleWithNull(values[this.widthColIndex]) == null) {
+            logError("Invalid width value in line " + this.in.getLineNumber());
+            return null;
+        }
+        if (parseDoubleWithNull(values[this.depthColIndex]) == null) {
+            logError("Invalid depth value in line " + this.in.getLineNumber());
+            return null;
+        }
+        return new ChannelKmLineImport(km, parseDoubleWithNull(values[this.widthColIndex]).doubleValue(),
+                parseDoubleWithNull(values[this.depthColIndex]).doubleValue());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/CollisionParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,193 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.CollisionKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.CollisionSeriesImport;
+import org.dive4elements.river.importer.sinfo.importitem.CollisionTypeImport;
+import org.dive4elements.river.model.sinfo.Collision;
+import org.dive4elements.river.model.sinfo.CollisionType;
+import org.dive4elements.river.model.sinfo.CollisionValue;
+
+/**
+ * Reads and parses a collision file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class CollisionParser extends AbstractParser<Collision, CollisionValue, CollisionKmLineImport, CollisionSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(CollisionParser.class);
+
+    private static final Pattern META_YEAR = Pattern.compile("^#\\sJahr:\\s*([12]\\d\\d\\d).*", Pattern.CASE_INSENSITIVE);
+
+    private enum ColTitlePattern {
+        DATE("Datum.*"), //
+        GAUGE_W("Pegelstand\\s*\\[(.*)\\].*"), //
+        GAUGE_NAME("Bezugspegel.*"), //
+        TYPE("Unfallart.*");
+
+        private final Pattern pattern;
+
+        ColTitlePattern(final String regexp) {
+            this.pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
+        }
+
+        public Pattern getPattern() {
+            return this.pattern;
+        }
+    }
+
+    private static final DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
+
+    private final EnumMap<ColTitlePattern, Integer> cols = new EnumMap<>(ColTitlePattern.class);
+
+    private final HashMap<String, CollisionTypeImport> types;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public CollisionParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+        this.types = new HashMap<>();
+        for (final CollisionType type : CollisionType.getTypes())
+            this.types.put(type.getName().trim().toLowerCase(), new CollisionTypeImport(type.getName()));
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoCollision();
+    }
+
+    /**
+     * Creates a list of parsers for all collision import files in a directory
+     */
+    public static List<CollisionParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<CollisionParser> parsers = new ArrayList<>();
+        if (importDir.exists()) {
+            for (final File file : listFiles(importDir, ".csv"))
+                parsers.add(new CollisionParser(file, new File(relativeDir, file.getName()), river));
+        }
+        return parsers;
+    }
+
+    @Override
+    protected CollisionSeriesImport createSeriesImport(final String filename) {
+        return new CollisionSeriesImport(filename);
+    }
+
+    @Override
+    protected KmMode kmMode() {
+        return KmMode.DUPLICATES;
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaYear())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaYear() {
+        final Matcher m = META_YEAR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_YEAR);
+            this.seriesHeader.setYear(Integer.parseInt(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (!super.handleMetaColumnTitles())
+            return false;
+        for (final ColTitlePattern col : ColTitlePattern.values())
+            this.cols.put(col, -1);
+        for (int i = 1; i <= this.columnTitles.size() - 1; i++) {
+            for (final ColTitlePattern col : ColTitlePattern.values()) {
+                if (col.getPattern().matcher(this.columnTitles.get(i)).matches()) {
+                    this.cols.put(col, i);
+                    break;
+                }
+            }
+        }
+        if (this.cols.get(ColTitlePattern.DATE) < 0)
+            logWarning("Column of the event dates could not be identified, missing column title 'Datum'");
+        if (this.cols.get(ColTitlePattern.TYPE) < 0) {
+            logError("Column of the collision types could not be identified, missing column title 'Unfallart'");
+            this.headerParsingState = ParsingState.STOP;
+            return false;
+        }
+        if (!this.metaPatternsMatched.contains(META_YEAR)) {
+            logError("Required meta info for the year is missing");
+            this.headerParsingState = ParsingState.STOP;
+        }
+        return true;
+    }
+
+    @Override
+    protected CollisionKmLineImport createKmLineImport(final Double km, final String[] values) {
+        Date eventDate = null;
+        try {
+            eventDate = dateFormat.parse(values[this.cols.get(ColTitlePattern.DATE)]);
+        }
+        catch (final Exception e) {
+            logError("Invalid date in line " + this.in.getLineNumber());
+            return null;
+        }
+        final String typeName = values[this.cols.get(ColTitlePattern.TYPE)].trim();
+        final String typeKey = typeName.toLowerCase();
+        CollisionTypeImport type = null;
+        if (this.types.containsKey(typeKey))
+            type = this.types.get(typeKey);
+        else {
+            type = new CollisionTypeImport(typeName);
+            this.types.put(typeKey, type);
+        }
+        String gaugeName = null;
+        if (this.cols.get(ColTitlePattern.GAUGE_NAME) >= 0)
+            gaugeName = values[this.cols.get(ColTitlePattern.GAUGE_NAME)].trim();
+        double gaugeW = Double.NaN;
+        if (this.cols.get(ColTitlePattern.GAUGE_W) >= 0)
+            gaugeW = parseDoubleWithNull(values[this.cols.get(ColTitlePattern.GAUGE_W)]).doubleValue();
+        return new CollisionKmLineImport(km, type, eventDate, gaugeName, gaugeW);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/DailyDischargeParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,168 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.DailyDischargeDayLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.DailyDischargeSeriesImport;
+import org.dive4elements.river.model.sinfo.DailyDischarge;
+import org.dive4elements.river.model.sinfo.DailyDischargeValue;
+
+/**
+ * Reads and parses a daily discharge file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class DailyDischargeParser extends AbstractParser<DailyDischarge, DailyDischargeValue, DailyDischargeDayLineImport, DailyDischargeSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(DailyDischargeParser.class);
+
+    static final Pattern IMPORT_FILENAME = Pattern.compile("^(.+)_mittlerer_Tagesabfluss.csv", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_GAUGENAME = Pattern.compile("^#\\s*Stations-*Name:\\s*(\\S[^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_GAUGENUMBER = Pattern.compile("^#\\s*Stations-*Nummer:\\s*(\\S[^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_COLUMNTITLES = Pattern.compile("^#*\\s*Datum\\s*;\\s*Q.*", Pattern.CASE_INSENSITIVE);
+
+    private static final DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DailyDischargeParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoDailyDischarge();
+    }
+
+    /**
+     * Creates a list of parsers for all daily discharge import files in a directory
+     */
+    public static List<DailyDischargeParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<DailyDischargeParser> parsers = new ArrayList<>();
+        if (importDir.exists()) {
+            final File[] files = importDir.listFiles(new FilenameFilter() {
+                @Override
+                public boolean accept(final File dir, final String name) {
+                    return IMPORT_FILENAME.matcher(name).matches();
+                }
+            });
+            for (final File file : files)
+                parsers.add(new DailyDischargeParser(file, new File(relativeDir, file.getName()), river));
+        }
+        return parsers;
+    }
+
+    @Override
+    protected KmMode kmMode() {
+        return KmMode.NONE;
+    }
+
+    @Override
+    protected DailyDischargeSeriesImport createSeriesImport(final String filename) {
+        return new DailyDischargeSeriesImport(filename);
+    }
+
+    @Override
+    protected DailyDischargeDayLineImport createKmLineImport(final Double km, final String[] values) {
+        Date day = null;
+        try {
+            day = dateFormat.parse(values[0]);
+        }
+        catch (final Exception e) {
+            logError("Invalid date in line " + this.in.getLineNumber());
+            return null;
+        }
+        if (parseDoubleWithNull(values[1]) == null) {
+            logError("Invalid discharge value in line " + this.in.getLineNumber());
+            return null;
+        }
+        return new DailyDischargeDayLineImport(day, Double.valueOf(parseDoubleWithNull(values[1]).doubleValue()));
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaGaugeName())
+            return true;
+        else if (handleMetaGaugeNumber())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaGaugeName() {
+        final Matcher m = META_GAUGENAME.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_GAUGENAME);
+            this.seriesHeader.setGaugeName(m.group(1).trim());
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaGaugeNumber() {
+        final Matcher m = META_GAUGENUMBER.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_GAUGENUMBER);
+            this.seriesHeader.setGaugeNumber(Long.parseLong(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (!META_COLUMNTITLES.matcher(this.currentLine).matches())
+            return false;
+        this.metaPatternsMatched.add(META_COLUMNTITLES);
+        this.columnTitles.clear();
+        final String[] titles = this.currentLine.split(SEPARATOR_CHAR, 0);
+        for (int i = 0; i <= titles.length - 1; i++)
+            this.columnTitles.add(titles[i].trim());
+        this.seriesHeader.setGauge(this.river.getPeer().findGauge(this.seriesHeader.getGaugeNumber(), this.seriesHeader.getGaugeName()));
+        if (this.seriesHeader.getGauge() == null) {
+            logError("Gauge not found, file skipped");
+            this.headerParsingState = ParsingState.STOP;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/DepthEvolutionParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,230 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.DepthEvolutionKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.DepthEvolutionSeriesImport;
+import org.dive4elements.river.model.sinfo.DepthEvolution;
+import org.dive4elements.river.model.sinfo.DepthEvolutionValue;
+
+/**
+ * Reads and parses a depth evolution file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class DepthEvolutionParser extends AbstractParser<DepthEvolution, DepthEvolutionValue, DepthEvolutionKmLineImport, DepthEvolutionSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(DepthEvolutionParser.class);
+
+    protected static final Pattern META_REFERENCE_YEAR = Pattern.compile("^#\\sBezugsjahr:\\s*([12]\\d\\d\\d).*", Pattern.CASE_INSENSITIVE);
+
+    protected static final Pattern META_START_YEAR = Pattern.compile("^#\\sAusgangsjahr:\\s*([12]\\d\\d\\d).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_CURR_SOUNDING = Pattern.compile("^#\\sAktuelle Peilung\\s*/\\s*Epoche:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_OLD_SOUNDING = Pattern.compile("^#\\sHistorische Peilung\\s*/\\s*Epoche:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_CURR_WSP = Pattern.compile("^#\\sAktuelle Wasserspiegellage:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_OLD_WSP = Pattern.compile("^#\\sHistorische Wasserspiegellage:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private enum GroupDirectory {
+        NONE(DepthEvolution.Group.NONE, ""), //
+        AKTUELL(DepthEvolution.Group.AKTUELL, "Bezug_aktueller_GLW"), //
+        ETAPPE(DepthEvolution.Group.ETAPPE, "GLW-Etappen");
+
+        private final DepthEvolution.Group group;
+        private final String dirname;
+
+        GroupDirectory(final DepthEvolution.Group group, final String dirname) {
+            this.group = group;
+            this.dirname = dirname;
+        }
+
+        public DepthEvolution.Group getGroup() {
+            return this.group;
+        }
+
+        public String getDirName() {
+            return this.dirname;
+        }
+
+        public static GroupDirectory forDirName(final String dirname) {
+            for (final GroupDirectory gd : GroupDirectory.values()) {
+                if (dirname.equalsIgnoreCase(gd.getDirName()))
+                    return gd;
+            }
+            return NONE;
+        }
+    }
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DepthEvolutionParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoDepthEvolution();
+    }
+
+    /**
+     * Creates a list of parsers for all depth_evolution import files in a directory
+     */
+    public static List<DepthEvolutionParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<DepthEvolutionParser> parsers = new ArrayList<>();
+        if (importDir.exists())
+            for (final File file : listFiles(importDir, ".csv"))
+                parsers.add(new DepthEvolutionParser(file, new File(relativeDir, file.getName()), river));
+        return parsers;
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaStartYear())
+            return true;
+        else if (handleMetaReferenceYear())
+            return true;
+        else if (handleMetaCurrSounding())
+            return true;
+        else if (handleMetaOldSounding())
+            return true;
+        else if (handleMetaCurrGlw())
+            return true;
+        else if (handleMetaOldGlw())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaStartYear() {
+        final Matcher m = META_START_YEAR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_START_YEAR);
+            this.seriesHeader.setStart_year(Integer.parseInt(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaReferenceYear() {
+        final Matcher m = META_REFERENCE_YEAR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_REFERENCE_YEAR);
+            this.seriesHeader.setReference_year(Integer.parseInt(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaCurrSounding() {
+        final Matcher m = META_CURR_SOUNDING.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_CURR_SOUNDING);
+            this.seriesHeader.setCurr_sounding(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaOldSounding() {
+        final Matcher m = META_OLD_SOUNDING.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_OLD_SOUNDING);
+            this.seriesHeader.setOld_sounding(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaCurrGlw() {
+        final Matcher m = META_CURR_WSP.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_CURR_WSP);
+            this.seriesHeader.setCurr_glw(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaOldGlw() {
+        final Matcher m = META_OLD_WSP.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_OLD_WSP);
+            this.seriesHeader.setOld_glw(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (super.handleMetaColumnTitles()) {
+            if (!this.metaPatternsMatched.contains(META_START_YEAR) || !this.metaPatternsMatched.contains(META_REFERENCE_YEAR)
+                    || !this.metaPatternsMatched.contains(META_CURR_SOUNDING) || !this.metaPatternsMatched.contains(META_OLD_SOUNDING)
+                    || !this.metaPatternsMatched.contains(META_CURR_WSP) || !this.metaPatternsMatched.contains(META_OLD_WSP)) {
+                logError("One or more of the required meta infos are missing");
+                this.headerParsingState = ParsingState.STOP;
+            }
+            return true;
+        }
+        else
+            return false;
+    }
+
+    @Override
+    protected DepthEvolutionSeriesImport createSeriesImport(final String filename) {
+        final DepthEvolutionSeriesImport series = new DepthEvolutionSeriesImport(filename);
+        series.setGroup(GroupDirectory.forDirName(this.importPath.getParentFile().getName()).getGroup());
+        return series;
+    }
+
+    @Override
+    protected DepthEvolutionKmLineImport createKmLineImport(final Double km, final String[] values) {
+        if (parseDoubleWithNull(values[1]) == null) {
+            logError("Invalid total change in line " + this.in.getLineNumber());
+            return null;
+        }
+        if (parseDoubleWithNull(values[2]) == null) {
+            logError("Invalid change per year in line " + this.in.getLineNumber());
+            return null;
+        }
+        // cm to m
+        return new DepthEvolutionKmLineImport(km, parseDoubleWithNull(values[1]).doubleValue() / 100.0,
+                parseDoubleWithNull(values[2]).doubleValue() / 100.0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/FlowDepthColumnParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,84 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.FlowDepthColumnSeriesImport;
+import org.dive4elements.river.importer.sinfo.importitem.FlowDepthKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.FlowDepthSeriesImport;
+import org.dive4elements.river.model.sinfo.FlowDepthColumn;
+import org.dive4elements.river.model.sinfo.FlowDepthValue;
+
+/**
+ * Reads and parses a column of a flow depth file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class FlowDepthColumnParser extends AbstractParser<FlowDepthColumn, FlowDepthValue, FlowDepthKmLineImport, FlowDepthColumnSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(FlowDepthColumnParser.class);
+
+    private final FlowDepthSeriesImport parent;
+
+    private final int colIndex;
+
+    private final String colName;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public FlowDepthColumnParser(final File importPath, final File rootRelativePath, final ImportRiver river, final FlowDepthSeriesImport parent,
+            final int colIndex,
+            final String colName) {
+        super(importPath, rootRelativePath, river);
+        this.parent = parent;
+        this.colIndex = colIndex;
+        this.colName = colName;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    @Override
+    protected void logStartInfo() {
+        getLog().info(String.format("Start parsing column %d '%s':;'%s'", this.colIndex, this.colName, this.rootRelativePath));
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        this.headerParsingState = ParsingState.IGNORE;
+        return false;
+    }
+
+    @Override
+    protected FlowDepthColumnSeriesImport createSeriesImport(final String filename) {
+        return new FlowDepthColumnSeriesImport(filename, this.parent, this.colName, this.rootRelativePath);
+    }
+
+    @Override
+    protected FlowDepthKmLineImport createKmLineImport(final Double km, final String[] values) {
+        final double tkheight = parseDoubleWithNull(values[this.colIndex]).doubleValue();
+        return new FlowDepthKmLineImport(km, tkheight);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/FlowDepthParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,222 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.FlowDepthColumnSeriesImport;
+import org.dive4elements.river.importer.sinfo.importitem.FlowDepthKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.FlowDepthSeriesImport;
+import org.dive4elements.river.model.sinfo.FlowDepthColumn;
+import org.dive4elements.river.model.sinfo.FlowDepthValue;
+
+/**
+ * Reads and parses the header of a flow depth file and handles the parse and store of the columns
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class FlowDepthParser extends AbstractParser<FlowDepthColumn, FlowDepthValue, FlowDepthKmLineImport, FlowDepthColumnSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(FlowDepthParser.class);
+
+    private static final Pattern META_YEAR = Pattern.compile("^#\\sBezugsjahr:\\s*([12]\\d\\d\\d).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_EVALUATOR = Pattern.compile("^#\\sAuswerter:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_SOUNDING = Pattern.compile("^#\\sPeilung:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_TYPE = Pattern.compile("^#\\sTyp:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern COLUMN_TITLE = Pattern.compile("Flie((.)|(ss))tiefe\\s*\\((.+?)\\)\\s*\\[m\\].*", Pattern.CASE_INSENSITIVE);
+
+    private final FlowDepthSeriesImport tkhGroup;
+
+    private final List<FlowDepthColumnParser> colParsers;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public FlowDepthParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+        this.tkhGroup = new FlowDepthSeriesImport(importPath.getName().replaceAll("\\.csv", ""));
+        this.seriesHeader = new FlowDepthColumnSeriesImport(this.tkhGroup.getFilename(), this.tkhGroup, null, null);
+        this.colParsers = new ArrayList<>();
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoFlowDepth();
+    }
+
+    /**
+     * Creates a list of parsers for all collision import files in a directory
+     */
+    public static List<FlowDepthParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<FlowDepthParser> parsers = new ArrayList<>();
+        if (importDir.exists())
+            for (final File file : listFiles(importDir, ".csv"))
+                parsers.add(new FlowDepthParser(file, new File(relativeDir, file.getName()), river));
+        return parsers;
+    }
+
+    @Override
+    public void parse() throws IOException {
+        getLog().info("Start parsing:;'" + this.rootRelativePath + "'");
+        // this.seriesHeader = createSeriesImport(this.importPath.getName().replaceAll("\\.csv", ""));
+        this.metaPatternsMatched.clear();
+        this.kmExists.clear();
+        this.colParsers.clear();
+        this.headerParsingState = ParsingState.CONTINUE;
+        try {
+            try {
+                this.in = new LineNumberReader(new InputStreamReader(new FileInputStream(this.importPath), ENCODING));
+            }
+            catch (final Exception e) {
+                logError("Could not open (" + e.getMessage() + ")");
+                this.headerParsingState = ParsingState.STOP;
+            }
+            this.currentLine = null;
+            while (this.headerParsingState == ParsingState.CONTINUE) {
+                this.currentLine = this.in.readLine();
+                if (this.currentLine == null)
+                    break;
+                this.currentLine = this.currentLine.trim();
+                if (this.currentLine.isEmpty())
+                    continue;
+                handleMetaLine();
+            }
+        }
+        finally {
+            if (this.in != null) {
+                this.in.close();
+                this.in = null;
+            }
+        }
+        if (this.headerParsingState == ParsingState.STOP) {
+            logError("Parsing of the file stopped due to a severe error");
+            return;
+        }
+        for (final FlowDepthColumnParser colParser : this.colParsers)
+            colParser.parse();
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaYear())
+            return true;
+        else if (handleMetaType())
+            return true;
+        else if (handleMetaSounding())
+            return true;
+        else if (handleMetaEvaluator())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaYear() {
+        final Matcher m = META_YEAR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_YEAR);
+            this.tkhGroup.setYear(Integer.parseInt(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaType() {
+        final Matcher m = META_TYPE.matcher(this.currentLine);
+        return m.matches();
+    }
+
+    private boolean handleMetaSounding() {
+        final Matcher m = META_SOUNDING.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_SOUNDING);
+            this.tkhGroup.setSounding_info(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaEvaluator() {
+        final Matcher m = META_EVALUATOR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_EVALUATOR);
+            this.tkhGroup.setEvaluation_by(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (!super.handleMetaColumnTitles())
+            return false;
+        this.tkhGroup.setKmrange_info(this.seriesHeader.getKmrange_info());
+        this.tkhGroup.setNotes(this.seriesHeader.getNotes());
+        for (int i = 1; i <= this.columnTitles.size() - 1; i++) {
+            final Matcher m = COLUMN_TITLE.matcher(this.columnTitles.get(i));
+            if (m.matches())
+                this.colParsers.add(new FlowDepthColumnParser(this.importPath, this.rootRelativePath, this.river, this.tkhGroup, i, m.group(4).trim()));
+            else
+                logWarning("No title found in column " + i + ", skipped");
+        }
+        return true;
+    }
+
+    @Override
+    public void store() {
+        if (this.headerParsingState != ParsingState.STOP) {
+            this.tkhGroup.getPeer(this.river.getPeer());
+            for (final FlowDepthColumnParser colParser : this.colParsers)
+                colParser.store();
+        }
+        else
+            logWarning("Severe parsing errors, not storing series '" + this.tkhGroup.getFilename() + "'");
+    }
+
+    @Override
+    protected FlowDepthColumnSeriesImport createSeriesImport(final String filename) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected FlowDepthKmLineImport createKmLineImport(final Double km, final String[] values) {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/InfrastructureParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,219 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportAnnotationType;
+import org.dive4elements.river.importer.ImportAttribute;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.InfrastructureKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.InfrastructureSeriesImport;
+import org.dive4elements.river.model.sinfo.Infrastructure;
+import org.dive4elements.river.model.sinfo.InfrastructureValue;
+
+/**
+ * Reads and parses an infrastructure file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class InfrastructureParser extends AbstractParser<Infrastructure, InfrastructureValue, InfrastructureKmLineImport, InfrastructureSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(InfrastructureParser.class);
+
+    private static final Pattern META_TYPE = Pattern.compile("^#\\sInfrastruktur:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_PROVIDER = Pattern.compile("^#\\sDatenherkunft:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_EVALUATOR = Pattern.compile("^#\\sAuswerter:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_YEAR = Pattern.compile("^#\\sStand:\\s*([12]\\d\\d\\d).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern HEIGHT_COLUMNTITLE = Pattern.compile("((H.he)|(Hoehe))\\s*\\[(.*)\\].*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern BANK_COLUMNTITLE = Pattern.compile("Uferseite.*", Pattern.CASE_INSENSITIVE);
+
+    private static final String DB_BANK_LEFT = "links"; // TODO: improve database design to make this secure
+
+    private static final String DB_BANK_RIGHT = "rechts";
+
+    private static final String DB_BANK_NULL = "";
+
+    private int heightColIndex;
+
+    private int bankColIndex;
+
+    private final HashMap<String, ImportAttribute> bankAttributes;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public InfrastructureParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+        this.heightColIndex = -1;
+        this.bankColIndex = -1;
+        this.bankAttributes = new HashMap<>();
+        this.bankAttributes.put("links", new ImportAttribute(DB_BANK_LEFT));
+        this.bankAttributes.put("rechts", new ImportAttribute(DB_BANK_RIGHT));
+        this.bankAttributes.put("", new ImportAttribute(DB_BANK_NULL));
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoInfrastructure();
+    }
+
+    /**
+     * Creates a list of parsers for all infrastructure import files in a directory
+     */
+    public static List<InfrastructureParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<InfrastructureParser> parsers = new ArrayList<>();
+        if (importDir.exists())
+            for (final File file : listFiles(importDir, ".csv"))
+                parsers.add(new InfrastructureParser(file, new File(relativeDir, file.getName()), river));
+        return parsers;
+    }
+
+    @Override
+    protected InfrastructureSeriesImport createSeriesImport(final String filename) {
+        return new InfrastructureSeriesImport(filename);
+    }
+
+    @Override
+    protected KmMode kmMode() {
+        return KmMode.DUPLICATES;
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaType())
+            return true;
+        else if (handleMetaProvider())
+            return true;
+        else if (handleMetaEvaluator())
+            return true;
+        else if (handleMetaYear())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaType() {
+        final Matcher m = META_TYPE.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_TYPE);
+            if (this.river.getAnnotationClassifier() != null) {
+                final ImportAnnotationType type = this.river.getAnnotationClassifier().classifyDescription(m.group(1).trim(),
+                        this.river.getAnnotationClassifier().getDefaultType());
+                this.seriesHeader.setType(type);
+                log.info(String.format("Type name in file: '%s', will be assigned to database name '%s'", m.group(1).trim(), type.getName()));
+            }
+            else {
+                log.error("No annotation types file configured, cannot process type '" + m.group(1).trim() + "'");
+                this.headerParsingState = ParsingState.STOP;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaProvider() {
+        final Matcher m = META_PROVIDER.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_PROVIDER);
+            this.seriesHeader.setProvider(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaEvaluator() {
+        final Matcher m = META_EVALUATOR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_EVALUATOR);
+            this.seriesHeader.setEvaluation_by(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaYear() {
+        final Matcher m = META_YEAR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_YEAR);
+            this.seriesHeader.setYear(Integer.parseInt(m.group(1)));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (super.handleMetaColumnTitles()) {
+            for (int i = 1; i <= this.columnTitles.size() - 1; i++) {
+                if (HEIGHT_COLUMNTITLE.matcher(this.columnTitles.get(i)).matches())
+                    this.heightColIndex = i;
+                else if (BANK_COLUMNTITLE.matcher(this.columnTitles.get(i)).matches())
+                    this.bankColIndex = i;
+            }
+            if (this.bankColIndex < 0)
+                logWarning("Column of river side value could not be identified, missing column title 'Uferseite'");
+            if (this.heightColIndex < 0) {
+                logError("Column of height values could not be identified, missing column title 'Höhe...'");
+                this.headerParsingState = ParsingState.STOP;
+                return false;
+            }
+            return true;
+        }
+        else
+            return false;
+    }
+
+    @Override
+    protected InfrastructureKmLineImport createKmLineImport(final Double km, final String[] values) {
+        if (parseDoubleWithNull(values[this.heightColIndex]) == null) {
+            logError("Invalid height value in line " + this.in.getLineNumber());
+            return null;
+        }
+        if ((this.bankColIndex >= 0) && this.bankAttributes.containsKey(values[this.bankColIndex].trim().toLowerCase())) {
+            final InfrastructureKmLineImport kmLine = new InfrastructureKmLineImport(km, parseDoubleWithNull(values[this.heightColIndex]).doubleValue(),
+                    this.bankAttributes.get(values[this.bankColIndex].trim().toLowerCase()));
+            logTrace("createKmLineImport(" + km.toString() + ") => " + kmLine.getStation());
+            return kmLine;
+        }
+        else {
+            logError("Invalid bank value in line " + this.in.getLineNumber());
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/SelectedAdditionalParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,169 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.ImporterSession;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ImportParser;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.Wst;
+import org.hibernate.Query;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+
+/**
+ * Reads and parses a selected WST additionals link file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class SelectedAdditionalParser implements ImportParser {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(SelectedAdditionalParser.class);
+
+    private static final String IMPORT_FILENAME = "Zus_Laengsschnitte.txt";
+
+    private enum SelectionType {
+        WITH_Q("Q", "with discharge"), //
+        WITHOUT_Q("W", "without discharge");
+
+        private final String key;
+        private final String logText;
+
+        SelectionType(final String key, final String logText) {
+            this.key = key;
+            this.logText = logText;
+        }
+
+        public String getKey() {
+            return this.key;
+        }
+
+        public String getLogText() {
+            return this.logText;
+        }
+
+        public static SelectionType parse(final String path) {
+            if (path.toLowerCase().endsWith(".wst"))
+                return WITH_Q;
+            else
+                return WITHOUT_Q;
+        }
+    }
+
+    private final File importPath;
+
+    private final File rootRelativePath;
+
+    private final ImportRiver river;
+
+    private final HashMap<String, SelectionType> links;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public SelectedAdditionalParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        this.importPath = importPath;
+        this.rootRelativePath = rootRelativePath;
+        this.river = river;
+        this.links = new HashMap<>();
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoSelectedAdditional();
+    }
+
+    /**
+     * Creates a list of parsers for all selected additionals import files in a directory
+     */
+    public static List<SelectedAdditionalParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<SelectedAdditionalParser> parsers = new ArrayList<>();
+        final File importFile = new File(importDir, IMPORT_FILENAME);
+        if (importFile.exists())
+            parsers.add(new SelectedAdditionalParser(importFile, new File(relativeDir, IMPORT_FILENAME), river));
+        return parsers;
+    }
+
+    @Override
+    public void parse() throws IOException {
+        this.links.clear();
+        log.info("Parse '... " + this.rootRelativePath + "'");
+        LineNumberReader in = null;
+        try {
+            in = new LineNumberReader(new InputStreamReader(new FileInputStream(this.importPath), AbstractParser.ENCODING));
+            String line;
+            while (true) {
+                line = in.readLine();
+                if (line == null)
+                    break;
+                if (!line.trim().isEmpty() && !line.trim().startsWith(AbstractParser.START_META_CHAR) && !this.links.containsKey(line.trim()))
+                    this.links.put(line.trim(), SelectionType.parse(line.trim()));
+            }
+            log.info("Number of file links found: " + this.links.size());
+        }
+        finally {
+            if (in != null)
+                in.close();
+        }
+    }
+
+    @Override
+    public void store() {
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final SQLQuery reset = session.createSQLQuery("UPDATE wsts SET sinfo_selection = NULL WHERE (river_id=:river_id) AND (kind=1)"
+                + " AND (sinfo_selection IS NOT NULL)");
+        reset.setParameter("river_id", this.river.getPeer().getId());
+        reset.executeUpdate();
+        final Query query = session.createQuery("FROM Wst WHERE (river=:river) AND (kind=1) AND (lower(description) LIKE :path)");
+        query.setParameter("river", this.river.getPeer());
+        int count = 0;
+        for (final String wstfile : this.links.keySet()) {
+            count += updateWst(session, query, this.river.getPeer(), wstfile, this.links.get(wstfile));
+        }
+        log.info("Updated " + count + " wsts for selected additionals");
+    }
+
+    private int updateWst(final Session session, final Query query, final River river, final String path, final SelectionType selectionType) {
+        final String pathPattern = path.toLowerCase().replace('/', '_').replace('\\', '_');
+        query.setParameter("path", pathPattern);
+        final List<Wst> rows = query.list();
+        if (rows.isEmpty()) {
+            log.warn("Wst not found for description '" + path + "'" + ";" + this.rootRelativePath);
+            return 0;
+        } else {
+            final Wst wst = rows.get(0);
+            wst.setSInfoSelection(selectionType.getKey());
+            final Serializable id = session.save(wst);
+            return 1;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/TkhColumnParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,84 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.TkhColumnSeriesImport;
+import org.dive4elements.river.importer.sinfo.importitem.TkhKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.TkhSeriesImport;
+import org.dive4elements.river.model.sinfo.TkhColumn;
+import org.dive4elements.river.model.sinfo.TkhValue;
+
+/**
+ * Reads and parses a column of a TKH file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class TkhColumnParser extends AbstractParser<TkhColumn, TkhValue, TkhKmLineImport, TkhColumnSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(TkhColumnParser.class);
+
+    private final TkhSeriesImport parent;
+
+    private final int colIndex;
+
+    private final String colName;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public TkhColumnParser(final File importPath, final File rootRelativePath, final ImportRiver river, final TkhSeriesImport parent, final int colIndex,
+            final String colName) {
+        super(importPath, rootRelativePath, river);
+        this.parent = parent;
+        this.colIndex = colIndex;
+        this.colName = colName;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    @Override
+    protected void logStartInfo() {
+        getLog().info(String.format("Start parsing column %d '%s':;'%s'", this.colIndex, this.colName, this.rootRelativePath));
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        this.headerParsingState = ParsingState.IGNORE;
+        return false;
+    }
+
+    @Override
+    protected TkhColumnSeriesImport createSeriesImport(final String filename) {
+        return new TkhColumnSeriesImport(filename, this.parent, this.colName, this.rootRelativePath);
+    }
+
+    @Override
+    protected TkhKmLineImport createKmLineImport(final Double km, final String[] values) {
+        // convert from cm to m
+        final double tkheight = parseDoubleWithNull(values[this.colIndex]).doubleValue() / 100.0;
+        return new TkhKmLineImport(km, tkheight);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/sinfo/parsers/TkhParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,269 @@
+/* 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.importer.sinfo.parsers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.sinfo.importitem.TkhColumnSeriesImport;
+import org.dive4elements.river.importer.sinfo.importitem.TkhKmLineImport;
+import org.dive4elements.river.importer.sinfo.importitem.TkhSeriesImport;
+import org.dive4elements.river.model.sinfo.Tkh;
+import org.dive4elements.river.model.sinfo.TkhColumn;
+import org.dive4elements.river.model.sinfo.TkhValue;
+
+/**
+ * Reads and parses the header of a TKH file and handles the parse and store of the columns
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class TkhParser extends AbstractParser<TkhColumn, TkhValue, TkhKmLineImport, TkhColumnSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(TkhParser.class);
+
+    private static final Pattern META_DATUM = Pattern.compile("^#\\sDatum:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_EVALUATOR = Pattern.compile("^#\\sAuswerter:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_SOUNDING = Pattern.compile("^#\\sPeilung:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_TYPE = Pattern.compile("^#\\sTyp:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern COLUMN_TITLE = Pattern.compile("Transportk((.)|(oe))rperh((.)|(oe))he\\s*\\((.+?)\\)\\s*\\[cm\\].*", Pattern.CASE_INSENSITIVE);
+
+    private enum GroupDirectory {
+        NONE(Tkh.Group.NONE, ""), //
+        CALCULATION(Tkh.Group.CALCULATION, "Berechnungsergebnisse"), //
+        MEASUREMENT(Tkh.Group.MEASUREMENT, "Naturmessungen");
+
+        private final Tkh.Group group;
+        private final String dirname;
+
+        GroupDirectory(final Tkh.Group group, final String dirname) {
+            this.group = group;
+            this.dirname = dirname;
+        }
+
+        public Tkh.Group getGroup() {
+            return this.group;
+        }
+
+        public String getDirName() {
+            return this.dirname;
+        }
+
+        public static GroupDirectory forDirName(final String dirname) {
+            for (final GroupDirectory gd : GroupDirectory.values()) {
+                if (dirname.equalsIgnoreCase(gd.getDirName()))
+                    return gd;
+            }
+            return NONE;
+        }
+    }
+
+    private static final DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
+
+    private final TkhSeriesImport tkhGroup;
+
+    private final List<TkhColumnParser> colParsers;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public TkhParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+        this.tkhGroup = new TkhSeriesImport(importPath.getName().replaceAll("\\.csv", ""));
+        this.tkhGroup.setGroup(GroupDirectory.forDirName(this.importPath.getParentFile().getName()).getGroup());
+        this.seriesHeader = new TkhColumnSeriesImport(this.tkhGroup.getFilename(), this.tkhGroup, null, null);
+        this.colParsers = new ArrayList<>();
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipSInfoTkh();
+    }
+
+    /**
+     * Creates a list of parsers for all collision import files in a directory
+     */
+    public static List<TkhParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<TkhParser> parsers = new ArrayList<>();
+        if (importDir.exists())
+            for (final File file : listFiles(importDir, ".csv"))
+                parsers.add(new TkhParser(file, new File(relativeDir, file.getName()), river));
+        return parsers;
+    }
+
+    @Override
+    public void parse() throws IOException {
+        getLog().info("Start parsing:;'" + this.rootRelativePath + "'");
+        // this.seriesHeader = createSeriesImport(this.importPath.getName().replaceAll("\\.csv", ""));
+        this.metaPatternsMatched.clear();
+        this.kmExists.clear();
+        this.colParsers.clear();
+        this.headerParsingState = ParsingState.CONTINUE;
+        try {
+            try {
+                this.in = new LineNumberReader(new InputStreamReader(new FileInputStream(this.importPath), ENCODING));
+            }
+            catch (final Exception e) {
+                logError("Could not open (" + e.getMessage() + ")");
+                this.headerParsingState = ParsingState.STOP;
+            }
+            this.currentLine = null;
+            while (this.headerParsingState == ParsingState.CONTINUE) {
+                this.currentLine = this.in.readLine();
+                if (this.currentLine == null)
+                    break;
+                this.currentLine = this.currentLine.trim();
+                if (this.currentLine.isEmpty())
+                    continue;
+                handleMetaLine();
+            }
+        }
+        finally {
+            if (this.in != null) {
+                this.in.close();
+                this.in = null;
+            }
+        }
+        if (this.headerParsingState == ParsingState.STOP) {
+            logError("Parsing of the file stopped due to a severe error");
+            return;
+        }
+        for (final TkhColumnParser colParser : this.colParsers)
+            colParser.parse();
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaDay())
+            return true;
+        else if (handleMetaType())
+            return true;
+        else if (handleMetaSounding())
+            return true;
+        else if (handleMetaEvaluator())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaDay() {
+        final Matcher m = META_DATUM.matcher(this.currentLine);
+        if (m.matches()) {
+            Date day = null;
+            try {
+                if (!m.group(1).isEmpty())
+                    day = dateFormat.parse(m.group(1));
+            }
+            catch (final Exception e) {
+                logError("Invalid date in line " + this.in.getLineNumber());
+            }
+            this.metaPatternsMatched.add(META_DATUM);
+            this.tkhGroup.setDay(day);
+            if (day == null)
+                logWarning("No date specified");
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaType() {
+        final Matcher m = META_TYPE.matcher(this.currentLine);
+        return m.matches();
+    }
+
+    private boolean handleMetaSounding() {
+        final Matcher m = META_SOUNDING.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_SOUNDING);
+            this.tkhGroup.setSounding_info(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleMetaEvaluator() {
+        final Matcher m = META_EVALUATOR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_EVALUATOR);
+            this.tkhGroup.setEvaluation_by(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (!super.handleMetaColumnTitles())
+            return false;
+        this.tkhGroup.setKmrange_info(this.seriesHeader.getKmrange_info());
+        this.tkhGroup.setNotes(this.seriesHeader.getNotes());
+        for (int i = 1; i <= this.columnTitles.size() - 1; i++) {
+            final Matcher m = COLUMN_TITLE.matcher(this.columnTitles.get(i));
+            if (m.matches())
+                this.colParsers.add(new TkhColumnParser(this.importPath, this.rootRelativePath, this.river, this.tkhGroup, i, m.group(7).trim()));
+            else
+                logWarning("No title found in column " + i + ", skipped");
+        }
+        return true;
+    }
+
+    @Override
+    public void store() {
+        if (this.headerParsingState != ParsingState.STOP) {
+            this.tkhGroup.getPeer(this.river.getPeer());
+            for (final TkhColumnParser colParser : this.colParsers)
+                colParser.store();
+        }
+        else
+            logWarning("Severe parsing errors, not storing series '" + this.tkhGroup.getFilename() + "'");
+    }
+
+    @Override
+    protected TkhColumnSeriesImport createSeriesImport(final String filename) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected TkhKmLineImport createKmLineImport(final Double km, final String[] values) {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/UInfoImporter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,121 @@
+/* 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.importer.uinfo;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.ImportParser;
+import org.dive4elements.river.importer.uinfo.parsers.SalixParser;
+import org.dive4elements.river.importer.uinfo.parsers.VegetationParser;
+
+/**
+ * Import all U-INFO files of a river from its import directory and subdirectories<br />
+ * <br />
+ * Requires river and its gauges to exist in the database already
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class UInfoImporter
+{
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(UInfoImporter.class);
+
+    private static final String UINFO_DIR = "Oekologie";
+
+    private enum UInfoDirName {
+        BASICS("Basisdaten"), //
+        SALIX("Salix-Linie" + File.separator + "Salix-Linie"), //
+        VEGETATION("Vegetationszonen");
+
+        private final String dirname;
+
+        UInfoDirName(final String dirname) {
+            this.dirname = dirname;
+        }
+
+        public String getDir() {
+            return this.dirname;
+        }
+        public File getFile() {
+            return new File(getDir());
+        }
+
+        public File buildPath(final File rootDir) {
+            return new File(rootDir, getDir());
+        }
+    }
+
+    /**
+     * Series of river's stations with bed mobility flag.
+     */
+    private final List<ImportParser> parsers;
+
+    /**
+     * Path of the S-INFO data directory of the importing river.
+     */
+    private File rootDir;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public UInfoImporter() {
+        this.parsers = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Inits the parser list regarding the skip flags.
+     */
+    public void setup(final File riverDir, final ImportRiver river) {
+        this.rootDir = new File(riverDir, UINFO_DIR);
+        log.info("Parse U-INFO files from " + this.rootDir);
+        this.parsers.clear();
+        if (!SalixParser.shallSkip()) {
+            if (!this.parsers.addAll(SalixParser.createParsers(UInfoDirName.SALIX.buildPath(this.rootDir), UInfoDirName.SALIX.getFile(), river)))
+                log.info("Salix: no files found");
+        }
+        else {
+            log.info("Salix: skipped");
+        }
+        if (!VegetationParser.shallSkip()) {
+            if (!this.parsers.addAll(VegetationParser.createParsers(UInfoDirName.VEGETATION.buildPath(this.rootDir), UInfoDirName.VEGETATION.getFile(), river)))
+                log.info("Vegetation: no files found");
+        }
+        else {
+            log.info("Vegetation: skipped");
+        }
+    }
+
+    /**
+     * Imports the files according to the active parser list
+     */
+    public void parse() throws IOException {
+        for (final ImportParser parser : this.parsers)
+            parser.parse();
+    }
+
+    /**
+     * Stores all pending import objects
+     */
+    public void store() {
+        for (final ImportParser parser : this.parsers)
+            parser.store();
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/importitem/SalixKmLineImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,65 @@
+/* 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.importer.uinfo.importitem;
+
+import java.util.List;
+
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.uinfo.Salix;
+import org.dive4elements.river.model.uinfo.SalixValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported salix values of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class SalixKmLineImport extends AbstractKmLineImport<Salix, SalixValue> {
+
+    /***** FIELDS *****/
+
+    private final double factor;
+
+    private final double mnw_mw_diff;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public SalixKmLineImport(final Double km, final double factor, final double mnw_mw_diff) {
+        super(km.doubleValue());
+        this.factor = factor;
+        this.mnw_mw_diff = mnw_mw_diff;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    public SalixValue queryValueItem(final Session session, final Salix parent) {
+        final Query query = session.createQuery("FROM SalixValue WHERE (salix=:parent)"
+                + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+        query.setParameter("parent", parent);
+        query.setParameter("station", this.station);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (SalixValue) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    public SalixValue createValueItem(final Salix parent) {
+        return new SalixValue(parent, this.station, this.factor, this.mnw_mw_diff);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/importitem/SalixSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,69 @@
+/* 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.importer.uinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.uinfo.Salix;
+import org.dive4elements.river.model.uinfo.SalixValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported salix data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class SalixSeriesImport extends AbstractSeriesImport<Salix, SalixValue, SalixKmLineImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(SalixSeriesImport.class);
+
+    private String evaluation_by;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public SalixSeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    public void setEvaluationBy(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<Salix> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM Salix WHERE river=:river AND lower(filename)=:filename");
+        query.setParameter("river", river);
+        query.setParameter("filename", this.filename.toLowerCase());
+        return query.list();
+    }
+
+
+    @Override
+    public Salix createSeriesItem(final River river) {
+        return new Salix(river, this.filename, this.kmrange_info, this.notes, this.evaluation_by);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/importitem/VegetationSeriesImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,69 @@
+/* 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.importer.uinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractSeriesImport;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.uinfo.Vegetation;
+import org.dive4elements.river.model.uinfo.VegetationZone;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported vegetation data series of a river
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class VegetationSeriesImport extends AbstractSeriesImport<Vegetation, VegetationZone, VegetationZoneImport> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(VegetationSeriesImport.class);
+
+    private String name;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public VegetationSeriesImport(final String filename) {
+        super(filename);
+    }
+
+
+    /***** METHODS *****/
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public Logger getLog() {
+        return log;
+    }
+
+    @Override
+    public List<Vegetation> querySeriesItem(final Session session, final River river) {
+        final Query query = session.createQuery("FROM Vegetation WHERE river=:river AND lower(filename)=:filename");
+        query.setParameter("river", river);
+        query.setParameter("filename", this.filename.toLowerCase());
+        return query.list();
+    }
+
+
+    @Override
+    public Vegetation createSeriesItem(final River river) {
+        return new Vegetation(river, this.filename, this.name, this.notes);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/importitem/VegetationTypeImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,94 @@
+/* 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.importer.uinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.ImporterSession;
+import org.dive4elements.river.model.uinfo.VegetationType;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported vegetation zone type
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class VegetationTypeImport implements Comparable<VegetationTypeImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(VegetationTypeImport.class);
+
+    protected Integer id;
+
+    protected String name;
+
+    protected VegetationType peer;
+
+    /***** CONSTRUCTOR *****/
+
+    public VegetationTypeImport() {
+    }
+
+    public VegetationTypeImport(final int id) {
+        this.id = Integer.valueOf(id);
+    }
+
+    /***** METHODS *****/
+
+    @Override
+    public int compareTo(final VegetationTypeImport other) {
+        return this.id.compareTo(other.getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return this.id;
+    }
+
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public VegetationType getPeer() {
+        if (this.peer != null)
+            return this.peer;
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM VegetationType WHERE id=:id");
+        query.setParameter("id", this.id);
+        final List<VegetationType> types = query.list();
+        if (types.isEmpty()) {
+            // Type table is not modifiable by the importer
+            // this.peer = new VegetationType(this.name);
+            // session.save(this.peer);
+            // log.info(String.format("Create new database instance: %d, '%s'", this.peer.getId(), this.name));
+        }
+        else {
+            this.peer = types.get(0);
+        }
+        return this.peer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/importitem/VegetationZoneImport.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,77 @@
+/* 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.importer.uinfo.importitem;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.common.AbstractKmLineImport;
+import org.dive4elements.river.model.uinfo.Vegetation;
+import org.dive4elements.river.model.uinfo.VegetationType;
+import org.dive4elements.river.model.uinfo.VegetationZone;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Imported vegetation values of a river station.
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class VegetationZoneImport extends AbstractKmLineImport<Vegetation, VegetationZone> {
+
+    /***** FIELDS *****/
+
+    private static Logger log = Logger.getLogger(VegetationZoneImport.class);
+
+    private final VegetationTypeImport vegetationType;
+
+    private final Integer minOverflowDays;
+
+    private final Integer maxOverflowDays;
+
+
+    /***** CONSTRUCTOR *****/
+
+    public VegetationZoneImport(final int vegetationTypeId, final Integer minOverflowDays, final Integer maxOverflowDays) {
+        super(Double.NaN);
+        this.vegetationType = new VegetationTypeImport(vegetationTypeId);
+        this.minOverflowDays = minOverflowDays;
+        this.maxOverflowDays = maxOverflowDays;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    public VegetationZone queryValueItem(final Session session, final Vegetation parent) {
+        final Query query = session.createQuery("FROM VegetationZone WHERE (vegetation=:parent)"
+                + " AND (vegetationType=:type)");
+        query.setParameter("parent", parent);
+        query.setParameter("type", this.vegetationType);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (VegetationZone) rows.get(0);
+        else
+            return null;
+    }
+
+
+    @Override
+    public VegetationZone createValueItem(final Vegetation parent) {
+        final VegetationType type = this.vegetationType.getPeer();
+        if (type == null) {
+            log.error("Unknown vegetation zone class " + this.vegetationType.getId());
+            return null;
+        }
+        return new VegetationZone(parent, type, this.minOverflowDays, this.maxOverflowDays);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/parsers/SalixParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,154 @@
+/* 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.importer.uinfo.parsers;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.uinfo.importitem.SalixKmLineImport;
+import org.dive4elements.river.importer.uinfo.importitem.SalixSeriesImport;
+import org.dive4elements.river.model.uinfo.Salix;
+import org.dive4elements.river.model.uinfo.SalixValue;
+
+/**
+ * Reads and parses a salix file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class SalixParser extends AbstractParser<Salix, SalixValue, SalixKmLineImport, SalixSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(SalixParser.class);
+
+    private static final String IMPORT_FILENAME = "Salix-Linie.csv";
+
+    private static final Pattern META_EVALUATOR = Pattern.compile("^#\\sAuswerter:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private enum ColTitlePattern {
+        FACTOR("Salix.Fa.tor\\s*\\[(.*)\\].*"), //
+        MWMNW("\\(MW-MNW\\).*\\[(.*)\\].*");
+
+        private final Pattern pattern;
+
+        ColTitlePattern(final String regexp) {
+            this.pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
+        }
+
+        public Pattern getPattern() {
+            return this.pattern;
+        }
+    }
+
+    private final EnumMap<ColTitlePattern, Integer> cols = new EnumMap<>(ColTitlePattern.class);
+
+
+    /***** CONSTRUCTORS *****/
+
+    public SalixParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipUInfoSalix();
+    }
+
+    /**
+     * Creates a list of parsers for all salix import files in a directory
+     */
+    public static List<SalixParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<SalixParser> parsers = new ArrayList<>();
+        final File importFile = new File(importDir, IMPORT_FILENAME);
+        if (importFile.exists())
+            parsers.add(new SalixParser(importFile, new File(relativeDir, IMPORT_FILENAME), river));
+        return parsers;
+    }
+
+    @Override
+    protected SalixSeriesImport createSeriesImport(final String filename) {
+        return new SalixSeriesImport(filename);
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaEvaluator())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaEvaluator() {
+        final Matcher m = META_EVALUATOR.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_EVALUATOR);
+            this.seriesHeader.setEvaluationBy(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (!super.handleMetaColumnTitles())
+            return false;
+        for (final ColTitlePattern col : ColTitlePattern.values())
+            this.cols.put(col, -1);
+        for (int i = 1; i <= this.columnTitles.size() - 1; i++) {
+            for (final ColTitlePattern col : ColTitlePattern.values()) {
+                if (col.getPattern().matcher(this.columnTitles.get(i)).matches()) {
+                    this.cols.put(col, i);
+                    break;
+                }
+            }
+        }
+        if ((this.cols.get(ColTitlePattern.FACTOR) < 0) || (this.cols.get(ColTitlePattern.MWMNW) < 0)) {
+            logError("Column of the salix factor and/or mnw-mw-diff could not be identified");
+            this.headerParsingState = ParsingState.STOP;
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    protected SalixKmLineImport createKmLineImport(final Double km, final String[] values) {
+        if (Double.isNaN(parseDoubleWithNull(values[this.cols.get(ColTitlePattern.FACTOR)]).doubleValue())) {
+            logError("Salix factor not found in line " + this.in.getLineNumber());
+            return null;
+        }
+        if (Double.isNaN(parseDoubleWithNull(values[this.cols.get(ColTitlePattern.MWMNW)]).doubleValue())) {
+            logError("MNW-MW-diff not found in line " + this.in.getLineNumber());
+            return null;
+        }
+        return new SalixKmLineImport(km, parseDoubleWithNull(values[this.cols.get(ColTitlePattern.FACTOR)]).doubleValue(),
+                parseDoubleWithNull(values[this.cols.get(ColTitlePattern.MWMNW)]).doubleValue());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/importer/uinfo/parsers/VegetationParser.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,187 @@
+/* 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.importer.uinfo.parsers;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.river.importer.Config;
+import org.dive4elements.river.importer.ImportRiver;
+import org.dive4elements.river.importer.common.AbstractParser;
+import org.dive4elements.river.importer.common.ParsingState;
+import org.dive4elements.river.importer.uinfo.importitem.VegetationSeriesImport;
+import org.dive4elements.river.importer.uinfo.importitem.VegetationZoneImport;
+import org.dive4elements.river.model.uinfo.Vegetation;
+import org.dive4elements.river.model.uinfo.VegetationZone;
+
+/**
+ * Reads and parses a vegetation zones file
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class VegetationParser extends AbstractParser<Vegetation, VegetationZone, VegetationZoneImport, VegetationSeriesImport> {
+
+    /***** FIELDS *****/
+
+    private static final Logger log = Logger.getLogger(VegetationParser.class);
+
+    private static final Pattern META_NAME = Pattern.compile("^#\\sEinteilung:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern META_COLUMNTITLES = Pattern.compile("^#*\\s*Vegetationstyp\\s*;.+", Pattern.CASE_INSENSITIVE);
+
+    private enum ColTitlePattern {
+        OVERFLOW_LIMIT("((.)|(Ue))berflutungsdauer-bis\\s*\\[(.*)\\].*"), //
+        CLASSNO("Vegetationsklasse.*");
+
+        private final Pattern pattern;
+
+        ColTitlePattern(final String regexp) {
+            this.pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
+        }
+
+        public Pattern getPattern() {
+            return this.pattern;
+        }
+    }
+
+    private final EnumMap<ColTitlePattern, Integer> cols = new EnumMap<>(ColTitlePattern.class);
+
+    private int previousClassNo;
+
+    private int previousDaysLimit;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public VegetationParser(final File importPath, final File rootRelativePath, final ImportRiver river) {
+        super(importPath, rootRelativePath, river);
+        this.previousClassNo = 0;
+        this.previousDaysLimit = -1;
+    }
+
+
+    /***** METHODS *****/
+
+    @Override
+    protected Logger getLog() {
+        return log;
+    }
+
+    /**
+     * Whether this import type shall be skipped
+     */
+    public static boolean shallSkip() {
+        return Config.INSTANCE.skipUInfoVegetation();
+    }
+
+    /**
+     * Creates a list of parsers for all vegetation import files in a directory
+     */
+    public static List<VegetationParser> createParsers(final File importDir, final File relativeDir, final ImportRiver river) {
+        final List<VegetationParser> parsers = new ArrayList<>();
+        if (importDir.exists()) {
+            for (final File file : listFiles(importDir, ".csv"))
+                parsers.add(new VegetationParser(file, new File(relativeDir, file.getName()), river));
+        }
+        return parsers;
+    }
+
+    @Override
+    protected KmMode kmMode() {
+        return KmMode.NONE;
+    }
+
+    @Override
+    protected VegetationSeriesImport createSeriesImport(final String filename) {
+        return new VegetationSeriesImport(filename);
+    }
+
+    @Override
+    protected boolean handleMetaOther() {
+        if (handleMetaName())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean handleMetaName() {
+        final Matcher m = META_NAME.matcher(this.currentLine);
+        if (m.matches()) {
+            this.metaPatternsMatched.add(META_NAME);
+            this.seriesHeader.setName(parseMetaInfo(m.group(1).trim()));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean handleMetaColumnTitles() {
+        if (!META_COLUMNTITLES.matcher(this.currentLine).matches())
+            return false;
+        this.metaPatternsMatched.add(META_COLUMNTITLES);
+        this.columnTitles.clear();
+        final String[] titles = this.currentLine.split(SEPARATOR_CHAR, 0);
+        for (int i = 0; i <= titles.length - 1; i++)
+            this.columnTitles.add(titles[i].trim());
+        for (final ColTitlePattern col : ColTitlePattern.values())
+            this.cols.put(col, -1);
+        for (int i = 1; i <= this.columnTitles.size() - 1; i++) {
+            for (final ColTitlePattern col : ColTitlePattern.values()) {
+                if (col.getPattern().matcher(this.columnTitles.get(i)).matches()) {
+                    this.cols.put(col, i);
+                    break;
+                }
+            }
+        }
+        if ((this.cols.get(ColTitlePattern.OVERFLOW_LIMIT) < 0) || (this.cols.get(ColTitlePattern.CLASSNO) < 0)) {
+            logError("Column of the overflow duration limit and/or vegetation zone class could not be identified");
+            this.headerParsingState = ParsingState.STOP;
+            return true;
+        }
+        this.previousClassNo = 0;
+        this.previousDaysLimit = 0;
+        return true;
+    }
+
+    @Override
+    protected VegetationZoneImport createKmLineImport(final Double km, final String[] values) {
+        int daysLimit = 367;
+        int classNo = 0;
+        try {
+            if (!values[this.cols.get(ColTitlePattern.OVERFLOW_LIMIT)].trim().isEmpty())
+                daysLimit = Integer.parseInt(values[this.cols.get(ColTitlePattern.OVERFLOW_LIMIT)]);
+            classNo = Integer.parseInt(values[this.cols.get(ColTitlePattern.CLASSNO)]);
+        }
+        catch (final Exception e) {
+            logError("Overflow days limit and/or vegetation zone class could not be parsed: line " + this.in.getLineNumber());
+            return null;
+        }
+        // Check completeness of vegetation zone type set, if needed
+        // if (classNo != this.previousClassNo + 1) {
+        // logError("Wrong vegetation zone class number or wrong class order: line " + this.in.getLineNumber());
+        // return null;
+        // }
+        // if (!this.types.containsKey(Integer.valueOf(classNo))) {
+        // logError("Unknown vegetation zone class: line " + this.in.getLineNumber());
+        // return null;
+        // }
+        this.previousClassNo = classNo;
+        final Integer minDays = Integer.valueOf(this.previousDaysLimit);
+        this.previousDaysLimit = daysLimit + 1;
+        return new VegetationZoneImport(classNo, minDays, Integer.valueOf(this.previousDaysLimit));
+    }
+}
--- a/backend/src/main/java/org/dive4elements/river/model/Annotation.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/Annotation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,15 +10,18 @@
 
 import java.io.Serializable;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
 import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
 import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
-import javax.persistence.OneToOne;
-import javax.persistence.JoinColumn;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.model.Attribute.AttributeKey;
 
 @Entity
 @Table(name = "annotations")
@@ -36,12 +39,12 @@
     }
 
     public Annotation(
-        Range          range,
-        Attribute      attribute,
-        Position       position,
-        Edge           edge,
-        AnnotationType type
-    ) {
+            final Range          range,
+            final Attribute      attribute,
+            final Position       position,
+            final Edge           edge,
+            final AnnotationType type
+            ) {
         this.range     = range;
         this.attribute = attribute;
         this.position  = position;
@@ -51,68 +54,73 @@
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_ANNOTATIONS_ID_SEQ",
-        sequenceName   = "ANNOTATIONS_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_ANNOTATIONS_ID_SEQ",
+            sequenceName   = "ANNOTATIONS_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_ANNOTATIONS_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_ANNOTATIONS_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "range_id")
     public Range getRange() {
-        return range;
+        return this.range;
     }
 
-    public void setRange(Range range) {
+    public void setRange(final Range range) {
         this.range = range;
     }
 
     @OneToOne
     @JoinColumn(name = "attribute_id")
     public Attribute getAttribute() {
-        return attribute;
+        return this.attribute;
     }
 
-    public void setAttribute(Attribute attribute) {
+    public void setAttribute(final Attribute attribute) {
         this.attribute = attribute;
     }
 
+    @Transient
+    public AttributeKey getAttributeKey() {
+        return this.getAttribute().getKey();
+    }
+
     @OneToOne
     @JoinColumn(name = "position_id")
     public Position getPosition() {
-        return position;
+        return this.position;
     }
 
-    public void setPosition(Position position) {
+    public void setPosition(final Position position) {
         this.position = position;
     }
 
     @OneToOne
     @JoinColumn(name = "edge_id")
     public Edge getEdge() {
-        return edge;
+        return this.edge;
     }
 
-    public void setEdge(Edge edge) {
+    public void setEdge(final Edge edge) {
         this.edge = edge;
     }
 
     @OneToOne
     @JoinColumn(name = "type_id")
     public AnnotationType getType() {
-        return type;
+        return this.type;
     }
 
-    public void setType(AnnotationType type) {
+    public void setType(final AnnotationType type) {
         this.type = type;
     }
 }
--- a/backend/src/main/java/org/dive4elements/river/model/AnnotationType.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/AnnotationType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,14 +9,20 @@
 package org.dive4elements.river.model;
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 @Entity
 @Table(name = "annotation_types")
@@ -29,34 +35,43 @@
     public AnnotationType() {
     }
 
-    public AnnotationType(String name) {
+    public AnnotationType(final String name) {
         this.name = name;
     }
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_ANNOTATION_TYPES_ID_SEQ",
-        sequenceName   = "ANNOTATION_TYPES_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_ANNOTATION_TYPES_ID_SEQ",
+            sequenceName   = "ANNOTATION_TYPES_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_ANNOTATION_TYPES_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_ANNOTATION_TYPES_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @Column(name = "name")
     public String getName() {
-        return name;
+        return this.name;
     }
 
-    public void setName(String name) {
+    public void setName(final String name) {
         this.name = name;
     }
+
+    /**
+     * Queries all annotation types from the database, orders by name
+     */
+    public static List<AnnotationType> getTypes() {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM AnnotationType ORDER BY name");
+        return new ArrayList<>(query.list());
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/Attribute.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/Attribute.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,20 +9,124 @@
 package org.dive4elements.river.model;
 
 import java.io.Serializable;
+import java.util.List;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 @Entity
 @Table(name = "attributes")
 public class Attribute
 implements   Serializable
 {
+
+    /***** TYPES *****/
+
+    /**
+     * River attribute (river side or range type)
+     *
+     */
+    public enum AttributeKey {
+        NONE(""), STRECKE(">>>>>>>>>>>>>>>"), LEFT("links"), RIGHT("rechts"), UNKNOWN("?");
+
+        private final String name;
+        private int id;
+        private boolean ready;
+
+        AttributeKey(final String name) {
+            this.name = name;
+            this.id = 0;
+            this.ready = false;
+        }
+
+        /**
+         * Type name in the database
+         */
+        public String getName() {
+            return this.name;
+        }
+
+        /**
+         * Type id in the database
+         */
+        public int getId() {
+            initFromDatabase();
+            return this.id;
+        }
+
+        /**
+         * Set the type id
+         */
+        public void setId(final int id) {
+            this.id = id;
+        }
+
+        protected boolean getReady() {
+            return this.ready;
+        }
+
+        protected void setReady(final boolean ready) {
+            this.ready = ready;
+        }
+
+        /**
+         * Main value type key for a database name value
+         */
+        public static AttributeKey forDbName(final String dbname) {
+            initFromDatabase();
+            for (final AttributeKey k : AttributeKey.values()) {
+                if (k.getName().equalsIgnoreCase(dbname))
+                    return k;
+            }
+            return UNKNOWN;
+        }
+
+        /**
+         * Main value type key for a database id value
+         */
+        public static AttributeKey forDbId(final int dbid) {
+            initFromDatabase();
+            for (final AttributeKey k : AttributeKey.values()) {
+                if (k.getId() == dbid)
+                    return k;
+            }
+            return UNKNOWN;
+        }
+
+        /**
+         * Initially queries the database ids
+         */
+        private static void initFromDatabase() {
+            if (STRECKE.getReady())
+                return;
+            // Avoid recursion
+            for (final AttributeKey k : AttributeKey.values())
+                k.setReady(true);
+            // Select database ids
+            final Session session = SessionHolder.HOLDER.get();
+            final Query query = session.createQuery("FROM Attribute");
+            final List<Attribute> rows = query.list();
+            if (!rows.isEmpty()) {
+                for (int i = 0; i <= rows.size() - 1; i++) {
+                    if (forDbName(rows.get(i).getValue()) != UNKNOWN)
+                        forDbName(rows.get(i).getValue()).setId(rows.get(i).getId());
+                }
+            }
+        }
+    }
+
+    /***** FIELDS *****/
+
     private Integer id;
 
     private String  value;
@@ -30,34 +134,43 @@
     public Attribute() {
     }
 
-    public Attribute(String value) {
+    /***** CONSTRUCTORS *****/
+
+    public Attribute(final String value) {
         this.value = value;
     }
 
+    /***** METHODS *****/
+
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_ATTRIBUTES_ID_SEQ",
-        sequenceName   = "ATTRIBUTES_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_ATTRIBUTES_ID_SEQ",
+            sequenceName   = "ATTRIBUTES_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_ATTRIBUTES_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_ATTRIBUTES_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @Column(name = "value")
     public String getValue() {
-        return value;
+        return this.value;
     }
 
-    public void setValue(String value) {
+    public void setValue(final String value) {
         this.value = value;
     }
+
+    @Transient
+    public AttributeKey getKey() {
+        return AttributeKey.forDbId(this.getId());
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/BedHeight.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/BedHeight.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,26 +9,23 @@
 package org.dive4elements.river.model;
 
 import java.io.Serializable;
-
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
 import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
-import javax.persistence.JoinColumn;
-import javax.persistence.OneToOne;
-import javax.persistence.OneToMany;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
+import javax.persistence.Table;
 
 import org.dive4elements.river.backend.SessionHolder;
-
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 @Entity
 @Table(name = "bed_height")
@@ -42,7 +39,7 @@
 
     private River river;
 
-    private BedHeightType  type;
+    private BedHeightType type;
 
     private LocationSystem locationSystem;
 
@@ -52,215 +49,276 @@
 
     private Range range;
 
+    private String sounding_width_info;
+    private String notes;
+
     private List<BedHeightValue> values;
 
-
     public BedHeight() {
     }
 
-
-    public BedHeight(
-        River          river,
-        Integer        year,
-        BedHeightType  type,
-        LocationSystem locationSystem,
-        ElevationModel curElevationModel,
-        Range          range
-    ) {
-        this(
-            river,
-            year,
-            type,
-            locationSystem,
-            curElevationModel,
-            null,
-            range,
-            null,
-            null);
+    public BedHeight(final River river, final Integer year, final BedHeightType type, final LocationSystem locationSystem,
+            final ElevationModel curElevationModel, final Range range) {
+        this(river, year, type, locationSystem, curElevationModel, null, range, null, null, null, null);
     }
 
-
-    public BedHeight(
-        River          river,
-        Integer        year,
-        BedHeightType  type,
-        LocationSystem locationSystem,
-        ElevationModel curElevationModel,
-        ElevationModel oldElevationModel,
-        Range          range,
-        String         evaluationBy,
-        String         description
-    ) {
-        this.river             = river;
-        this.year              = year;
-        this.type              = type;
-        this.locationSystem    = locationSystem;
+    public BedHeight(final River river, final Integer year, final BedHeightType type, final LocationSystem locationSystem,
+            final ElevationModel curElevationModel, final ElevationModel oldElevationModel, final Range range, final String evaluationBy,
+            final String description, final String sounding_width_info, final String notes) {
+        this.river = river;
+        this.year = year;
+        this.type = type;
+        this.locationSystem = locationSystem;
         this.curElevationModel = curElevationModel;
         this.oldElevationModel = oldElevationModel;
-        this.range             = range;
-        this.evaluationBy      = evaluationBy;
-        this.description       = description;
+        this.range = range;
+        this.evaluationBy = evaluationBy;
+        this.description = description;
+        this.sounding_width_info = sounding_width_info;
+        this.notes = notes;
     }
 
-
     @Id
-    @SequenceGenerator(
-        name           = "SEQUENCE_BED_HEIGHT_ID_SEQ",
-        sequenceName   = "BED_HEIGHT_ID_SEQ",
-        allocationSize = 1)
-    @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_BED_HEIGHT_ID_SEQ")
+    @SequenceGenerator(name = "SEQUENCE_BED_HEIGHT_ID_SEQ", sequenceName = "BED_HEIGHT_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_BED_HEIGHT_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "river_id")
     public River getRiver() {
-        return river;
+        return this.river;
     }
 
-    public void setRiver(River river) {
+    public void setRiver(final River river) {
         this.river = river;
     }
 
     @Column(name = "year")
     public Integer getYear() {
-        return year;
+        return this.year;
     }
 
-    public void setYear(Integer year) {
+    public void setYear(final Integer year) {
         this.year = year;
     }
 
     @OneToOne
     @JoinColumn(name = "type_id")
     public BedHeightType getType() {
-        return type;
+        return this.type;
     }
 
-    public void setType(BedHeightType type) {
+    public void setType(final BedHeightType type) {
         this.type = type;
     }
 
     @OneToOne
     @JoinColumn(name = "location_system_id")
     public LocationSystem getLocationSystem() {
-        return locationSystem;
+        return this.locationSystem;
     }
 
-    public void setLocationSystem(LocationSystem locationSystem) {
+    public void setLocationSystem(final LocationSystem locationSystem) {
         this.locationSystem = locationSystem;
     }
 
     @OneToOne
     @JoinColumn(name = "cur_elevation_model_id")
     public ElevationModel getCurElevationModel() {
-        return curElevationModel;
+        return this.curElevationModel;
     }
 
-    public void setCurElevationModel(ElevationModel curElevationModel) {
+    public void setCurElevationModel(final ElevationModel curElevationModel) {
         this.curElevationModel = curElevationModel;
     }
 
     @OneToOne
     @JoinColumn(name = "old_elevation_model_id")
     public ElevationModel getOldElevationModel() {
-        return oldElevationModel;
+        return this.oldElevationModel;
     }
 
-    public void setOldElevationModel(ElevationModel oldElevationModel) {
+    public void setOldElevationModel(final ElevationModel oldElevationModel) {
         this.oldElevationModel = oldElevationModel;
     }
 
     @OneToOne
     @JoinColumn(name = "range_id")
     public Range getRange() {
-        return range;
+        return this.range;
     }
 
-    public void setRange(Range range) {
+    public void setRange(final Range range) {
         this.range = range;
     }
 
     @Column(name = "evaluation_by")
     public String getEvaluationBy() {
-        return evaluationBy;
+        return this.evaluationBy;
     }
 
-    public void setEvaluationBy(String evaluationBy) {
+    public void setEvaluationBy(final String evaluationBy) {
         this.evaluationBy = evaluationBy;
     }
 
     @Column(name = "description")
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
+    @Column(name = "sounding_width_info")
+    public String getSoundingWidthInfo() {
+        return this.sounding_width_info;
+    }
+
+    public void setSoundingWidthInfo(final String sounding_width_info) {
+        this.sounding_width_info = sounding_width_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
     @OneToMany
     @JoinColumn(name = "bed_height_id")
     public List<BedHeightValue> getValues() {
-        return values;
+        return this.values;
     }
 
-    public void setValues(List<BedHeightValue> values) {
+    public void setValues(final List<BedHeightValue> values) {
         this.values = values;
     }
 
+    public static List<BedHeight> getBedHeights(final River river, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
 
-    public static List<BedHeight> getBedHeights(
-        River  river,
-        double kmLo,
-        double kmHi
-    ) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeight where river=:river");
+        final Query query = session.createQuery("from BedHeight" + " where river=:river" + " and id in (select bedHeight.id from BedHeightValue"
+                + " where station between :kmfrom and :kmto" + " group by bedHeight.id)");
 
         query.setParameter("river", river);
-
-        // TODO Do km range filtering in SQL statement
-
-        List<BedHeight> singles = query.list();
-        List<BedHeight> good    = new ArrayList<BedHeight>();
+        query.setParameter("kmfrom", kmLo);
+        query.setParameter("kmto", kmHi);
 
-        for (BedHeight s: singles) {
-            for (BedHeightValue value: s.getValues()) {
-                double station = value.getStation().doubleValue();
+        final List<BedHeight> singles = query.list();
 
-                if (station >= kmLo && station <= kmHi) {
-                    good.add(s);
-                    break;
-                }
-            }
-        }
-
-        return good;
+        return singles;
     }
 
+    public static BedHeight getBedHeightById(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
 
-    public static BedHeight getBedHeightById(int id) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeight where id=:id");
+        final Query query = session.createQuery("from BedHeight where id=:id");
 
         query.setParameter("id", id);
 
-        List<BedHeight> singles = query.list();
+        final List<BedHeight> singles = query.list();
 
-        return singles != null ? singles.get(0) : null;
+        return ((singles != null) && !singles.isEmpty()) ? singles.get(0) : null;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+    public static BedHeight getBedHeightByDescription(final River river, final String description, final double startKm, final double endKm) {
+
+        final Session session = SessionHolder.HOLDER.get();
+
+        final Query query = session.createQuery("FROM BedHeight" + " WHERE (TRIM(description)=:description) AND river=:river"
+                + " AND id IN (SELECT bedHeight.id FROM BedHeightValue" + " WHERE station BETWEEN :kmfrom AND :kmto" + " GROUP BY bedHeight.id)");
+        query.setParameter("river", river);
+        query.setParameter("description", description);
+        query.setParameter("kmfrom", startKm);
+        query.setParameter("kmto", endKm);
+
+        final List<BedHeight> singles = query.list();
+
+        return ((singles != null) && !singles.isEmpty()) ? singles.get(0) : null;
+    }
+
+    public static List<BedHeight> getBedHeightEpochs(final River river, final double startKm, final double endKm) {
+
+        final Session session = SessionHolder.HOLDER.get();
+        final String description = "epoch";
+        final Query query = session.createQuery("FROM BedHeight" + " WHERE lower(description) LIKE :description AND " + "river=:river"
+                + " AND id IN (SELECT bedHeight.id FROM BedHeightValue" + " WHERE station BETWEEN :kmfrom AND :kmto" + " GROUP BY bedHeight.id)");
+        query.setParameter("river", river);
+        query.setParameter("description", "%" + description + "%");
+        query.setParameter("kmfrom", startKm);
+        query.setParameter("kmto", endKm);
+
+        final List<BedHeight> singles = query.list();
+
+        return ((singles != null) && !singles.isEmpty()) ? singles : null;
+    }
+
+    public static List<BedHeight> getBedHeightYear(final River river, final double startKm, final double endKm) {
+
+        final Session session = SessionHolder.HOLDER.get();
+        final String description = "epoch";
+        final Query query = session.createQuery("FROM BedHeight" + " WHERE lower(description) NOT LIKE :description AND " + "river=:river"
+                + " AND id IN (SELECT bedHeight.id FROM BedHeightValue" + " WHERE station BETWEEN :kmfrom AND :kmto" + " GROUP BY bedHeight.id)");
+        query.setParameter("river", river);
+        query.setParameter("description", "%" + description + "%");
+        query.setParameter("kmfrom", startKm);
+        query.setParameter("kmto", endKm);
+
+        final List<BedHeight> singles = query.list();
+
+        return ((singles != null) && !singles.isEmpty()) ? singles : null;
+    }
+
+    public static Range getRangeFromBedHeights(final BedHeight bh) {
+        final List<Range> ranges = new ArrayList<>();
+
+        final Session session = SessionHolder.HOLDER.get();
+
+        final Query query = session.createQuery("FROM Range" + " WHERE id=:range_id)");
+        query.setParameter("range_id", bh.getRange().getId());
+
+        final List<Range> singles = query.list();
+
+        return ((singles != null) && !singles.isEmpty()) ? singles.get(0) : null;
+    }
+
+    public static List<BedHeight> getBedHeightYearEpoch(final boolean isEpoch, final Integer year, final River river, final double lowerKm,
+            final double upperKm) {
+
+        final Session session = SessionHolder.HOLDER.get();
+        final String description = "epoch";
+
+        final StringBuilder builder = new StringBuilder();
+        builder.append("FROM BedHeight");
+        if (isEpoch) {
+            builder.append(" WHERE lower(description) LIKE :description ");
+        } else {
+            builder.append(" WHERE lower(description) NOT LIKE :description ");
+        }
+        builder.append(" AND year =:year");
+
+        builder.append(
+                " AND river=:river  AND id IN (SELECT bedHeight.id FROM BedHeightValue   WHERE station BETWEEN :kmfrom AND :kmto  GROUP BY bedHeight.id )");
+        final Query query = session.createQuery(builder.toString());
+        query.setParameter("river", river);
+        query.setParameter("year", year);
+        query.setParameter("description", "%" + description + "%");
+        query.setParameter("kmfrom", lowerKm);
+        query.setParameter("kmto", upperKm);
+
+        final List<BedHeight> singles = query.list();
+
+        return ((singles != null) && !singles.isEmpty()) ? singles : null;
+    }
+}
\ No newline at end of file
--- a/backend/src/main/java/org/dive4elements/river/model/BedHeightValue.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/BedHeightValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,26 +8,24 @@
 
 package org.dive4elements.river.model;
 
+import java.io.Serializable;
 import java.util.List;
 
-import java.io.Serializable;
-
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
 import javax.persistence.JoinColumn;
 import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Transient;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.backend.SessionHolder;
 
 
 @Entity
@@ -36,7 +34,7 @@
 implements   Serializable
 {
     private static Logger log =
-        Logger.getLogger(BedHeightValue.class);
+            Logger.getLogger(BedHeightValue.class);
 
     private Integer id;
 
@@ -47,126 +45,262 @@
     private Double uncertainty;
     private Double dataGap;
     private Double soundingWidth;
+    private Double minHeight;
+    private Double maxHeight;
+    private Double height01;
+    private Double height02;
+    private Double height03;
+    private Double height04;
+    private Double height05;
+    private Double height06;
+    private Double height07;
+    private Double height08;
+    private Double height09;
+    private Double height10;
 
 
     public BedHeightValue() {
     }
 
-    public BedHeightValue(
-        BedHeight bedHeight,
-        Double station,
-        Double height,
-        Double uncertainty,
-        Double dataGap,
-        Double soundingWidth
-    ) {
+    public BedHeightValue(final BedHeight bedHeight, final Double station, final Double height, final Double uncertainty, final Double dataGap,
+            final Double soundingWidth, final Double minHeight, final Double maxHeight) {
         this.bedHeight     = bedHeight;
         this.station       = station;
         this.height        = height;
         this.uncertainty   = uncertainty;
         this.dataGap       = dataGap;
         this.soundingWidth = soundingWidth;
+        this.minHeight = minHeight;
+        this.maxHeight = maxHeight;
     }
 
     @Id
-    @SequenceGenerator(
-        name           = "SEQUENCE_BED_HEIGHT_VALUE_ID_SEQ",
-        sequenceName   = "BED_HEIGHT_VALUES_ID_SEQ",
-        allocationSize = 1)
-    @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_BED_HEIGHT_VALUE_ID_SEQ")
+    @SequenceGenerator(name = "SEQUENCE_BED_HEIGHT_VALUE_ID_SEQ", sequenceName = "BED_HEIGHT_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_BED_HEIGHT_VALUE_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "bed_height_id")
     public BedHeight getBedHeight() {
-        return bedHeight;
+        return this.bedHeight;
     }
 
-    public void setBedHeight(BedHeight bedHeight) {
+    public void setBedHeight(final BedHeight bedHeight) {
         this.bedHeight = bedHeight;
     }
 
     @Column(name = "station")
     public Double getStation() {
-        return station;
+        return this.station;
     }
 
-    public void setStation(Double station) {
+    public void setStation(final Double station) {
         this.station = station;
     }
 
     @Column(name = "height")
     public Double getHeight() {
-        return height;
+        return this.height;
     }
 
-    public void setHeight(Double height) {
+    public void setHeight(final Double height) {
         this.height = height;
     }
 
     @Column(name="uncertainty")
     public Double getUncertainty() {
-        return uncertainty;
+        return this.uncertainty;
     }
 
-    public void setUncertainty(Double uncertainty) {
+    public void setUncertainty(final Double uncertainty) {
         this.uncertainty = uncertainty;
     }
 
     @Column(name="data_gap")
     public Double getDataGap() {
-        return dataGap;
+        return this.dataGap;
     }
 
-    public void setDataGap(Double dataGap) {
+    public void setDataGap(final Double dataGap) {
         this.dataGap = dataGap;
     }
 
     @Column(name="sounding_width")
     public Double getSoundingWidth() {
-        return soundingWidth;
+        return this.soundingWidth;
     }
 
-    public void setSoundingWidth(Double soundingWidth) {
+    public void setSoundingWidth(final Double soundingWidth) {
         this.soundingWidth = soundingWidth;
     }
 
-    public static List<BedHeightValue> getBedHeightValues(
-        BedHeight single) {
-        Session session = SessionHolder.HOLDER.get();
+    @Column(name = "min_height")
+    public Double getMinHeight() {
+        return this.minHeight;
+    }
 
-        Query query = session.createQuery(
-            "from BedHeightValue where bedHeight=:single");
+    public void setMinHeight(final Double minHeight) {
+        this.minHeight = minHeight;
+    }
 
+    @Column(name = "max_height")
+    public Double getMaxHeight() {
+        return this.maxHeight;
+    }
+
+    public void setMaxHeight(final Double maxHeight) {
+        this.maxHeight = maxHeight;
+    }
+
+    @Column(name = "height01")
+    public Double getHeight01() {
+        return this.height01;
+    }
+
+    public void setHeight01(final Double height) {
+        this.height01 = height;
+    }
+
+    @Column(name = "height02")
+    public Double getHeight02() {
+        return this.height02;
+    }
+
+    public void setHeight02(final Double height) {
+        this.height02 = height;
+    }
+
+    @Column(name = "height03")
+    public Double getHeight03() {
+        return this.height03;
+    }
+
+    public void setHeight03(final Double height) {
+        this.height03 = height;
+    }
+
+    @Column(name = "height04")
+    public Double getHeight04() {
+        return this.height04;
+    }
+
+    public void setHeight04(final Double height) {
+        this.height04 = height;
+    }
+
+    @Column(name = "height05")
+    public Double getHeight05() {
+        return this.height05;
+    }
+
+    public void setHeight05(final Double height) {
+        this.height05 = height;
+    }
+
+    @Column(name = "height06")
+    public Double getHeight06() {
+        return this.height06;
+    }
+
+    public void setHeight06(final Double height) {
+        this.height06 = height;
+    }
+
+    @Column(name = "height07")
+    public Double getHeight07() {
+        return this.height07;
+    }
+
+    public void setHeight07(final Double height) {
+        this.height07 = height;
+    }
+
+    @Column(name = "height08")
+    public Double getHeight08() {
+        return this.height08;
+    }
+
+    public void setHeight08(final Double height) {
+        this.height08 = height;
+    }
+
+    @Column(name = "height09")
+    public Double getHeight09() {
+        return this.height09;
+    }
+
+    public void setHeight09(final Double height) {
+        this.height09 = height;
+    }
+
+    @Column(name = "height10")
+    public Double getHeight10() {
+        return this.height10;
+    }
+
+    public void setHeight10(final Double height) {
+        this.height10 = height;
+    }
+
+    @Transient
+    public void setSectionHeight(final int index, final Double value) {
+        switch (index) {
+        case 1:
+            this.height01 = value;
+            break;
+        case 2:
+            this.height02 = value;
+            break;
+        case 3:
+            this.height03 = value;
+            break;
+        case 4:
+            this.height04 = value;
+            break;
+        case 5:
+            this.height05 = value;
+            break;
+        case 6:
+            this.height06 = value;
+            break;
+        case 7:
+            this.height07 = value;
+            break;
+        case 8:
+            this.height08 = value;
+            break;
+        case 9:
+            this.height09 = value;
+            break;
+        case 10:
+            this.height10 = value;
+            break;
+        default:
+            break;
+        }
+    }
+    public static List<BedHeightValue> getBedHeightValues(final BedHeight single) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM BedHeightValue WHERE bedHeight=:single");
         query.setParameter("single", single);
         return query.list();
     }
 
 
-    public static List<BedHeightValue> getBedHeightValues(
-        BedHeight single,
-        double kmLo,
-        double kmHi
-    ) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeightValue where bedHeight=:single " +
-            "   and station >= :kmLo and station <= :kmHi");
-
+    public static List<BedHeightValue> getBedHeightValues(final BedHeight single, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM BedHeightValue WHERE (bedHeight=:single)"
+                + " AND (station >= :kmLo) AND (station <= :kmHi)");
         query.setParameter("single", single);
         query.setParameter("kmLo", new Double(kmLo));
         query.setParameter("kmHi", new Double(kmHi));
-
         return query.list();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/BedHeightValueType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.model;
+
+/**
+ * Enumerations that allows to access min/max/mean value of {@link BedHeight} in the same way.
+ *
+ * @author Gernot Belger
+ *
+ */
+public enum BedHeightValueType {
+    min {
+        @Override
+        public Double getValue(final BedHeightValue bedheightValue) {
+            return bedheightValue.getMinHeight();
+        }
+    },
+    max {
+        @Override
+        public Double getValue(final BedHeightValue bedheightValue) {
+            return bedheightValue.getMaxHeight();
+        }
+    },
+    value {
+        @Override
+        public Double getValue(final BedHeightValue bedheightValue) {
+            return bedheightValue.getHeight();
+        }
+    };
+
+    public abstract Double getValue(final BedHeightValue bedheightValue);
+}
\ No newline at end of file
--- a/backend/src/main/java/org/dive4elements/river/model/DischargeTable.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/DischargeTable.java	Fri Jul 13 11:56:22 2018 +0200
@@ -23,10 +23,11 @@
 import javax.persistence.OrderBy;
 import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
+import javax.persistence.Transient;
 
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-import org.dive4elements.river.backend.SessionHolder;
 
 @Entity
 @Table(name = "discharge_tables")
@@ -43,20 +44,20 @@
     private List<DischargeTableValue> dischargeTableValues;
 
     public DischargeTable() {
-        kind = 0;
+        this.kind = 0;
     }
 
-    public DischargeTable(Gauge gauge) {
+    public DischargeTable(final Gauge gauge) {
         this(gauge, null, null, 0, null);
     }
 
     public DischargeTable(
-        Gauge        gauge,
-        String       description,
-        String       bfgId,
-        Integer      kind,
-        TimeInterval timeInterval
-    ) {
+            final Gauge        gauge,
+            final String       description,
+            final String       bfgId,
+            final Integer      kind,
+            final TimeInterval timeInterval
+            ) {
         this.gauge        = gauge;
         this.description  = description;
         this.bfgId        = bfgId;
@@ -66,65 +67,65 @@
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_DISCHARGE_TABLES_ID_SEQ",
-        sequenceName   = "DISCHARGE_TABLES_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_DISCHARGE_TABLES_ID_SEQ",
+            sequenceName   = "DISCHARGE_TABLES_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_DISCHARGE_TABLES_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_DISCHARGE_TABLES_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "gauge_id")
     public Gauge getGauge() {
-        return gauge;
+        return this.gauge;
     }
 
-    public void setGauge(Gauge gauge) {
+    public void setGauge(final Gauge gauge) {
         this.gauge = gauge;
     }
 
     @Column(name = "description")
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
     @Column(name = "bfg_id")
     public String getBfgId() {
-        return bfgId;
+        return this.bfgId;
     }
 
-    public void setBfgId(String bfgId) {
+    public void setBfgId(final String bfgId) {
         this.bfgId = bfgId;
     }
 
     @Column(name = "kind")
     public Integer getKind() {
-        return kind;
+        return this.kind;
     }
 
-    public void setKind(Integer kind) {
+    public void setKind(final Integer kind) {
         this.kind = kind;
     }
 
     @OneToOne
     @JoinColumn(name = "time_interval_id")
     public TimeInterval getTimeInterval() {
-        return timeInterval;
+        return this.timeInterval;
     }
 
-    public void setTimeInterval(TimeInterval timeInterval) {
+    public void setTimeInterval(final TimeInterval timeInterval) {
         this.timeInterval = timeInterval;
     }
 
@@ -132,34 +133,43 @@
     @JoinColumn(name = "table_id")
     @OrderBy("q")
     public List<DischargeTableValue> getDischargeTableValues() {
-        return dischargeTableValues;
+        return this.dischargeTableValues;
     }
 
     public void setDischargeTableValues(
-        List<DischargeTableValue> dischargeTableValues
-    ) {
+            final List<DischargeTableValue> dischargeTableValues
+            ) {
         this.dischargeTableValues = dischargeTableValues;
     }
 
+    @Transient
+    public double[] getWs() {
+        final double[] ws = new double[this.dischargeTableValues.size()];
+        for (int i=0; i<=this.dischargeTableValues.size()-1; i++)
+            ws[i] = this.dischargeTableValues.get(i).getW().doubleValue();
+
+        return ws;
+    }
+
     @Override
-    public int compareTo(DischargeTable o) {
+    public int compareTo(final DischargeTable o) {
         if (getKind() == 0 && o.getKind() != 0) {
             return 1;
         }
 
-        TimeInterval other = o.getTimeInterval();
-        if (other == null && timeInterval == null) {
+        final TimeInterval other = o.getTimeInterval();
+        if (other == null && this.timeInterval == null) {
             return 1;
         }
         else if (other == null) {
             return -1;
         }
-        else if (timeInterval == null) {
+        else if (this.timeInterval == null) {
             return 1;
         }
 
-        Date otherStartTime = other.getStartTime();
-        Date thisStartTime  = timeInterval.getStartTime();
+        final Date otherStartTime = other.getStartTime();
+        final Date thisStartTime  = this.timeInterval.getStartTime();
 
         if (otherStartTime == null) {
             return -1;
@@ -168,8 +178,8 @@
             return 1;
         }
 
-        long otherStart = otherStartTime.getTime();
-        long thisStart  = thisStartTime.getTime();
+        final long otherStart = otherStartTime.getTime();
+        final long thisStart  = thisStartTime.getTime();
 
         if (otherStart < thisStart) {
             return 1;
@@ -178,8 +188,8 @@
             return -1;
         }
 
-        Date otherStopTime  = other.getStopTime();
-        Date thisStopTime  = timeInterval.getStopTime();
+        final Date otherStopTime  = other.getStopTime();
+        final Date thisStopTime  = this.timeInterval.getStopTime();
 
         if (otherStopTime == null) {
             return -1;
@@ -188,8 +198,8 @@
             return 1;
         }
 
-        long otherEnd   = otherStopTime.getTime();
-        long thisEnd    = thisStopTime.getTime();
+        final long otherEnd   = otherStopTime.getTime();
+        final long thisEnd    = thisStopTime.getTime();
 
         if (otherEnd < thisEnd) {
             return 1;
@@ -202,15 +212,24 @@
         }
     }
 
-    public static DischargeTable getDischargeTableById(int dtId)
+    public static DischargeTable getDischargeTableById(final int dtId)
     {
-        Session session = SessionHolder.HOLDER.get();
-        Query query = session.createQuery(
-            "from DischargeTable where id =:dtId");
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("from DischargeTable where id =:dtId");
         query.setParameter("dtId", dtId);
 
-        List<DischargeTable> list = query.list();
+        final List<DischargeTable> list = query.list();
         return list.isEmpty() ? null : list.get(0);
     }
+
+    /**
+     * Selects from the database the values of a discharge table sorted by W
+     */
+    public static List<DischargeTableValue> fetchValuesSortedByW(final DischargeTable dischargeTable) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM DischargeTableValue WHERE table_id=:parentid ORDER BY w");
+        query.setParameter("parentid", dischargeTable.getId());
+        return query.list();
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/MainValue.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/MainValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,21 +9,26 @@
 package org.dive4elements.river.model;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
 
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
 import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.OneToOne;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
 import javax.persistence.JoinColumn;
-import javax.persistence.GenerationType;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
 
-import java.math.BigDecimal;
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
-/** A Main or Extreme value of a rivers gauge. */
+/** A Main or Extreme value of a river's gauge. */
 @Entity
 @Table(name = "main_values")
 public class MainValue
@@ -43,11 +48,11 @@
     }
 
     public MainValue(
-        Gauge          gauge,
-        NamedMainValue mainValue,
-        BigDecimal     value,
-        TimeInterval   timeInterval
-    ) {
+            final Gauge          gauge,
+            final NamedMainValue mainValue,
+            final BigDecimal     value,
+            final TimeInterval   timeInterval
+            ) {
         this.gauge        = gauge;
         this.mainValue    = mainValue;
         this.value        = value;
@@ -56,58 +61,86 @@
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_MAIN_VALUES_ID_SEQ",
-        sequenceName   = "MAIN_VALUES_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_MAIN_VALUES_ID_SEQ",
+            sequenceName   = "MAIN_VALUES_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_MAIN_VALUES_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_MAIN_VALUES_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "gauge_id")
     public Gauge getGauge() {
-        return gauge;
+        return this.gauge;
     }
 
-    public void setGauge(Gauge gauge) {
+    public void setGauge(final Gauge gauge) {
         this.gauge = gauge;
     }
 
     @OneToOne
     @JoinColumn(name = "named_value_id")
     public NamedMainValue getMainValue() {
-        return mainValue;
+        return this.mainValue;
     }
 
-    public void setMainValue(NamedMainValue mainValue) {
+    public void setMainValue(final NamedMainValue mainValue) {
         this.mainValue = mainValue;
     }
 
     @Column(name = "value") // FIXME: type mapping needed?
     public BigDecimal getValue() {
-        return value;
+        return this.value;
     }
 
-    public void setValue(BigDecimal value) {
+    public void setValue(final BigDecimal value) {
         this.value = value;
     }
 
     @OneToOne
     @JoinColumn(name = "time_interval_id")
     public TimeInterval getTimeInterval() {
-        return timeInterval;
+        return this.timeInterval;
     }
 
-    public void setTimeInterval(TimeInterval timeInterval) {
+    public void setTimeInterval(final TimeInterval timeInterval) {
         this.timeInterval = timeInterval;
     }
+
+    /**
+     * Selects from the database the main values of a gauge and a type, in ascending value order
+     */
+    public static List<MainValue> getValuesOfGaugeAndType(final Gauge gauge, final MainValueTypeKey typekey) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("SELECT mv"
+                + " FROM MainValue AS mv JOIN mv.mainValue AS nmv"
+                + " WHERE mv.gauge.id=:gaugeid AND nmv.type.id=:typeid"
+                + " ORDER BY value");
+        query.setParameter("gaugeid", gauge.getId());
+        query.setParameter("typeid", typekey.getId());
+        return query.list();
+    }
+
+    /**
+     * Selects from the database the discharge-duration main values of a gauge sorted by duration
+     */
+    public static List<MainValue> getDurationDischargesOfGauge(final Gauge gauge) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("SELECT mv"
+                + " FROM MainValue AS mv JOIN mv.mainValue AS nmv"
+                + " WHERE mv.gauge.id=:gaugeid AND nmv.type.id=:typeid"
+                + " ORDER BY CAST(nmv.name AS int)");
+        query.setParameter("gaugeid", gauge.getId());
+        query.setParameter("typeid", MainValueTypeKey.DURATION.getId());
+        return query.list();
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/MainValueType.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/MainValueType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,53 +9,163 @@
 package org.dive4elements.river.model;
 
 import java.io.Serializable;
+import java.util.List;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 @Entity
 @Table(name = "main_value_types")
 public class MainValueType
 implements   Serializable
 {
+
+    /***** TYPES *****/
+
+    /**
+     * Main value type names
+     *
+     */
+    public enum MainValueTypeKey {
+        NONE(""), W("W"), Q("Q"), DURATION("D"), UNKNOWN("-");
+
+        private final String name;
+        private int id;
+        private boolean ready;
+
+        MainValueTypeKey(final String name) {
+            this.name = name;
+            this.id = 0;
+            this.ready = false;
+        }
+
+        /**
+         * Type name in the database
+         */
+        public String getName() {
+            return this.name;
+        }
+
+        /**
+         * Type id in the database
+         */
+        public int getId() {
+            initFromDatabase();
+            return this.id;
+        }
+
+        /**
+         * Set the type id
+         */
+        public void setId(final int id) {
+            this.id = id;
+        }
+
+        protected boolean getReady() {
+            return this.ready;
+        }
+
+        protected void setReady(final boolean ready) {
+            this.ready = ready;
+        }
+
+        /**
+         * Main value type key for a database name value
+         */
+        public static MainValueTypeKey forDbName(final String dbname) {
+            initFromDatabase();
+            for (final MainValueTypeKey k : MainValueTypeKey.values()) {
+                if (k.getName().equalsIgnoreCase(dbname))
+                    return k;
+            }
+            return NONE;
+        }
+
+        /**
+         * Main value type key for a database id value
+         */
+        public static MainValueTypeKey forDbId(final int dbid) {
+            initFromDatabase();
+            for (final MainValueTypeKey k : MainValueTypeKey.values()) {
+                if (k.getId() == dbid)
+                    return k;
+            }
+            return NONE;
+        }
+
+        /**
+         * Initially queries the database ids
+         */
+        private static void initFromDatabase() {
+            if (W.getReady())
+                return;
+            // Avoid recursion
+            for (final MainValueTypeKey k : MainValueTypeKey.values())
+                k.setReady(true);
+            // Select database ids
+            final Session session = SessionHolder.HOLDER.get();
+            final Query query = session.createQuery("FROM MainValueType");
+            final List<MainValueType> rows = query.list();
+            if (!rows.isEmpty()) {
+                for (int i = 0; i <= rows.size() - 1; i++) {
+                    if (forDbName(rows.get(i).getName()) != NONE)
+                        forDbName(rows.get(i).getName()).setId(rows.get(i).getId());
+                }
+            }
+        }
+    }
+
+    /***** FIELDS *****/
+
     private Integer id;
     private String  name;
+    // static private List<Integer> typeids;
+    // static private List<String> typenames;
+
+    /***** CONSTRUCTORS *****/
 
     public MainValueType() {
     }
 
-    public MainValueType(String name) {
+    public MainValueType(final String name) {
         this.name = name;
     }
 
+
+    /***** METHODS *****/
+
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_MAIN_VALUE_TYPES_ID_SEQ",
-        sequenceName   = "MAIN_VALUE_TYPES_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_MAIN_VALUE_TYPES_ID_SEQ",
+            sequenceName   = "MAIN_VALUE_TYPES_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_MAIN_VALUE_TYPES_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_MAIN_VALUE_TYPES_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @Column(name = "name") // FIXME: Type conversion needed?
     public String getName() {
-        return name;
+        return this.name;
     }
 
-    public void setName(String name) {
+    public void setName(final String name) {
         this.name = name;
     }
 }
--- a/backend/src/main/java/org/dive4elements/river/model/River.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/River.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,8 +8,6 @@
 
 package org.dive4elements.river.model;
 
-import org.dive4elements.river.backend.SessionHolder;
-
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.MathContext;
@@ -29,12 +27,12 @@
 import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
 
+import org.apache.log4j.Logger;
+import org.dive4elements.river.backend.SessionHolder;
 import org.hibernate.Query;
 import org.hibernate.Session;
 import org.hibernate.annotations.Type;
 
-import org.apache.log4j.Logger;
-
 @Entity
 @Table(name = "rivers")
 public class River
@@ -51,8 +49,8 @@
 
     public static final Comparator<Double> KM_CMP = new Comparator<Double>() {
         @Override
-        public int compare(Double a, Double b) {
-            double diff = a - b;
+        public int compare(final Double a, final Double b) {
+            final double diff = a - b;
             if (diff < -EPSILON) return -1;
             if (diff >  EPSILON) return +1;
             return 0;
@@ -77,46 +75,46 @@
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_RIVERS_ID_SEQ",
-        sequenceName   = "RIVERS_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_RIVERS_ID_SEQ",
+            sequenceName   = "RIVERS_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_RIVERS_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_RIVERS_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @Column(name = "official_number")
     public Long getOfficialNumber() {
-        return officialNumber;
+        return this.officialNumber;
     }
 
-    public void setOfficialNumber(Long officialNumber) {
+    public void setOfficialNumber(final Long officialNumber) {
         this.officialNumber = officialNumber;
     }
 
     @Column(name = "name")
     public String getName() {
-        return name;
+        return this.name;
     }
 
-    public void setName(String name) {
+    public void setName(final String name) {
         this.name = name;
     }
 
     @Type(type="numeric_boolean")
     @Column(name = "km_up")
     public boolean getKmUp() {
-        return kmUp;
+        return this.kmUp;
     }
 
-    public void setKmUp(boolean kmUp) {
+    public void setKmUp(final boolean kmUp) {
         this.kmUp = kmUp;
     }
 
@@ -125,14 +123,14 @@
         return this.modelUuid;
     }
 
-    public void setModelUuid(String modelUuid) {
+    public void setModelUuid(final String modelUuid) {
         this.modelUuid = modelUuid;
     }
 
     public River() {
     }
 
-    public River(String name, Unit wstUnit, String modelUuid) {
+    public River(final String name, final Unit wstUnit, final String modelUuid) {
         this.name      = name;
         this.modelUuid = modelUuid;
         this.wstUnit   = wstUnit;
@@ -141,20 +139,20 @@
     @OneToMany
     @JoinColumn(name="river_id")
     public List<Gauge> getGauges() {
-        return gauges;
+        return this.gauges;
     }
 
-    public void setGauges(List<Gauge> gauges) {
+    public void setGauges(final List<Gauge> gauges) {
         this.gauges = gauges;
     }
 
     @OneToOne
     @JoinColumn(name = "wst_unit_id" )
     public Unit getWstUnit() {
-        return wstUnit;
+        return this.wstUnit;
     }
 
-    public void setWstUnit(Unit wstUnit) {
+    public void setWstUnit(final Unit wstUnit) {
         this.wstUnit = wstUnit;
     }
 
@@ -168,7 +166,7 @@
      * @return The name River in the seddb.
      */
     public String nameForSeddb() {
-        SeddbName alt = getSeddbName();
+        final SeddbName alt = getSeddbName();
         if (alt == null) {
             return getName();
         }
@@ -179,16 +177,16 @@
     @OneToOne
     @JoinColumn(name = "seddb_name_id" )
     public SeddbName getSeddbName() {
-        return seddbName;
+        return this.seddbName;
     }
 
-    public void setSeddbName(SeddbName name) {
+    public void setSeddbName(final SeddbName name) {
         this.seddbName = name;
     }
 
     @Override
     public String toString() {
-        return name != null ? name : "";
+        return this.name != null ? this.name : "";
     }
 
 
@@ -202,16 +200,16 @@
      * @return the intersecting gauges.
      */
     public List<Gauge> determineGauges(double a, double b) {
-        Session session = SessionHolder.HOLDER.get();
-
-        if (a > b) { double t = a; a = b; b = t; }
+        final Session session = SessionHolder.HOLDER.get();
 
-        Query query = session.createQuery(
-            "from Gauge where river=:river " +
-            "and not " +
-            "((:b < least(range.a, range.b)) or" +
-            " (:a > greatest(range.a, range.b)))" +
-            "order by a");
+        if (a > b) { final double t = a; a = b; b = t; }
+
+        final Query query = session.createQuery(
+                "from Gauge where river=:river " +
+                        "and not " +
+                        "((:b < least(range.a, range.b)) or" +
+                        " (:a > greatest(range.a, range.b)))" +
+                "order by a");
         query.setParameter("river", this);
         query.setParameter("a", new BigDecimal(a, PRECISION));
         query.setParameter("b", new BigDecimal(b, PRECISION));
@@ -220,28 +218,28 @@
     }
 
     public Gauge maxOverlap(double a, double b) {
-        List<Gauge> gauges = determineGauges(a, b);
+        final List<Gauge> gauges = determineGauges(a, b);
         if (gauges == null) {
             return null;
         }
 
-        if (a > b) { double t = a; a = b; b = t; }
+        if (a > b) { final double t = a; a = b; b = t; }
 
         double max = -Double.MAX_VALUE;
 
         Gauge result = null;
 
-        for (Gauge gauge: gauges) {
-            Range  r = gauge.getRange();
+        for (final Gauge gauge: gauges) {
+            final Range  r = gauge.getRange();
             double c = r.getA().doubleValue();
             double d = r.getB().doubleValue();
 
-            if (c > d) { double t = c; c = d; d = t; }
+            if (c > d) { final double t = c; c = d; d = t; }
 
-            double start = c >= a ? c : a;
-            double stop  = d <= b ? d : b;
+            final double start = c >= a ? c : a;
+            final double stop  = d <= b ? d : b;
 
-            double length = stop - start;
+            final double length = stop - start;
 
             if (length > max) {
                 max = length;
@@ -252,17 +250,17 @@
         return result;
     }
 
-    public Gauge determineGaugeByName(String name) {
-        Session session = SessionHolder.HOLDER.get();
-        Query query = session.createQuery(
-            "from Gauge where river=:river and name=:name");
+    public Gauge determineGaugeByName(final String name) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery(
+                "from Gauge where river=:river and name=:name");
         query.setParameter("river", this);
         query.setParameter("name", name);
-        List<Gauge> gauges = query.list();
+        final List<Gauge> gauges = query.list();
         return gauges.isEmpty() ? null : gauges.get(0);
     }
 
-    public Gauge determineGaugeByPosition(double p) {
+    public Gauge determineGaugeByPosition(final double p) {
         // Per default, we prefer the gauge downstream
         return determineGaugeByPosition(p, getKmUp());
     }
@@ -272,16 +270,16 @@
      * @param kmLower At boundary of two gauge ranges, should gauge at lower
      * km be returned?
      */
-    public Gauge determineGaugeByPosition(double p, boolean kmLower) {
-        Session session = SessionHolder.HOLDER.get();
-        Query query = session.createQuery(
-            "from Gauge g where river=:river "  +
-            "and :p between " +
-            "least(g.range.a, g.range.b) and " +
-            "greatest(g.range.a, g.range.b)");
+    public Gauge determineGaugeByPosition(final double p, final boolean kmLower) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery(
+                "from Gauge g where river=:river "  +
+                        "and :p between " +
+                        "least(g.range.a, g.range.b) and " +
+                "greatest(g.range.a, g.range.b)");
         query.setParameter("river", this);
         query.setParameter("p", new BigDecimal(p, PRECISION));
-        List<Gauge> gauges = query.list();
+        final List<Gauge> gauges = query.list();
         if (gauges.isEmpty()) {
             return null;
         }
@@ -291,19 +289,19 @@
         if (gauges.size() > 2) {
             // TODO: database schema should prevent this.
             log.warn("More than two gauge ranges overlap km " + p +
-                ". Returning arbitrary result.");
+                    ". Returning arbitrary result.");
         }
-        Gauge g0 = gauges.get(0);
-        Gauge g1 = gauges.get(1);
+        final Gauge g0 = gauges.get(0);
+        final Gauge g1 = gauges.get(1);
         if (kmLower) {
             return
-                g0.getStation().doubleValue() < g1.getStation().doubleValue()
-                ? g0
-                : g1;
+                    g0.getStation().doubleValue() < g1.getStation().doubleValue()
+                    ? g0
+                            : g1;
         }
         return g0.getStation().doubleValue() > g1.getStation().doubleValue()
-            ? g0
-            : g1;
+                ? g0
+                        : g1;
     }
 
 
@@ -311,46 +309,46 @@
      * @param s station at which the gauge is requested.
      * @return Gauge within tolerance at given station. null if there is none.
      */
-    public Gauge determineGaugeAtStation(double s) {
-        Session session = SessionHolder.HOLDER.get();
+    public Gauge determineGaugeAtStation(final double s) {
+        final Session session = SessionHolder.HOLDER.get();
 
-        Query query = session.createQuery(
-            "from Gauge where river.id=:river " +
-            "and station between :a and :b");
+        final Query query = session.createQuery(
+                "from Gauge where river.id=:river " +
+                "and station between :a and :b");
         query.setParameter("river", getId());
         query.setParameter("a", new BigDecimal(s - GAUGE_EPSILON));
         query.setParameter("b", new BigDecimal(s + GAUGE_EPSILON));
 
-        List<Gauge> gauges = query.list();
+        final List<Gauge> gauges = query.list();
         if (gauges.size() > 1) {
             log.warn("More than one gauge found at km " + s +
-                " within +-" + GAUGE_EPSILON +
-                ". Returning arbitrary result.");
+                    " within +-" + GAUGE_EPSILON +
+                    ". Returning arbitrary result.");
         }
         return gauges.isEmpty() ? null : gauges.get(0);
     }
 
     public double[] determineMinMaxQ() {
-        Session session = SessionHolder.HOLDER.get();
+        final Session session = SessionHolder.HOLDER.get();
 
-        Query query = session.createQuery(
-            "select min(wqr.q) as min, max(wqr.q) as max " +
-            "from Wst as w " +
-            "join w.columns as wc " +
-            "join wc.columnQRanges as wcqr " +
-            "join wcqr.wstQRange as wqr " +
-            "where w.kind = 0 and river_id = :river");
+        final Query query = session.createQuery(
+                "select min(wqr.q) as min, max(wqr.q) as max " +
+                        "from Wst as w " +
+                        "join w.columns as wc " +
+                        "join wc.columnQRanges as wcqr " +
+                        "join wcqr.wstQRange as wqr " +
+                "where w.kind = 0 and river_id = :river");
 
         query.setParameter("river", getId());
 
-        double minmax[] = new double[] { Double.MAX_VALUE, -Double.MAX_VALUE };
+        final double minmax[] = new double[] { Double.MAX_VALUE, -Double.MAX_VALUE };
 
-        List<Object> results = query.list();
+        final List<Object> results = query.list();
 
         if (!results.isEmpty()) {
-            Object[] arr = (Object[]) results.get(0);
-            BigDecimal minq = (BigDecimal)arr[0];
-            BigDecimal maxq = (BigDecimal)arr[1];
+            final Object[] arr = (Object[]) results.get(0);
+            final BigDecimal minq = (BigDecimal)arr[0];
+            final BigDecimal maxq = (BigDecimal)arr[1];
             minmax[0] = minq.doubleValue();
             minmax[1] = maxq.doubleValue();
         }
@@ -362,11 +360,11 @@
      * Determine reference gauge dependent on direction of calculation
      * for a range calculation, otherwise dependent on flow direction.
      */
-    public Gauge determineRefGauge(double[] range, boolean isRange) {
+    public Gauge determineRefGauge(final double[] range, final boolean isRange) {
         if (isRange) {
             return determineGaugeByPosition(
-                range[0],
-                range[0] > range[1]);
+                    range[0],
+                    range[0] > range[1]);
         }
         else {
             return determineGaugeByPosition(range[0]);
@@ -381,21 +379,21 @@
      * @return the min and max distance of this river.
      */
     public double[] determineMinMaxDistance() {
-        Session session = SessionHolder.HOLDER.get();
+        final Session session = SessionHolder.HOLDER.get();
 
-        Query query = session.createQuery(
-            "select min(range.a), max(range.b) from Gauge "
-            + "where river=:river "
-            + "and range is not null");
+        final Query query = session.createQuery(
+                "select min(range.a), max(range.b) from Gauge "
+                        + "where river=:river "
+                        + "and range is not null");
         query.setParameter("river", this);
 
-        List<Object[]> result = query.list();
+        final List<Object[]> result = query.list();
 
         if (!result.isEmpty()) {
-            Object[] minMax = result.get(0);
+            final Object[] minMax = result.get(0);
             if (minMax[0] != null && minMax[1] != null) {
                 return new double[] { ((BigDecimal)minMax[0]).doubleValue(),
-                    ((BigDecimal)minMax[1]).doubleValue() };
+                        ((BigDecimal)minMax[1]).doubleValue() };
             }
         }
 
@@ -403,12 +401,12 @@
     }
 
     public Map<Double, Double> queryGaugeDatumsKMs() {
-        List<Gauge> gauges = getGauges();
-        Map<Double, Double> result = new TreeMap<Double, Double>(KM_CMP);
+        final List<Gauge> gauges = getGauges();
+        final Map<Double, Double> result = new TreeMap<>(KM_CMP);
 
-        for (Gauge gauge: gauges) {
-            BigDecimal km    = gauge.getStation();
-            BigDecimal datum = gauge.getDatum();
+        for (final Gauge gauge: gauges) {
+            final BigDecimal km    = gauge.getStation();
+            final BigDecimal datum = gauge.getDatum();
             if (km != null && datum != null) {
                 result.put(km.doubleValue(), datum.doubleValue());
             }
@@ -417,5 +415,17 @@
         return result;
     }
 
+    /**
+     * Searches the gauges list of the river for a gauge number or a gauge name
+     */
+    public Gauge findGauge(final long number, final String name) {
+        for (final Gauge gauge : getGauges()) {
+            if (gauge.getOfficialNumber().longValue() == number)
+                return gauge;
+            if (gauge.getName().equalsIgnoreCase(name))
+                return gauge;
+        }
+        return null;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/TimeInterval.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/TimeInterval.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,22 +9,33 @@
 package org.dive4elements.river.model;
 
 import java.io.Serializable;
-
+import java.util.Calendar;
 import java.util.Date;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
 
 @Entity
 @Table(name = "time_intervals")
 public class TimeInterval
 implements   Serializable
 {
+    /**
+     * Pseudo-date for Date values where only the year field is significant
+     * (in Flys 3.2.1 June-15 12:00 had been used)
+     */
+    public final static Calendar YEAR_ONLY_DATE;
+    static {
+        YEAR_ONLY_DATE = Calendar.getInstance();
+        YEAR_ONLY_DATE.clear();
+        YEAR_ONLY_DATE.set(0, Calendar.DECEMBER, 31, 3, 5, 6);
+    }
+
     private Integer id;
     private Date    startTime;
     private Date    stopTime;
@@ -32,43 +43,43 @@
     public TimeInterval() {
     }
 
-    public TimeInterval(Date startTime, Date stopTime) {
+    public TimeInterval(final Date startTime, final Date stopTime) {
         this.startTime = startTime;
         this.stopTime  = stopTime;
     }
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_TIME_INTERVALS_ID_SEQ",
-        sequenceName   = "TIME_INTERVALS_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_TIME_INTERVALS_ID_SEQ",
+            sequenceName   = "TIME_INTERVALS_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_TIME_INTERVALS_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_TIME_INTERVALS_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @Column(name = "start_time") // FIXME: type mapping needed?
     public Date getStartTime() {
-        return startTime;
+        return this.startTime;
     }
 
-    public void setStartTime(Date startTime) {
+    public void setStartTime(final Date startTime) {
         this.startTime = startTime;
     }
 
     @Column(name = "stop_time") // FIXME: type mapping needed?
     public Date getStopTime() {
-        return stopTime;
+        return this.stopTime;
     }
 
-    public void setStopTime(Date stopTime) {
+    public void setStopTime(final Date stopTime) {
         this.stopTime = stopTime;
     }
 }
--- a/backend/src/main/java/org/dive4elements/river/model/Wst.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/Wst.java	Fri Jul 13 11:56:22 2018 +0200
@@ -12,26 +12,24 @@
 import java.math.BigDecimal;
 import java.util.List;
 
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
 import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
+import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
-import javax.persistence.OneToMany;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
 import org.hibernate.SQLQuery;
-import org.hibernate.Query;
+import org.hibernate.Session;
 import org.hibernate.type.StandardBasicTypes;
 
-import org.dive4elements.river.backend.SessionHolder;
-
 
 /** DB-mapped WST. */
 @Entity
@@ -45,22 +43,23 @@
     private River   river;
     private String  description;
     private Integer kind;
+    private String sinfo_selection;
 
     private List<WstColumn> columns;
 
 
     public static final String SQL_SELECT_MINMAX =
-        "select min(q) as minQ, max(q) as maxQ from wst_q_values " +
-        "where wst_id = :wst and not (a > :km or b < :km)";
+            "select min(q) as minQ, max(q) as maxQ from wst_q_values " +
+                    "where wst_id = :wst and not (a > :km or b < :km)";
 
     public Wst() {
     }
 
-    public Wst(River river, String description) {
+    public Wst(final River river, final String description) {
         this(river, description, 0);
     }
 
-    public Wst(River river, String description, Integer kind) {
+    public Wst(final River river, final String description, final Integer kind) {
         this.river       = river;
         this.description = description;
         this.kind        = kind;
@@ -68,56 +67,65 @@
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_WSTS_ID_SEQ",
-        sequenceName   = "WSTS_ID_SEQ",
-        allocationSize = 1)
+            name           = "SEQUENCE_WSTS_ID_SEQ",
+            sequenceName   = "WSTS_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_WSTS_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_WSTS_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "river_id" )
     public River getRiver() {
-        return river;
+        return this.river;
     }
 
-    public void setRiver(River river) {
+    public void setRiver(final River river) {
         this.river = river;
     }
 
     @Column(name = "description")
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
     @Column(name = "kind")
     public Integer getKind() {
-        return kind;
+        return this.kind;
     }
 
-    public void setKind(Integer kind) {
+    public void setKind(final Integer kind) {
         this.kind = kind;
     }
 
+    @Column(name = "sinfo_selection")
+    public String getSInfoSelection() {
+        return this.sinfo_selection;
+    }
+
+    public void setSInfoSelection(final String sinfoSelection) {
+        this.sinfo_selection = sinfoSelection;
+    }
+
     @OneToMany
     @JoinColumn(name="wst_id")
     public List<WstColumn> getColumns() {
-        return columns;
+        return this.columns;
     }
 
-    public void setColumns(List<WstColumn> columns) {
+    public void setColumns(final List<WstColumn> columns) {
         this.columns = columns;
     }
 
@@ -130,8 +138,8 @@
      * @return the min and max Q values of this WST.
      */
     public double[] determineMinMaxQ() {
-        double[] ab = river.determineMinMaxDistance();
-        return determineMinMaxQ(new Range(ab[0], ab[1], river));
+        final double[] ab = this.river.determineMinMaxDistance();
+        return determineMinMaxQ(new Range(ab[0], ab[1], this.river));
     }
 
 
@@ -144,11 +152,11 @@
      *
      * @return the min and max Q values of this WST.
      */
-    public double[] determineMinMaxQ(Range range) {
+    public double[] determineMinMaxQ(final Range range) {
         if (range != null) {
             return determineMinMaxQ(
-                range.getA().doubleValue(),
-                range.getB().doubleValue());
+                    range.getA().doubleValue(),
+                    range.getB().doubleValue());
         }
 
         return null;
@@ -165,22 +173,22 @@
      *
      * @return the min and max Q values of this WST.
      */
-    public double[] determineMinMaxQ(double fromKm, double toKm) {
-        Session session = SessionHolder.HOLDER.get();
+    public double[] determineMinMaxQ(final double fromKm, final double toKm) {
+        final Session session = SessionHolder.HOLDER.get();
 
-        Query query = session.createQuery(
-          "select min(q), max(q) from WstQRange where "
-          + "id in "
-          + " (select wstQRange.id from WstColumnQRange where "
-          + "  wstColumn.id in (select id from WstColumn where wst.id = :wst)) "
-          + "and range.id in "
-          + " (select id from Range where not (a > :end or b < :start))");
+        final Query query = session.createQuery(
+                "select min(q), max(q) from WstQRange where "
+                        + "id in "
+                        + " (select wstQRange.id from WstColumnQRange where "
+                        + "  wstColumn.id in (select id from WstColumn where wst.id = :wst)) "
+                        + "and range.id in "
+                        + " (select id from Range where not (a > :end or b < :start))");
 
         query.setParameter("wst",   getId());
         query.setParameter("start", new BigDecimal(fromKm));
         query.setParameter("end",   new BigDecimal(toKm));
 
-        List<Object []> results = query.list();
+        final List<Object []> results = query.list();
 
         if (results.isEmpty()) {
             return null;
@@ -191,32 +199,32 @@
             return null;
         }
 
-        Object [] result = results.get(0);
+        final Object [] result = results.get(0);
 
         return new double [] {
-            ((BigDecimal)result[0]).doubleValue(),
-            ((BigDecimal)result[1]).doubleValue() };
+                ((BigDecimal)result[0]).doubleValue(),
+                ((BigDecimal)result[1]).doubleValue() };
     }
 
 
-    public double[] determineMinMaxQFree(double km) {
-        Session session = SessionHolder.HOLDER.get();
+    public double[] determineMinMaxQFree(final double km) {
+        final Session session = SessionHolder.HOLDER.get();
 
-        SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_MINMAX)
-            .addScalar("minQ", StandardBasicTypes.DOUBLE)
-            .addScalar("maxQ", StandardBasicTypes.DOUBLE);
+        final SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_MINMAX)
+                .addScalar("minQ", StandardBasicTypes.DOUBLE)
+                .addScalar("maxQ", StandardBasicTypes.DOUBLE);
 
         sqlQuery.setInteger("wst", getId());
         sqlQuery.setDouble("km", km);
 
-        List<Object[]> minmaxQ = sqlQuery.list();
+        final List<Object[]> minmaxQ = sqlQuery.list();
 
 
         if (minmaxQ.isEmpty()) {
             return null;
         }
 
-        Object[] mm = minmaxQ.get(0);
+        final Object[] mm = minmaxQ.get(0);
 
         if (mm[0] == null || mm[1] == null) {
             log.warn("No min/max Q for km " + km + " found.");
--- a/backend/src/main/java/org/dive4elements/river/model/WstColumnQRange.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/backend/src/main/java/org/dive4elements/river/model/WstColumnQRange.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,15 +10,15 @@
 
 import java.io.Serializable;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
 import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
 import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
-import javax.persistence.OneToOne;
-import javax.persistence.JoinColumn;
+import javax.persistence.Table;
 
 @Entity
 @Table(name = "wst_column_q_ranges")
@@ -33,47 +33,46 @@
     }
 
     public WstColumnQRange(
-        WstColumn wstColumn,
-        WstQRange wstQRange
-    ) {
+            final WstColumn wstColumn,
+            final WstQRange wstQRange
+            ) {
         this.wstColumn = wstColumn;
         this.wstQRange = wstQRange;
     }
 
     @Id
     @SequenceGenerator(
-        name           = "SEQUENCE_WST_Q_RANGES_ID_SEQ",
-        sequenceName   = "WST_Q_RANGES_ID_SEQ",
-        allocationSize = 1)
+            name = "SEQUENCE_WST_COLUMN_Q_RANGES_ID_SEQ", sequenceName = "WST_COLUMN_Q_RANGES_ID_SEQ",
+            allocationSize = 1)
     @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_WST_Q_RANGES_ID_SEQ")
+            strategy  = GenerationType.SEQUENCE,
+            generator = "SEQUENCE_WST_COLUMN_Q_RANGES_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "wst_column_id" )
     public WstColumn getWstColumn() {
-        return wstColumn;
+        return this.wstColumn;
     }
 
-    public void setWstColumn(WstColumn wstColumn) {
+    public void setWstColumn(final WstColumn wstColumn) {
         this.wstColumn = wstColumn;
     }
 
     @OneToOne
     @JoinColumn(name = "wst_q_range_id" )
     public WstQRange getWstQRange() {
-        return wstQRange;
+        return this.wstQRange;
     }
 
-    public void setWstQRange(WstQRange wstQRange) {
+    public void setWstQRange(final WstQRange wstQRange) {
         this.wstQRange = wstQRange;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/BedMobility.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,154 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table bed_mobility
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+
+@Entity
+@Table(name = "bed_mobility")
+public class BedMobility implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -2315936652180822551L;
+
+    private Integer id;
+
+    private String kmrange_info;
+
+    private String filename;
+
+    private String notes;
+
+    private River river;
+
+    private List<BedMobilityValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public BedMobility() {
+    }
+
+
+    public BedMobility(final River river, final String filename, final String kmrange_info, final String notes) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.values = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_BED_MOBILITY_ID_SEQ", sequenceName = "BED_MOBILITY_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_BED_MOBILITY_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "bed_mobility_id")
+    public List<BedMobilityValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<BedMobilityValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final BedMobilityValue value) {
+        this.values.add(value);
+    }
+
+    /**
+     * Selects a bed mobility series of a river from the database
+     */
+    public static BedMobility queryForRiver(final River river) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM BedMobility WHERE river=:river");
+        query.setParameter("river", river);
+        final List<BedMobility> rows = query.list();
+        if (rows != null)
+            return rows.get(0);
+        else
+            return null;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/BedMobilityValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,127 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+
+/**
+ * Hibernate binding for the DB table bed_mobility_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "bed_mobility_values")
+public class BedMobilityValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 1784382276688203055L;
+
+    private Integer id;
+
+    private BedMobility bedMobility;
+
+    private Double station;
+
+    private int moving; /* 0 or 1 */
+
+
+    /***** CONSTRUCTORS *****/
+
+    public BedMobilityValue() {
+    }
+
+    public BedMobilityValue(final BedMobility bedMobility, final Double station, final int bedMoving) {
+        this.bedMobility = bedMobility;
+        this.station = station;
+        this.moving = bedMoving;
+    }
+
+    /**
+     * Parameter constructor with primitive double km and boolean
+     */
+    public BedMobilityValue(final BedMobility bedMobility, final double km, final boolean bedMoving) {
+        this(bedMobility, Double.valueOf(km), (bedMoving ? 1 : 0));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_BED_MOBILITY_VALUE_ID_SEQ", sequenceName = "BED_MOBILITY_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_BED_MOBILITY_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "bed_mobility_id")
+    public BedMobility getBedMobility() {
+        return this.bedMobility;
+    }
+
+    public void setBedMobility(final BedMobility bedMobility) {
+        this.bedMobility = bedMobility;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @Column(name = "moving")
+    public int getMoving() {
+        return this.moving;
+    }
+
+    public void setMoving(final int bedMoving) {
+        this.moving = bedMoving;
+    }
+
+    /**
+     * Selects the bed mobility of a series in a km range from the database
+     */
+    public static List<BedMobilityValue> getValues(final BedMobility parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM BedMobilityValue WHERE (bedMobility=:parent)"
+                + " AND (station >= :kmLo - 0.0001) AND (station <= :kmHi + 0.0001)");
+        query.setParameter("parent", parent);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        return query.list();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/Channel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,173 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table channel
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+
+@Entity
+@Table(name = "channel")
+public class Channel implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 4845405421049630551L;
+
+    private Integer id;
+
+    private River river;
+
+    private String kmrange_info;
+
+    private String filename;
+
+    private String notes;
+
+    private Integer year_from;
+
+    private Integer year_to;
+
+    private List<ChannelValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public Channel() {
+    }
+
+    public Channel(final River river, final String filename, final String kmrange_info, final String notes, final Integer year_from, final Integer year_to) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.setYear_from(year_from);
+        this.setYear_to(year_to);
+        this.values = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_CHANNEL_ID_SEQ", sequenceName = "CHANNEL_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_CHANNEL_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @Column(name = "year_from")
+    public Integer getYear_from() {
+        return this.year_from;
+    }
+
+    public void setYear_from(final Integer year_from) {
+        this.year_from = year_from;
+    }
+
+    @Column(name = "year_to")
+    public Integer getYear_to() {
+        return this.year_to;
+    }
+
+    public void setYear_to(final Integer year_to) {
+        this.year_to = year_to;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "channel_id")
+    public List<ChannelValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<ChannelValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final ChannelValue value) {
+        this.values.add(value);
+    }
+
+    /**
+     * Get data series by id
+     */
+    public static Channel getSeries(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM Channel WHERE (id=:id)");
+        query.setParameter("id", id);
+        return (Channel) query.list().get(0);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/ChannelValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,139 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+
+/**
+ * Hibernate binding for the DB table channel_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "channel_values")
+public class ChannelValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -3793243094875530557L;
+
+    private Integer id;
+
+    private Channel channel;
+
+    private Double station;
+
+    private Double width;
+
+    private Double depth;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public ChannelValue() {
+    }
+
+    public ChannelValue(final Channel channel, final Double station, final Double width, final Double depth) {
+        this.channel = channel;
+        this.station = station;
+        this.width = width;
+        this.depth = depth;
+    }
+
+    /**
+     * Parameter constructor with primitive parameter types
+     */
+    public ChannelValue(final Channel channel, final double km, final double width, final double depth) {
+        this(channel, Double.valueOf(km), Double.valueOf(width), Double.valueOf(depth));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_CHANNEL_VALUE_ID_SEQ", sequenceName = "CHANNEL_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_CHANNEL_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "channel_id")
+    public Channel getChannel() {
+        return this.channel;
+    }
+
+    public void setChannel(final Channel channel) {
+        this.channel = channel;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @Column(name = "width")
+    public Double getWidth() {
+        return this.width;
+    }
+
+    public void setWidth(final Double width) {
+        this.width = width;
+    }
+
+    @Column(name = "depth")
+    public Double getDepth() {
+        return this.depth;
+    }
+
+    public void setDepth(final Double depth) {
+        this.depth = depth;
+    }
+
+    /**
+     * Selects the channel size values of a data series in a km range from the database
+     */
+    public static List<ChannelValue> getValues(final Channel parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM ChannelValue WHERE (channel=:parent)"
+                + " AND (station >= :kmLo - 0.0001) AND (station <= :kmHi + 0.0001)");
+        query.setParameter("parent", parent);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        return query.list();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/Collision.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,182 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table collision
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+@Entity
+@Table(name = "collision")
+public class Collision implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -6950745885816251322L;
+
+    private Integer id;
+
+    private River river;
+
+    private String filename;
+
+    private String kmrange_info;
+
+    private String notes;
+
+    private Integer year;
+
+    private List<CollisionValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public Collision() {
+    }
+
+
+    public Collision(final River river, final String filename, final String kmrange_info, final String notes, final Integer year) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.year = year;
+        this.values = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_COLLISION_ID_SEQ", sequenceName = "COLLISION_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_COLLISION_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @Column(name = "year")
+    public Integer getYear() {
+        return this.year;
+    }
+
+    public void setYear(final Integer year) {
+        this.year = year;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "collision_id")
+    public List<CollisionValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<CollisionValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final CollisionValue value) {
+        this.values.add(value);
+    }
+
+    /**
+     * Get data series by id
+     */
+    public static Collision getSeries(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM Collision WHERE (id=:id)");
+        query.setParameter("id", id);
+        return (Collision) query.list().get(0);
+    }
+
+    /**
+     * Selects from the database the years of the collisions of a river
+     */
+    public static List<Integer> getYearsOfRiver(final River river) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("SELECT c.year, COUNT(cv) AS count"
+                + " FROM Collision c INNER JOIN c.values cv"
+                + " WHERE c.river=:river"
+                + " GROUP BY c.year"
+                + " ORDER BY c.year");
+        query.setParameter("river", river);
+        final List<Integer> years = new ArrayList<>();
+        final List<Object[]> rows = query.list();
+        if (rows != null) {
+            for (int i = 0; i <= rows.size() - 1; i++) {
+                years.add(Integer.valueOf((int) rows.get(i)[0]));
+            }
+        }
+        return years;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/CollisionAggregateValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,162 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.model.River;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.type.StandardBasicTypes;
+
+
+/**
+ * Aggregation of collision_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class CollisionAggregateValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 1;
+
+    private Collision parent;
+
+    private double station;
+
+    // private CollisionType collisionType;
+
+    private Date minDate;
+
+    private Date maxDate;
+
+    private int count;
+
+    private double gaugeW;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public CollisionAggregateValue() {
+    }
+
+    public CollisionAggregateValue(final Collision collision, final double station, final Date minDate, final Date maxDate, final int count,
+            final double gaugeW) {
+        this.parent = collision;
+        this.station = station;
+        // this.collisionType = collisionType;
+        this.minDate = minDate;
+        this.maxDate = maxDate;
+        this.count = count;
+        this.gaugeW = gaugeW;
+    }
+
+
+    /***** METHODS *****/
+
+    public int getCount() {
+        return this.count;
+    }
+
+    public Collision getCollision() {
+        return this.parent;
+    }
+
+    public double getStation() {
+        return this.station;
+    }
+
+    // public CollisionType getCollisionType() {
+    // return this.collisionType;
+    // }
+
+    public Date getMinDate() {
+        return this.minDate;
+    }
+
+    public Date getMaxDate() {
+        return this.maxDate;
+    }
+
+    public Double getGaugeW() {
+        return this.gaugeW;
+    }
+
+    /**
+     * Selects from the database the collision aggregate values of a data series in a km range
+     */
+    public static List<CollisionAggregateValue> getValuesByKm(final Collision parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final SQLQuery query = session.createSQLQuery("SELECT FLOOR(station+0.4999) AS station, COUNT(*) AS count,"
+                + " MIN(event_date) AS date_min, MAX(event_date) AS date_max,"
+                + "  AVG(gauge_w) AS gauge_w"
+                + " FROM collision_values v INNER JOIN collision s ON v.collision_id=s.id"
+                + " WHERE (collision_id=:parent)"
+                + " AND (station BETWEEN (:kmLo - 0.0001) AND (:kmHi + 0.0001))"
+                + " GROUP BY FLOOR(station+0.4999)"
+                + " ORDER BY FLOOR(station+0.4999)")
+                .addScalar("station", StandardBasicTypes.DOUBLE).addScalar("count", StandardBasicTypes.INTEGER)
+                .addScalar("date_min", StandardBasicTypes.DATE).addScalar("date_max", StandardBasicTypes.DATE)
+                .addScalar("gauge_w", StandardBasicTypes.DOUBLE);
+        query.setInteger("parent", parent.getId());
+        query.setDouble("kmLo", new Double(kmLo));
+        query.setDouble("kmHi", new Double(kmHi));
+        final List<CollisionAggregateValue> values = new ArrayList();
+        final List<Object[]> rows = query.list();
+        if (rows != null) {
+            for (int i = 0; i <= rows.size() - 1; i++) {
+                values.add(new CollisionAggregateValue(parent, (double) rows.get(i)[0], (Date) rows.get(i)[2], (Date) rows.get(i)[3],
+                        (int) rows.get(i)[1], (double) rows.get(i)[4]));
+            }
+        }
+        return values;
+    }
+    
+    /**
+     * Selects from the database the collision aggregate values of a km range of a river and a range of years
+     */
+    public static List<CollisionAggregateValue> getValuesByKm(final River river, final double kmLo, final double kmHi, final int fromYear, final int toYear) {
+        final Session session = SessionHolder.HOLDER.get();
+        final SQLQuery query = session.createSQLQuery("SELECT FLOOR(station+0.4999) AS station, COUNT(*) AS count,"
+                + " MIN(event_date) AS date_min, MAX(event_date) AS date_max,"
+                + "  AVG(gauge_w) AS gauge_w"
+                + " FROM collision_values v INNER JOIN collision s ON v.collision_id=s.id"
+                + " WHERE (s.river_id=:river_id)"
+                + " AND (station BETWEEN (:kmLo - 0.0001) AND (:kmHi + 0.0001))"
+                + " AND (event_date BETWEEN :fromDate AND :toDate)"
+                + " GROUP BY FLOOR(station+0.4999)"
+                + " ORDER BY FLOOR(station+0.4999)")
+                .addScalar("station", StandardBasicTypes.DOUBLE).addScalar("count", StandardBasicTypes.INTEGER)
+                .addScalar("date_min", StandardBasicTypes.DATE).addScalar("date_max", StandardBasicTypes.DATE)
+                .addScalar("gauge_w", StandardBasicTypes.DOUBLE);
+        query.setInteger("river_id", river.getId());
+        query.setDouble("kmLo", new Double(kmLo));
+        query.setDouble("kmHi", new Double(kmHi));
+        query.setDate("fromDate", DateUtil.getStartDateFromYear(fromYear));
+        query.setDate("toDate", DateUtil.getEndDateFromYear(toYear));
+        final List<CollisionAggregateValue> values = new ArrayList();
+        final List<Object[]> rows = query.list();
+        if (rows != null) {
+            for (int i = 0; i <= rows.size() - 1; i++) {
+                values.add(new CollisionAggregateValue(null, (double) rows.get(i)[0], (Date) rows.get(i)[2], (Date) rows.get(i)[3],
+                        (int) rows.get(i)[1], (double) rows.get(i)[4]));
+            }
+        }
+        return values;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/CollisionType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,82 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+@Entity
+@Table(name = "collision_type")
+public class CollisionType implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -865783384903507910L;
+
+    private Integer id;
+
+    private String  name;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public CollisionType() {
+    }
+
+    public CollisionType(final String name) {
+        this.name = name;
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_COLLISION_TYPE_ID_SEQ", sequenceName = "COLLISION_TYPE_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_COLLISION_TYPE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @Column(name = "name")
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Queries all collision types from the database, orders by name
+     */
+    public static List<CollisionType> getTypes() {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM CollisionType ORDER BY name");
+        return new ArrayList<>(query.list());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/CollisionValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,202 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.SQLQuery;
+import org.hibernate.Session;
+import org.hibernate.type.StandardBasicTypes;
+
+
+/**
+ * Hibernate binding for the DB table collision_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "collision_values")
+public class CollisionValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -1157324854470346513L;
+
+    private Integer id;
+
+    private Collision collision;
+
+    private Double station;
+
+    private CollisionType collisionType;
+
+    private Date eventDate;
+
+    private String gaugeName;
+
+    private Double gaugeW;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public CollisionValue() {
+    }
+
+    public CollisionValue(final Collision collision, final Double station, final CollisionType collisionType, final Date eventDate, final String gaugeName,
+            final Double gaugeW) {
+        this.collision = collision;
+        this.station = station;
+        this.collisionType = collisionType;
+        this.eventDate = eventDate;
+        this.gaugeName = gaugeName;
+        this.gaugeW = gaugeW;
+    }
+
+    /**
+     * Constructor with primitive parameter types
+     */
+    public CollisionValue(final Collision collision, final double km, final CollisionType collisionType, final Date eventDate, final String gaugeName,
+            final double gaugeW) {
+        this(collision, Double.valueOf(km), collisionType, eventDate, gaugeName, Double.valueOf(gaugeW));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_COLLISION_VALUE_ID_SEQ", sequenceName = "COLLISION_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_COLLISION_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "collision_id")
+    public Collision getCollision() {
+        return this.collision;
+    }
+
+    public void setCollision(final Collision collision) {
+        this.collision = collision;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "collision_type_id")
+    public CollisionType getCollisionType() {
+        return this.collisionType;
+    }
+
+    public void setCollisionType(final CollisionType collisionType) {
+        this.collisionType = collisionType;
+    }
+
+    @Column(name = "event_date")
+    public Date getEventDate() {
+        return this.eventDate;
+    }
+
+    public void setEventDate(final Date eventDate) {
+        this.eventDate = eventDate;
+    }
+
+    @Column(name = "gauge_name")
+    public String getGaugeName() {
+        return this.gaugeName;
+    }
+
+    public void setGaugeName(final String gaugeName) {
+        this.gaugeName = gaugeName;
+    }
+
+    @Column(name = "gauge_w")
+    public Double getGaugeW() {
+        return this.gaugeW;
+    }
+
+    public void setGaugeW(final Double gaugeW) {
+        this.gaugeW = gaugeW;
+    }
+
+    /**
+     * Selects the collision values of a data series in a km range from the database
+     */
+    public static List<CollisionValue> getValues(final Collision parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM CollisionValue WHERE (collision=:parent)"
+                + " AND (station >= :kmLo - 0.0001) AND (station <= :kmHi + 0.0001)");
+        query.setParameter("parent", parent);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        return query.list();
+    }
+    /**
+     * Selects from the database the collision values of a km range of a river and a date range
+     */
+    public static List<CollisionValue> getValues(final River river, final double kmLo, final double kmHi, final Date fromDate, final Date toDate) {
+        final Session session = SessionHolder.HOLDER.get();
+        final SQLQuery query = session.createSQLQuery("SELECT station, event_date, gauge_w, gauge_name, ct.name AS collisiontype"
+                + " FROM collision_values v INNER JOIN collision s ON v.collision_id=s.id"
+                + " INNER JOIN collision_type ct ON v.collision_type_id=ct.id"
+                + " WHERE (s.river_id=:river_id)"
+                + " AND (station BETWEEN (:kmLo - 0.0001) AND (:kmHi + 0.0001))"
+                + " AND (event_date BETWEEN :fromDate AND :toDate)"
+                + " ORDER BY station, event_date")
+                .addScalar("station", StandardBasicTypes.DOUBLE)
+                .addScalar("event_date", StandardBasicTypes.DATE)
+                .addScalar("gauge_w", StandardBasicTypes.DOUBLE)
+                .addScalar("gauge_name", StandardBasicTypes.STRING)
+                .addScalar("collisiontype", StandardBasicTypes.STRING);
+        query.setInteger("river_id", river.getId());
+        query.setDouble("kmLo", new Double(kmLo));
+        query.setDouble("kmHi", new Double(kmHi));
+        query.setDate("fromDate", fromDate);
+        query.setDate("toDate", toDate);
+        return buildCollisionValueList(query.list());
+    }
+
+    private static List<CollisionValue> buildCollisionValueList(final List<Object[]> rows) {
+        final List<CollisionValue> values = new ArrayList<>();
+        for (int i = 0; i <= rows.size() - 1; i++)
+            values.add(new CollisionValue(null, (double) rows.get(i)[0], null, (Date) rows.get(i)[1], (String) rows.get(i)[3], (double) rows.get(i)[2]));
+        return values;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/DailyDischarge.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,147 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.model.Gauge;
+
+/**
+ * Hibernate binding for the DB table daily_discharge
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+
+@Entity
+@Table(name = "daily_discharge")
+public class DailyDischarge implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -3687154040155547884L;
+
+    private Integer id;
+
+    // private String kmrange_info;
+
+    private String filename;
+
+    // private String notes;
+
+    private Gauge gauge;
+
+    private List<DailyDischargeValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DailyDischarge() {
+    }
+
+
+    public DailyDischarge(final Gauge gauge, final String filename, final String notes) {
+        this.gauge = gauge;
+        // this.river = river;
+        this.filename = filename;
+        // this.notes = notes;
+        this.values = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_DAILY_DISCHARGE_ID_SEQ", sequenceName = "DAILY_DISCHARGE_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_DAILY_DISCHARGE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    // @OneToOne
+    // @JoinColumn(name = "river_id")
+    // public River getRiver() {
+    // return this.river;
+    // }
+
+    // public void setRiver(final River river) {
+    // this.river = river;
+    // }
+
+    @OneToOne
+    @JoinColumn(name = "gauge_id")
+    public Gauge getGauge() {
+        return this.gauge;
+    }
+
+    public void setGauge(final Gauge gauge) {
+        this.gauge = gauge;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    // @Column(name = "kmrange_info")
+    // public String getKmrange_info() {
+    // return this.kmrange_info;
+    // }
+
+    // public void setKmrange_info(final String kmrange_info) {
+    // this.kmrange_info = kmrange_info;
+    // }
+
+    // @Column(name = "notes")
+    // public String getNotes() {
+    // return this.notes;
+    // }
+
+    // public void setNotes(final String notes) {
+    // this.notes = notes;
+    // }
+
+    @OneToMany
+    @JoinColumn(name = "daily_discharge_id")
+    public List<DailyDischargeValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<DailyDischargeValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final DailyDischargeValue value) {
+        this.values.add(value);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/DailyDischargeValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,110 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+
+/**
+ * Hibernate binding for the DB table daily_discharge_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "daily_discharge_values")
+public class DailyDischargeValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -6192738825193230784L;
+
+    private Integer id;
+
+    private DailyDischarge dailyDischarge;
+
+    private Date day;
+
+    private Double discharge;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DailyDischargeValue() {
+    }
+
+    public DailyDischargeValue(final DailyDischarge dailyDischarge, final Date day, final Double discharge) {
+        this.dailyDischarge = dailyDischarge;
+        this.day = day;
+        this.discharge = discharge;
+    }
+
+    /**
+     * Parameter constructor with primitive parameter types
+     */
+    public DailyDischargeValue(final DailyDischarge dailyDischarge, final Date day, final double discharge) {
+        this(dailyDischarge, day, Double.valueOf(discharge));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_DAILY_DISCHARGE_VALUE_ID_SEQ", sequenceName = "DAILY_DISCHARGE_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_DAILY_DISCHARGE_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "daily_discharge_id")
+    public DailyDischarge getDailyDischarge() {
+        return this.dailyDischarge;
+    }
+
+    public void setDailyDischarge(final DailyDischarge dailyDischarge) {
+        this.dailyDischarge = dailyDischarge;
+    }
+
+    @Column(name = "discharge")
+    public Double getDischarge() {
+        return this.discharge;
+    }
+
+    public void setDischarge(final Double discharge) {
+        this.discharge = discharge;
+    }
+
+    @Column(name = "day")
+    public Date getDay() {
+        return this.day;
+    }
+
+    public void setDay(final Date day) {
+        this.day = day;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/DepthEvolution.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,279 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table depth_evolution
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+@Entity
+@Table(name = "depth_evolution")
+public class DepthEvolution implements Serializable {
+
+    /***** TYPES *****/
+
+    /**
+     * Possible values of the groupname column
+     *
+     */
+    public enum Group {
+        NONE(""), AKTUELL("aktuell"), ETAPPE("etappe");
+
+        private final String dbvalue;
+
+        Group(final String dbvalue) {
+            this.dbvalue = dbvalue;
+        }
+
+        /**
+         * Value of the group's groupname column
+         */
+        public String getDbValue() {
+            return this.dbvalue;
+        }
+
+        /**
+         * Group for a groupname column value
+         */
+        public static Group forDbValue(final String dbvalue) {
+            for (final Group g : Group.values()) {
+                if (g.getDbValue().equals(dbvalue))
+                    return g;
+            }
+            return Group.NONE;
+        }
+    }
+
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 2665718161356165179L;
+
+    private Integer id;
+
+    private River river;
+
+    private String kmrange_info;
+
+    private String filename;
+
+    private transient Group group;
+
+    private String notes;
+
+    private Integer start_year;
+
+    private Integer reference_year;
+
+    private String curr_sounding;
+
+    private String old_sounding;
+
+    private String curr_glw;
+
+    private String old_glw;
+
+    private List<DepthEvolutionValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DepthEvolution() {
+    }
+
+    public DepthEvolution(final River river, final String filename, final String kmrange_info, final String notes, final Integer start_year,
+            final Integer reference_year, final String curr_sounding, final String old_sounding, final String curr_glw, final String old_glw,
+            final Group group) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.setStart_year(start_year);
+        this.setReference_year(reference_year);
+        this.curr_sounding = curr_sounding;
+        this.old_sounding = old_sounding;
+        this.curr_glw = curr_glw;
+        this.old_glw = old_glw;
+        this.group = group;
+        this.values = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_DEPTH_EVOLUTION_ID_SEQ", sequenceName = "DEPTH_EVOLUTION_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_DEPTH_EVOLUTION_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "groupname")
+    public String getGroupname() {
+        return this.group.getDbValue();
+    }
+
+    public void setGroupname(final String groupname) {
+        this.group = Group.forDbValue(groupname);
+    }
+
+    @Transient
+    public Group getGroup() {
+        return this.group;
+    }
+
+    public void setGroup(final Group group) {
+        this.group = group;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @Column(name = "start_year")
+    public Integer getStart_year() {
+        return this.start_year;
+    }
+
+    public void setStart_year(final Integer start_year) {
+        this.start_year = start_year;
+    }
+
+    @Column(name = "reference_year")
+    public Integer getReference_year() {
+        return this.reference_year;
+    }
+
+    public void setReference_year(final Integer reference_year) {
+        this.reference_year = reference_year;
+    }
+
+    @Column(name = "curr_sounding")
+    public String getCurr_sounding() {
+        return this.curr_sounding;
+    }
+
+    public void setCurr_sounding(final String curr_sounding) {
+        this.curr_sounding = curr_sounding;
+    }
+
+    @Column(name = "old_sounding")
+    public String getOld_sounding() {
+        return this.old_sounding;
+    }
+
+    public void setOld_sounding(final String old_sounding) {
+        this.old_sounding = old_sounding;
+    }
+
+    @Column(name = "curr_glw")
+    public String getCurr_glw() {
+        return this.curr_glw;
+    }
+
+    public void setCurr_glw(final String curr_glw) {
+        this.curr_glw = curr_glw;
+    }
+
+    @Column(name = "old_glw")
+    public String getOld_glw() {
+        return this.old_glw;
+    }
+
+    public void setOld_glw(final String old_glw) {
+        this.old_glw = old_glw;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "depth_evolution_id")
+    public List<DepthEvolutionValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<DepthEvolutionValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final DepthEvolutionValue value) {
+        this.values.add(value);
+    }
+
+    /**
+     * Get data series by id
+     */
+    public static DepthEvolution getSeries(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM DepthEvolution WHERE (id=:id)");
+        query.setParameter("id", id);
+        return (DepthEvolution) query.list().get(0);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/DepthEvolutionValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,156 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+
+/**
+ * Hibernate binding for the DB table depth_evolution_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "depth_evolution_values")
+public class DepthEvolutionValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 3164888119107103560L;
+
+    private Integer id;
+
+    private DepthEvolution depth_evolution;
+
+    private Double station;
+
+    private Double total_change;
+
+    private Double change_per_year;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public DepthEvolutionValue() {
+    }
+
+    public DepthEvolutionValue(final DepthEvolution depth_evolution, final Double station, final Double total_change, final Double change_per_year) {
+        this.depth_evolution = depth_evolution;
+        this.station = station;
+        this.total_change = total_change;
+        this.change_per_year = change_per_year;
+    }
+
+    /**
+     * Parameter constructor with primitive parameter types
+     */
+    public DepthEvolutionValue(final DepthEvolution depth_evolution, final double km, final double total_change, final double change_per_year) {
+        this(depth_evolution, Double.valueOf(km), Double.valueOf(total_change), Double.valueOf(change_per_year));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_DEPTH_EVOLUTION_VALUE_ID_SEQ", sequenceName = "DEPTH_EVOLUTION_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_DEPTH_EVOLUTION_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "depth_evolution_id")
+    public DepthEvolution getDepthEvolution() {
+        return this.depth_evolution;
+    }
+
+    public void setDepthEvolution(final DepthEvolution depth_evolution) {
+        this.depth_evolution = depth_evolution;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @Column(name = "total_change")
+    public Double getTotal_change() {
+        return this.total_change;
+    }
+
+    public void setTotal_change(final Double total_change) {
+        this.total_change = total_change;
+    }
+
+    @Transient
+    public Double getTotalChangeCm() {
+        if (getTotal_change() != null)
+            return getTotal_change() * 100;
+        else
+            return null;
+    }
+
+    @Column(name = "change_per_year")
+    public Double getChange_per_year() {
+        return this.change_per_year;
+    }
+
+    public void setChange_per_year(final Double change_per_year) {
+        this.change_per_year = change_per_year;
+    }
+
+    @Transient
+    public Double getPerYearChangeCm() {
+        if (getChange_per_year() != null)
+            return getChange_per_year() * 100;
+        else
+            return null;
+    }
+
+    /**
+     * Selects the depth evolution values of a data series in a km range from the database
+     */
+    public static List<DepthEvolutionValue> getValues(final DepthEvolution parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM DepthEvolutionValue WHERE (depthEvolution=:parent)"
+                + " AND (station >= :kmLo - 0.0001) AND (station <= :kmHi + 0.0001)");
+        query.setParameter("parent", parent);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        return query.list();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/FlowDepth.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,173 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.model.River;
+
+/**
+ * Hibernate binding for the DB table flow_depth
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+@Entity
+@Table(name = "flow_depth")
+public class FlowDepth implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -1643015200580514950L;
+
+    private Integer id;
+
+    private River river;
+
+    private String filename;
+
+    private String kmrange_info;
+
+    private String notes;
+
+    private Integer year;
+
+    private String sounding_info;
+
+    private String evaluation_by;
+
+    private List<FlowDepthColumn> columns;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public FlowDepth() {
+    }
+
+
+    public FlowDepth(final River river, final String filename, final String kmrange_info, final String notes, final Integer year, final String sounding_info,
+            final String evaluation_by) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.year = year;
+        this.setSounding_info(sounding_info);
+        this.setEvaluation_by(evaluation_by);
+        this.columns = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_FLOW_DEPTH_ID_SEQ", sequenceName = "FLOW_DEPTH_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_FLOW_DEPTH_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @Column(name = "year")
+    public Integer getYear() {
+        return this.year;
+    }
+
+    public void setYear(final Integer year) {
+        this.year = year;
+    }
+
+    @Column(name = "sounding_info")
+    public String getSounding_info() {
+        return this.sounding_info;
+    }
+
+    public void setSounding_info(final String sounding_info) {
+        this.sounding_info = sounding_info;
+    }
+
+    @Column(name = "evaluation_by")
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "flow_depth_id")
+    public List<FlowDepthColumn> getColumns() {
+        return this.columns;
+    }
+
+    public void setColumns(final List<FlowDepthColumn> values) {
+        this.columns = values;
+    }
+
+    public void addColumn(final FlowDepthColumn value) {
+        this.columns.add(value);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/FlowDepthColumn.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,127 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table flow_depth_column
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "flow_depth_column")
+public class FlowDepthColumn implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -8164345503234852700L;
+
+    private Integer id;
+
+    private FlowDepth parent;
+
+    private String  name;
+
+    private List<FlowDepthValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public FlowDepthColumn() {
+    }
+
+    public FlowDepthColumn(final FlowDepth parent, final String name) {
+        this.parent = parent;
+        this.name = name;
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_FLOW_DEPTH_COLUMN_ID_SEQ", sequenceName = "FLOW_DEPTH_COLUMN_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_FLOW_DEPTH_COLUMN_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "flow_depth_id")
+    public FlowDepth getFlowDepth() {
+        return this.parent;
+    }
+
+    @Transient
+    public FlowDepth getSeries() {
+        return getFlowDepth();
+    }
+
+    public void setFlowDepth(final FlowDepth flow_depth) {
+        this.parent = flow_depth;
+    }
+
+    @Column(name = "name")
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "flow_depth_column_id")
+    public List<FlowDepthValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<FlowDepthValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final FlowDepthValue value) {
+        this.values.add(value);
+    }
+
+    /**
+     * Selects a flow depth series column by id from the database
+     */
+    public static FlowDepthColumn getColumnById(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM FlowDepthColumn WHERE id=:id");
+        query.setParameter("id", id);
+        final List<FlowDepthColumn> rows = query.list();
+        return ((rows != null) && !rows.isEmpty()) ? rows.get(0) : null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/FlowDepthValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,130 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+
+/**
+ * Hibernate binding for the DB table flow_depth_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "flow_depth_values")
+public class FlowDepthValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -7465899199734466657L;
+
+    private Integer id;
+
+    private FlowDepthColumn flowDepthColumn;
+
+    private Double station;
+
+    /**
+     * Flow depth in m
+     */
+    private Double depth;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public FlowDepthValue() {
+    }
+
+    public FlowDepthValue(final FlowDepthColumn flowDepthColumn, final Double station, final Double depth) {
+        this.flowDepthColumn = flowDepthColumn;
+        this.station = station;
+        this.depth = depth;
+    }
+
+    /**
+     * Constructor with primitive parameter types
+     */
+    public FlowDepthValue(final FlowDepthColumn flow_depthColumn, final double km, final double depth) {
+        this(flow_depthColumn, Double.valueOf(km), Double.valueOf(depth));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_FLOW_DEPTH_VALUE_ID_SEQ", sequenceName = "FLOW_DEPTH_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_FLOW_DEPTH_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "flow_depth_column_id")
+    public FlowDepthColumn getFlowDepthColumn() {
+        return this.flowDepthColumn;
+    }
+
+    public void setFlowDepthColumn(final FlowDepthColumn flow_depth) {
+        this.flowDepthColumn = flow_depth;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @Column(name = "depth")
+    public Double getDepth() {
+        return this.depth;
+    }
+
+    public void setDepth(final Double depth) {
+        this.depth = depth;
+    }
+
+    /**
+     * Selects the flow depth values of a flow depth series column in a km range from the database
+     */
+    public static List<FlowDepthValue> getValues(final FlowDepthColumn parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM FlowDepthValue WHERE (flowDepthColumn=:parent)"
+                + " AND (station >= :kmLo - 0.0001) AND (station <= :kmHi + 0.0001)");
+        query.setParameter("parent", parent);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        return query.list();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/Infrastructure.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,216 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.AnnotationType;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table infrastructure
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+@Entity
+@Table(name = "infrastructure")
+public class Infrastructure implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -5505080011501611034L;
+
+    private Integer id;
+
+    private River river;
+
+    private String filename;
+
+    private String kmrange_info;
+
+    private String notes;
+
+    private AnnotationType type;
+
+    private Integer year;
+
+    private String dataprovider;
+
+    private String evaluation_by;
+
+    private List<InfrastructureValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public Infrastructure() {
+    }
+
+
+    public Infrastructure(final River river, final String filename, final String kmrange_info, final String notes, final AnnotationType type,
+            final Integer year,
+            final String dataprovider, final String evaluation_by) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.type = type;
+        this.year = year;
+        this.dataprovider = dataprovider;
+        this.evaluation_by = evaluation_by;
+        this.values = new ArrayList<>();
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_INFRASTRUCTURE_ID_SEQ", sequenceName = "INFRASTRUCTURE_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_INFRASTRUCTURE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "annotation_type_id")
+    public AnnotationType getType() {
+        return this.type;
+    }
+
+    public void setType(final AnnotationType type) {
+        this.type = type;
+    }
+
+    @Column(name = "year")
+    public Integer getYear() {
+        return this.year;
+    }
+
+    public void setYear(final Integer year) {
+        this.year = year;
+    }
+
+    @Column(name = "dataprovider")
+    public String getDataprovider() {
+        return this.dataprovider;
+    }
+
+    public void setDataprovider(final String dataprovider) {
+        this.dataprovider = dataprovider;
+    }
+
+    @Column(name = "evaluation_by")
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "infrastructure_id")
+    public List<InfrastructureValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<InfrastructureValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final InfrastructureValue value) {
+        this.values.add(value);
+    }
+
+    /**
+     * Get data series by id
+     */
+    public static Infrastructure getSeries(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM Infrastructure WHERE (id=:id)");
+        query.setParameter("id", id);
+        return (Infrastructure) query.list().get(0);
+    }
+
+    /**
+     * Get first data series of a river
+     */
+    public static Infrastructure getSeries(final River river) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM Infrastructure WHERE (river=:river)");
+        query.setParameter("river", river);
+        final List rows = query.list();
+        if (!rows.isEmpty())
+            return (Infrastructure) rows.get(0);
+        else
+            return null;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/InfrastructureValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,170 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.Attribute;
+import org.dive4elements.river.model.Attribute.AttributeKey;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+
+/**
+ * Hibernate binding for the DB table infrastructure_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "infrastructure_values")
+public class InfrastructureValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -3887269325288851829L;
+
+    private Integer id;
+
+    private Infrastructure infrastructure;
+
+    private Double station;
+
+    private Attribute attribute;
+
+    private Double height;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public InfrastructureValue() {
+    }
+
+    public InfrastructureValue(final Infrastructure infrastructure, final Double station, final Attribute attribute, final Double height) {
+        this.infrastructure = infrastructure;
+        this.station = station;
+        this.attribute = attribute;
+        this.height = height;
+    }
+
+    /**
+     * Parameter constructor with primitive double km and height
+     */
+    public InfrastructureValue(final Infrastructure infrastructure, final double km, final Attribute attribute, final double height) {
+        this(infrastructure, Double.valueOf(km), attribute, Double.valueOf(height));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_INFRASTRUCTURE_VALUE_ID_SEQ", sequenceName = "INFRASTRUCTURE_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_INFRASTRUCTURE_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "infrastructure_id")
+    public Infrastructure getInfrastructure() {
+        return this.infrastructure;
+    }
+
+    public void setInfrastructure(final Infrastructure infrastructure) {
+        this.infrastructure = infrastructure;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "attribute_id")
+    public Attribute getAttribute() {
+        return this.attribute;
+    }
+
+    public void setAttribute(final Attribute attribute) {
+        this.attribute = attribute;
+    }
+
+    @Transient
+    public AttributeKey getAttributeKey() {
+        return this.getAttribute().getKey();
+    }
+
+    @Column(name = "height")
+    public Double getHeight() {
+        return this.height;
+    }
+
+    public void setHeight(final Double height) {
+        this.height = height;
+    }
+
+    /**
+     * Selects from the database the infrastructure values of a data series in a km range
+     */
+    public static List<InfrastructureValue> getValues(final Infrastructure parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM InfrastructureValue WHERE (infrastructure=:parent)"
+                + " AND (station >= :kmLo - 0.0001) AND (station <= :kmHi + 0.0001)");
+        query.setParameter("parent", parent);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        return query.list();
+    }
+
+    /**
+     * Selects from the database the infrastructure values of a km range of a river and a river side
+     */
+    public static List<InfrastructureValue> getValues(final River river, final double kmLo, final double kmHi, final AttributeKey riverside) {
+        final Session session = SessionHolder.HOLDER.get();
+        String riversideClause = "";
+        if ((riverside == AttributeKey.LEFT) || (riverside == AttributeKey.RIGHT))
+            riversideClause = " AND (v.attribute.id=:attr_id)";
+        final Query query = session.createQuery("FROM InfrastructureValue v"
+                + " WHERE (v.infrastructure.river=:river)"
+                + " AND (v.station BETWEEN :kmLo - 0.0001 AND :kmHi + 0.0001)"
+                + riversideClause
+                + " ORDER BY v.station, v.attribute.id");
+        query.setParameter("river", river);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        if (!riversideClause.isEmpty())
+            query.setParameter("attr_id", riverside.getId());
+        return query.list();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/Tkh.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,242 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table tkh
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+@Entity
+@Table(name = "tkh")
+public class Tkh implements Serializable {
+
+    /**
+     * Possible values of the groupname column
+     *
+     */
+    public enum Group {
+        NONE(""), CALCULATION("berechnung"), MEASUREMENT("messung");
+
+        private final String dbvalue;
+
+        Group(final String dbvalue) {
+            this.dbvalue = dbvalue;
+        }
+
+        /**
+         * Value of the group's groupname column
+         */
+        public String getDbValue() {
+            return this.dbvalue;
+        }
+
+        /**
+         * Group for a groupname column value
+         */
+        public static Group forDbValue(final String dbvalue) {
+            for (final Group g : Group.values()) {
+                if (g.getDbValue().equals(dbvalue))
+                    return g;
+            }
+            return Group.NONE;
+        }
+    }
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 5891445651697221261L;
+
+    private Integer id;
+
+    private River river;
+
+    private String filename;
+
+    private transient Group group;
+
+    private String kmrange_info;
+
+    private String notes;
+
+    private Date day;
+
+    private String sounding_info;
+
+    private String evaluation_by;
+
+    private List<TkhColumn> columns;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public Tkh() {
+    }
+
+
+    public Tkh(final River river, final String filename, final String kmrange_info, final String notes, final Date day, final String sounding_info,
+            final String evaluation_by, final Group group) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.day = day;
+        this.setSounding_info(sounding_info);
+        this.setEvaluation_by(evaluation_by);
+        this.setGroup(group);
+        this.columns = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_TKH_ID_SEQ", sequenceName = "TKH_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_TKH_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "groupname")
+    public String getGroupname() {
+        return this.group.getDbValue();
+    }
+
+    public void setGroupname(final String groupname) {
+        this.group = Group.forDbValue(groupname);
+    }
+
+    @Transient
+    public Group getGroup() {
+        return this.group;
+    }
+
+    public void setGroup(final Group group) {
+        this.group = group;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @Column(name = "day")
+    public Date getDay() {
+        return this.day;
+    }
+
+    public void setDay(final Date day) {
+        this.day = day;
+    }
+
+    @Column(name = "sounding_info")
+    public String getSounding_info() {
+        return this.sounding_info;
+    }
+
+    public void setSounding_info(final String sounding_info) {
+        this.sounding_info = sounding_info;
+    }
+
+    @Column(name = "evaluation_by")
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "tkh_id")
+    public List<TkhColumn> getColumns() {
+        return this.columns;
+    }
+
+    public void setColumns(final List<TkhColumn> values) {
+        this.columns = values;
+    }
+
+    public void addColumn(final TkhColumn value) {
+        this.columns.add(value);
+    }
+
+    /**
+     * Selects a tkh series by id from the database
+     */
+    public static Tkh getTkhById(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM Tkh WHERE id=:id");
+        query.setParameter("id", id);
+        final List<Tkh> rows = query.list();
+        return ((rows != null) && !rows.isEmpty()) ? rows.get(0) : null;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/TkhColumn.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,121 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table tkh_column
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "tkh_column")
+public class TkhColumn implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -6567598780584866314L;
+
+    private Integer id;
+
+    private Tkh parent;
+
+    private String  name;
+
+    private List<TkhValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public TkhColumn() {
+    }
+
+    public TkhColumn(final Tkh parent, final String name) {
+        this.parent = parent;
+        this.name = name;
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_TKH_COLUMN_ID_SEQ", sequenceName = "TKH_COLUMN_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_TKH_COLUMN_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "tkh_id")
+    public Tkh getTkh() {
+        return this.parent;
+    }
+
+    public void setTkh(final Tkh tkh) {
+        this.parent = tkh;
+    }
+
+    @Column(name = "name")
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "tkh_column_id")
+    public List<TkhValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<TkhValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final TkhValue value) {
+        this.values.add(value);
+    }
+
+    /**
+     * Selects a tkh series column by id from the database
+     */
+    public static TkhColumn getTkhColumnById(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM TkhColumn WHERE id=:id");
+        query.setParameter("id", id);
+        final List<TkhColumn> rows = query.list();
+        return ((rows != null) && !rows.isEmpty()) ? rows.get(0) : null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/sinfo/TkhValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,154 @@
+/* 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.model.sinfo;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table tkh_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "tkh_values")
+public class TkhValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 4514054828340199384L;
+
+    private Integer id;
+
+    private TkhColumn tkhColumn;
+
+    private Double station;
+
+    /**
+     * TKH in m
+     */
+    private Double tkheight;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public TkhValue() {
+    }
+
+    public TkhValue(final TkhColumn tkhColumn, final Double station, final Double tkheight) {
+        this.tkhColumn = tkhColumn;
+        this.station = station;
+        this.tkheight = tkheight;
+    }
+
+    /**
+     * Constructor with primitive parameter types
+     */
+    public TkhValue(final TkhColumn tkhColumn, final double km, final double tkheight) {
+        this(tkhColumn, Double.valueOf(km), Double.valueOf(tkheight));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_TKH_VALUE_ID_SEQ", sequenceName = "TKH_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_TKH_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "tkh_column_id")
+    public TkhColumn getTkhColumn() {
+        return this.tkhColumn;
+    }
+
+    public void setTkhColumn(final TkhColumn tkh) {
+        this.tkhColumn = tkh;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @Column(name = "tkheight")
+    public Double getTkheight() {
+        return this.tkheight;
+    }
+
+    public void setTkheight(final Double tkheight) {
+        this.tkheight = tkheight;
+    }
+
+    @Transient
+    public double getTkhCm() {
+        if (getTkheight() != null)
+            return getTkheight().doubleValue() * 100;
+        else
+            return Double.NaN;
+    }
+
+    @Transient
+    public double getTkhUpCm(final boolean bedMoving) {
+        if (bedMoving)
+            return getTkhCm() / 2;
+        else
+            return getTkhCm();
+    }
+
+    @Transient
+    public double getTkhDownCm(final boolean bedMoving) {
+        if (bedMoving)
+            return -getTkhCm() / 2;
+        else
+            return 0.0;
+    }
+
+    /**
+     * Selects the tkh values of a tkh series column in a km range from the database
+     */
+    public static List<TkhValue> getTkhValues(final TkhColumn parent, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM TkhValue WHERE (tkhColumn=:parent)"
+                + " AND (station >= :kmLo - 0.0001) AND (station <= :kmHi + 0.0001)");
+        query.setParameter("parent", parent);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+        return query.list();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/uinfo/Salix.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,148 @@
+/* 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.model.uinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.model.River;
+
+/**
+ * Hibernate binding for the DB table salix
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+@Entity
+@Table(name = "salix")
+public class Salix implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -2765661962829259970L;
+
+    private Integer id;
+
+    private River river;
+
+    private String filename;
+
+    private String kmrange_info;
+
+    private String notes;
+
+    private String evaluation_by;
+
+    private List<SalixValue> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public Salix() {
+    }
+
+
+    public Salix(final River river, final String filename, final String kmrange_info, final String notes, final String evaluation_by) {
+        this.river = river;
+        this.filename = filename;
+        this.kmrange_info = kmrange_info;
+        this.notes = notes;
+        this.evaluation_by = evaluation_by;
+        this.values = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_SALIX_ID_SEQ", sequenceName = "SALIX_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_SALIX_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "kmrange_info")
+    public String getKmrange_info() {
+        return this.kmrange_info;
+    }
+
+    public void setKmrange_info(final String kmrange_info) {
+        this.kmrange_info = kmrange_info;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @Column(name = "evaluation_by")
+    public String getEvaluation_by() {
+        return this.evaluation_by;
+    }
+
+    public void setEvaluation_by(final String evaluation_by) {
+        this.evaluation_by = evaluation_by;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "salix_id")
+    public List<SalixValue> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<SalixValue> values) {
+        this.values = values;
+    }
+
+    public void addValue(final SalixValue value) {
+        this.values.add(value);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/uinfo/SalixRank.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,99 @@
+/* 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.model.uinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+@Entity
+@Table(name = "salix_rank")
+public class SalixRank implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 7459539781698086683L;
+
+    private Integer id;
+
+    private String  name;
+
+    private Double min_value;
+
+    private Double max_value;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public SalixRank() {
+    }
+
+    public SalixRank(final String name) {
+        this.name = name;
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @Column(name = "name")
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Column(name = "min_value")
+    public Double getMin_value() {
+        return this.min_value;
+    }
+
+    public void setMin_value(final Double min_value) {
+        this.min_value = min_value;
+    }
+
+    @Column(name = "max_value")
+    public Double getMax_value() {
+        return this.max_value;
+    }
+
+    public void setMax_value(final Double max_value) {
+        this.max_value = max_value;
+    }
+
+    /**
+     * Queries all salix ranks from the database, orders by id
+     */
+    public static List<SalixRank> getTypes() {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM SalixRank ORDER BY id");
+        return new ArrayList<>(query.list());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/uinfo/SalixValue.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,121 @@
+/* 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.model.uinfo;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+
+/**
+ * Hibernate binding for the DB table salix_values
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "salix_values")
+public class SalixValue implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = 7775536956084391338L;
+
+    private Integer id;
+
+    private Salix salix;
+
+    private Double station;
+
+    private Double factor;
+
+    private Double mnw_mw_diff;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public SalixValue() {
+    }
+
+    public SalixValue(final Salix salix, final Double station, final Double factor, final Double mnw_mw_diff) {
+        this.salix = salix;
+        this.station = station;
+        this.factor = factor;
+        this.mnw_mw_diff = mnw_mw_diff;
+    }
+
+    /**
+     * Constructor with primitive parameter types
+     */
+    public SalixValue(final Salix salix, final double km, final SalixRank salixType, final double factor, final double mnw_mw_diff) {
+        this(salix, Double.valueOf(km), Double.valueOf(factor), Double.valueOf(mnw_mw_diff));
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_SALIX_VALUE_ID_SEQ", sequenceName = "SALIX_VALUES_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_SALIX_VALUE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "salix_id")
+    public Salix getSalix() {
+        return this.salix;
+    }
+
+    public void setSalix(final Salix salix) {
+        this.salix = salix;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return this.station;
+    }
+
+    public void setStation(final Double station) {
+        this.station = station;
+    }
+
+    @Column(name = "factor")
+    public Double getFactor() {
+        return this.factor;
+    }
+
+    public void setFactor(final Double factor) {
+        this.factor = factor;
+    }
+
+    @Column(name = "mnw_mw_diff")
+    public Double getMnwMwDiff() {
+        return this.mnw_mw_diff;
+    }
+
+    public void setMnwMwDiff(final Double mnw_mw_diff) {
+        this.mnw_mw_diff = mnw_mw_diff;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/uinfo/Vegetation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,136 @@
+/* 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.model.uinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.dive4elements.river.model.River;
+
+/**
+ * Hibernate binding for the DB table vegetation
+ *
+ * @author Matthias Schäfer
+ *
+ */
+
+@Entity
+@Table(name = "vegetation")
+public class Vegetation implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -2264657956270172835L;
+
+    private Integer id;
+
+    private River river;
+
+    private String filename;
+
+    private String name;
+
+    private String notes;
+
+    private List<VegetationZone> values;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public Vegetation() {
+    }
+
+
+    public Vegetation(final River river, final String filename, final String name, final String notes) {
+        this.river = river;
+        this.filename = filename;
+        this.name = name;
+        this.notes = notes;
+        this.values = new ArrayList<>();
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_VEGETATION_ID_SEQ", sequenceName = "VEGETATION_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_VEGETATION_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id")
+    public River getRiver() {
+        return this.river;
+    }
+
+    public void setRiver(final River river) {
+        this.river = river;
+    }
+
+    @Column(name = "filename")
+    public String getFilename() {
+        return this.filename;
+    }
+
+    public void setFilename(final String filename) {
+        this.filename = filename;
+    }
+
+    @Column(name = "name")
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Column(name = "notes")
+    public String getNotes() {
+        return this.notes;
+    }
+
+    public void setNotes(final String notes) {
+        this.notes = notes;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "vegetation_id")
+    public List<VegetationZone> getValues() {
+        return this.values;
+    }
+
+    public void setValues(final List<VegetationZone> values) {
+        this.values = values;
+    }
+
+    public void addValue(final VegetationZone value) {
+        this.values.add(value);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/uinfo/VegetationType.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,82 @@
+/* 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.model.uinfo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Hibernate binding for the DB table vegetation_type
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "vegetation_type")
+public class VegetationType implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -845317173014273709L;
+
+    private Integer id;
+
+    private String  name;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public VegetationType() {
+    }
+
+    public VegetationType(final String name) {
+        this.name = name;
+    }
+
+    /***** METHODS *****/
+
+    @Id
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @Column(name = "name")
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+    /**
+     * Queries all salix ranks from the database, orders by id
+     */
+    public static List<VegetationType> getTypes() {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM VegetationType ORDER BY id");
+        return new ArrayList<>(query.list());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend/src/main/java/org/dive4elements/river/model/uinfo/VegetationZone.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,115 @@
+/* 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.model.uinfo;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+
+/**
+ * Hibernate binding for the DB table vegetation_zone
+ *
+ * @author Matthias Schäfer
+ *
+ */
+@Entity
+@Table(name = "vegetation_zone")
+public class VegetationZone implements Serializable {
+
+    /***** FIELDS *****/
+
+    private static final long serialVersionUID = -6579828019873800147L;
+
+    private Integer id;
+
+    private Vegetation vegetation;
+
+    private VegetationType vegetationType;
+
+    private Integer min_overflow_days;
+
+    private Integer max_overflow_days;
+
+
+    /***** CONSTRUCTORS *****/
+
+    public VegetationZone() {
+    }
+
+    public VegetationZone(final Vegetation vegetation, final VegetationType vegetationType, final Integer min_overflow_days, final Integer max_overflow_days) {
+        this.vegetation = vegetation;
+        this.vegetationType = vegetationType;
+        this.min_overflow_days = min_overflow_days;
+        this.max_overflow_days = max_overflow_days;
+    }
+
+
+    /***** METHODS *****/
+
+    @Id
+    @SequenceGenerator(name = "SEQUENCE_VEGETATION_ZONE_ID_SEQ", sequenceName = "VEGETATION_ZONE_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_VEGETATION_ZONE_ID_SEQ")
+    @Column(name = "id")
+    public Integer getId() {
+        return this.id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "vegetation_id")
+    public Vegetation getVegetation() {
+        return this.vegetation;
+    }
+
+    public void setVegetation(final Vegetation vegetation) {
+        this.vegetation = vegetation;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "vegetation_type_id")
+    public VegetationType getVegetationType() {
+        return this.vegetationType;
+    }
+
+    public void setVegetationType(final VegetationType vegetationType) {
+        this.vegetationType = vegetationType;
+    }
+
+    @Column(name = "min_overflow_days")
+    public Integer getMin_overflow_days() {
+        return this.min_overflow_days;
+    }
+
+    public void setMin_overflow_days(final Integer min_overflow_days) {
+        this.min_overflow_days = min_overflow_days;
+    }
+
+    @Column(name = "max_overflow_days")
+    public Integer getMax_overflow_days() {
+        return this.max_overflow_days;
+    }
+
+    public void setMax_overflow_days(final Integer max_overflow_days) {
+        this.max_overflow_days = max_overflow_days;
+    }
+}
--- a/gwt-client/pom.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/pom.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -224,7 +224,7 @@
           </filesets>
         </configuration>
       </plugin>
-
+<!-- 
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
@@ -247,6 +247,7 @@
           </execution>
         </executions>
       </plugin>
+ -->
 
     </plugins>
     </build>
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,7 +10,6 @@
 
 import com.google.gwt.i18n.client.ConstantsWithLookup;
 
-
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
@@ -40,7 +39,7 @@
 
     String clone_project();
 
-    String copy_of ();
+    String copy_of();
 
     String manage_projects();
 
@@ -144,6 +143,8 @@
 
     String databasket_loading();
 
+    String databasket_empty();
+
     String theme_top();
 
     String theme_up();
@@ -176,12 +177,6 @@
 
     String uesk_profile_distance();
 
-    String location_distance_state();
-
-    String distance_state();
-
-    String waterlevel_ground_state();
-
     String location();
 
     String locations();
@@ -236,7 +231,7 @@
 
     String missingInput();
 
-    String too_many_values ();
+    String too_many_values();
 
     String from();
 
@@ -1178,6 +1173,8 @@
 
     String areabgcolor();
 
+    String areabgpattern();
+
     String areashowborder();
 
     String areashowbg();
@@ -1418,8 +1415,163 @@
 
     String no_data_for_year();
 
+    String no_data_sediment_difference();
+
     String error_no_sedimentloadinfo_found();
 
     String error_no_sedimentloadinfo_data();
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+    String sinfo();
+
+    String sinfo_flowdepth_export();
+
+    String sinfo_flowdepth_report();
+
+    String sinfo_flow_depth();
+
+    String sinfo_flowdepth_twinpanel_no_pair_selected();
+
+    String sinfo_flow_depths();
+
+    String sinfo_flow_depths_minmax();
+
+    String sinfo_flow_depth_minmax();
+
+    String sinfo_flow_depth_developments();
+
+    String sinfo_flow_depth_development();
+
+    String sinfo_flow_depth_development_peryear();
+
+    String sinfo_waterlevel_differences();
+
+    String sinfo_waterlevel_difference();
+
+    String sinfo_bedheight_differences();
+
+    String sinfo_bedheight_difference();
+
+    String sinfo_tkh_export();
+
+    String sinfo_tkh_report();
+
+    String sinfo_tkhs();
+
+    String sinfo_tkk();
+
+    String sinfo_velocities();
+
+    String sinfo_taus();
+
+    String sinfo_bedqualities();
+
+    String sinfo_d50s();
+
+    String sinfo_flowdepthminmax_export();
+
+    String sinfo_flowdepthdevelopment_export();
+
+    String sinfo_additional_ls();
+
+    String sinfo_additional_ls_withQ();
+
+    String sinfo_additional_ls_withoutQ();
+
+    String sinfo_predefined_channel();
+
+    String sinfo_predefined_tkh();
+
+    String predefined_tkh_berechnung();
+
+    String predefined_tkh_messung();
+
+    String sinfo_predefined_depthevol();
+
+    String predefined_depthevol_aktuell();
+
+    String predefined_depthevol_etappe();
+
+    String sinfo_predefined_flowdepths();
+
+    String sinfo_predefined_flowdepth();
+
+    String sinfo_infrastructure();
+
+    String sinfo_collisions();
+
+    String sinfo_collision();
+
+    String uinfo();
+
+    String uinfo_salix_line_export();
+
+    String uinfo_vegetation_zones_export();
+
+    String uinfo_inundation_duration_export();
+
+    String uinfo_vegetation_zone_label();
+
+    String uinfo_vegetation_zones_label();
+
+    String uinfo_vegetation_zones_from();
+
+    String uinfo_vegetation_zones_to();
+
+    String bundu();
+
+    String uinfo_vegetation_zones_validation_empty();
+
+    String uinfo_vegetation_zones_validation_range();
+
+    String uinfo_vegetation_zones_validation_from_greater_to();
+
+    String uinfo_vegetation_zones_invalid_integer();
+
+    String chart_settings_export_metadata();
+
+    String sinfo_flow_depth_development_twin_panel_max_count_msg();
+
+    String sinfo_floodduration_export();
+
+    String sinfo_floodduration_report();
+
+    String export_csv_title();
+
+    String waterlevel_ground_state();
+
+    String error_no_data_for_river();
+
+    String sinfo_flood_duration();
+
+    String sinfo_collision_export();
+
+    String sinfo_flood_height();
+
+    String sinfo_columnlabel_soundings();
+
+    String sinfo_columnlabel_waterlevels();
+
+    String error_limit_exceeded_salix();
+
+    String sinfo_sounding_waterlevel_select_waterlevel();
+
+    String sinfo_deactivate_intelligent_datacord();
+
+    String sinfo_floodduration_curve();
+
+    String uinfo_salix_dmwspl_short();
+
+    String uinfo_salix_invalid_double();
+
+    String uinfo_salix_km_limit_exceed();
+
+    String uinfo_salix_km_overlap();
+
+    String uinfo_salix_km_has_gaps();
+
+    String uinfo_salix_km_anschluss();
+
+    String uinfo_salix_input_complete();
+
+    String common_input_hint_year();
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -57,12 +57,10 @@
 scale = Scale
 databasket = Databasket
 databasket_loading = Loading Databasket content
+databasket_empty = Databasket is empty
 fix = Fixing
 fixanalysis = Fixing Analysis
-next = Next
-location_distance_state = Choose calculation location(s) / range [km]
-distance_state = Choose calculation range [km]
-waterlevel_ground_state = Choose differences betweeen waterlevel and ground [m]
+next = Next  
 location = Location(s)
 locations = Locations
 single_location = Location
@@ -91,6 +89,8 @@
 sedimentload_ls = Sediment Load
 welcome = Welcome to Flusshydrologische Software
 welcome_open_or_create = Please open a project from the project list or create a
+common_input_hint_year = YYYY
+
 # Header images
 flysLogo = images/flys_logo.gif
 bfgLogo = images/bfg_logo.gif
@@ -165,6 +165,7 @@
 wq_value_q = Q [m\u00b3/s]
 river_km = River-Km
 uesk_profile_distance = Distance [m]
+
 minfo_type = Type
 analyzed_range = Analyzed Range
 
@@ -258,7 +259,7 @@
 extreme_wq_curve = W/Q
 fix_wq_curve = W/Q-Diagram
 fix_deltawt_curve = \u0394 W/t
-fix_longitudinal_section_curve = Longitudinal Section
+fix_longitudinal_section_curve = \u0394W Longitudinal Section
 fix_derivate_curve = Derivate
 fix_vollmer_wq_curve = W/Q-Diagram
 datacage_add_pair = Add difference pair
@@ -295,6 +296,8 @@
 events = Events
 kmchart = W/Q-Preview
 fix_waterlevel_export = Fixing analysis export
+sinfo_floodduration_export = \u00dcberflutungsdauern Infrastrukturen BWaStr Export
+sinfo_floodduration_report = \u00dcberflutungsdauern Infrastrukturen BWaStr Report
 
 chart_themepanel_header_themes = Theme
 chart_themepanel_header_actions = Actions
@@ -323,6 +326,8 @@
 ele_window_save_error = Error while saving elevations.
 ele_window_geometry_error = The geometry is not supported:
 
+error_limit_exceeded_salix = Die Eingabe ist auf 5 Werte beschr\u00e4nkt.
+error_no_data_for_river = F\u00fcr das gew\u00e4hlte Gew\u00e4sser liegen keine Daten vor.
 unexpected_exception = There occured an unexpected exception
 error_years_wrong = The second year needs to be bigger than the first year.
 error_read_minmax_values = Error while reading min/max values for the location input.
@@ -355,8 +360,8 @@
 error_no_sedimentloadinfo_data = No Sedimentload data for the current parameters.
 
 error_feed_no_data = No input data found.
-error_feed_from_out_of_range = The lower value is bigger than the upper value.
-error_feed_to_out_of_range = The upper value is out or the valid range.
+error_feed_from_out_of_range = The start value is out of the valid range.
+error_feed_to_out_of_range = The end value is out of the valid range.
 error_feed_from_bigger_to = The lower value is bigger than the upper value.
 error_feed_invalid_wq_mode = Invalid WQ-Mode selected.
 error_feed_number_format_float = The inserted value is no floating point number.
@@ -398,6 +403,8 @@
 warning_cannot_parse_date = Invalid date!
 warning_select_two_values = Please select two values!
 
+waterlevel_ground_state = Choose differences betweeen waterlevel and ground [m]
+
 ## map related strings
 digitize = images/digitize.png
 pipe1 = Pipe1
@@ -636,6 +643,7 @@
 showmiddleheight = Show middle depth
 fillcolor = Fill Color
 areabgcolor = Fill Color
+areabgpattern = Fill Pattern
 areashowborder = Show area border
 areashowbg = Show area background
 areabordercolor = Border color
@@ -746,13 +754,97 @@
 
 river=River
 
-bandwidthcolot = Band width color
-
 ld_locations=Station(s)
 
-potentiel = Potential
-
 lower_time = from
 upper_time = to
 
 no_data_for_year = No data available for: $1
+no_data_sediment_difference = Invalid value: $1
+
+sinfo = S-INFO
+sinfo_collision_export = Grundber\u00fchrungen Export
+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
+sinfo_flow_depths = Flie\u00dftiefen
+sinfo_flow_depths_minmax = Min./max. Flie\u00dftiefen
+sinfo_flow_depth_minmax = Min./max. Flie\u00dftiefen
+sinfo_flow_depth_developments = Flie\u00dftiefenentwicklung
+sinfo_flow_depth_development = Flie\u00dftiefenentwicklung
+sinfo_flow_depth_development_peryear = Flie\u00dftiefenentwicklung pro Jahr
+sinfo_flow_depth_development_twin_panel_max_count_msg = Es kann nur ein Differenzenpaar ausgew\u00e4hlt werden.
+sinfo_waterlevel_differences = Differenzen
+sinfo_waterlevel_difference = Differenzen
+sinfo_bedheight_differences = Sohlh\u00f6hendifferenzen
+sinfo_bedheight_difference = Sohlh\u00f6hendifferenzen
+sinfo_tkh_export = Transportk\u00f6rperh\u00f6hen Export
+sinfo_tkh_report = Transportk\u00f6rperh\u00f6hen Bericht
+sinfo_tkhs = Transportk\u00f6rperh\u00f6hen
+sinfo_tkk = Transportk\u00f6rperh\u00f6hen
+
+sinfo_velocities = Flie\u00dfgeschwindigkeiten
+sinfo_taus = Sohlschubspannung
+sinfo_bedqualities = Sohlbeschaffenheit  
+sinfo_d50s = Korndurchmesser
+
+sinfo_flowdepthminmax_export = min/max Flie\u00dftiefen Export
+sinfo_flowdepthdevelopment_export = Flie\u00dftiefenentwicklung Export
+
+sinfo_additional_ls = Selektierte zus. L\u00e4ngsschnitte
+sinfo_additional_ls_withQ = mit Abfluss
+sinfo_additional_ls_withoutQ = ohne Abfluss
+
+sinfo_predefined_channel = Zu gew\u00e4hrleistende Fahrrinnenverh\u00e4ltnisse
+
+sinfo_predefined_tkh = Transportk\u00f6rperh\u00f6hen
+predefined_tkh_berechnung = Berechnungsergebnisse
+predefined_tkh_messung = Naturmessungen
+
+sinfo_predefined_depthevol = Flie\u00dftiefenentwicklung
+predefined_depthevol_aktuell = Bezug aktueller GlW
+predefined_depthevol_etappe = GlW-Etappen
+
+sinfo_predefined_flowdepths = Modellierte Datens\u00e4tze
+sinfo_predefined_flowdepth = Flie\u00dftiefen
+
+sinfo_infrastructure = Infrastrukturen BWaStr
+
+sinfo_collisions = Grundber\u00fchrungen
+sinfo_collision = Grundber\u00fchrungen
+
+sinfo_flood_duration = \u00dcberflutungsdauer Infrastrukturen BWaStr
+sinfo_flood_height = H\u00f6he Infrastrukturen BWaStr
+sinfo_floodduration_curve = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie
+
+uinfo = U-INFO
+uinfo_salix_dmwspl_short = \u0394MW [cm]
+uinfo_inundation_duration_export = \u00dcberflutungsdauern Export
+uinfo_salix_line_export = Salix-Linie Export
+uinfo_vegetation_zones_export = Vegetationszonen Export
+
+uinfo_vegetation_zone_label = Vegetationszone
+uinfo_vegetation_zones_label = Vegetationszonen
+uinfo_vegetation_zones_from = \u00dcfd von [d/a]
+uinfo_vegetation_zones_to = \u00dcfd bis [d/a]
+uinfo_vegetation_zones_validation_empty = Eingabefeld leer.
+uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen.
+uinfo_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis".
+uinfo_vegetation_zones_invalid_integer = Nur Ganzzahlen erlaubt.
+uinfo_salix_invalid_double = Nur Zahlen erlaubt.
+uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs.
+uinfo_salix_km_overlap = Km-Bereiche \u00fcberlappen.
+uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt.
+uinfo_salix_km_anschluss = Der eingegebene Bereich schlie\u00dft nicht an den letzten Wert an.
+uinfo_salix_input_complete = Die gesamte Strecke ist bereits mit Werten belegt.
+
+bundu = Betrieb und Unterhaltung 
+
+chart_settings_export_metadata = Show Meta-Data
+export_csv_title = Title: 
+
+sinfo_columnlabel_soundings = Wahl der Peilung
+sinfo_columnlabel_waterlevels = Wahl des Wasserspiegels
+sinfo_sounding_waterlevel_select_waterlevel = W\u00e4hlen Sie zuerst eine Peilung
+sinfo_deactivate_intelligent_datacord = Intelligente Datenkorbfilterung ausschalten
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -14,7 +14,7 @@
 projectlist_creationTime = Anlegezeitpunkt
 projectlist_title = Titel
 projectlist_favorite = Dauerhaft
-projectlist_close = Schlie\u1E9Een
+projectlist_close = Schlie\u00dfen
 really_delete = Wollen Sie dieses Projekt wirklich l\u00f6schen?
 project_name_too_long = Der eingegebene Projektname ist zu lang. Die maximale L\u00e4nge betr\u00e4gt $LEN Zeichen.
 switch_language = Englisch
@@ -33,8 +33,8 @@
 river_selection = Gew\u00e4sser
 winfo = W-INFO
 minfo = M-INFO
+new_map = Neue Karte
 map = Karte
-new_map = Neue Karte
 new_chart = Neues Diagramm
 diagram = Diagramm
 axes = Achsen
@@ -57,12 +57,10 @@
 scale = Skalierung
 databasket = Datenkorb
 databasket_loading=Lade Datenkorb Inhalt
+databasket_empty = Datenkorb Inhalt ist leer
 fix = Fixierungsanalyse
 fixanalysis = Fixierungsanalyse
-next = Weiter
-location_distance_state = Berechnungsort(e) / strecke w\u00e4hlen [km]
-distance_state = Berechnungsstrecke w\u00e4hlen [km]
-waterlevel_ground_state = Differenzen zwischen Wasserspiegel und Gel\u00e4nde [m]
+next = Weiter 
 location = Ort(e)
 locations = Orte
 single_location = Ort
@@ -82,7 +80,6 @@
 cancelCalculationLabel = Aktuelle Berechnung abbrechen.
 calculationCanceled = Die Berechnung wurde abgebrochen.
 range = Bereich
-analyzed_range = ausgewertete Strecke
 resultCount = Treffer
 bfg_id = BfG-ID
 start_year = Start
@@ -92,6 +89,7 @@
 sedimentload_ls = Sediment Fracht
 welcome = Willkommen bei der Flusshydrologischen Software
 welcome_open_or_create = Bitte \u00f6ffnen Sie ein bestehendes Projekt aus der Projektliste oder erstellen Sie ein
+common_input_hint_year = JJJJ
 
 # Header images
 flysLogo = images/flys_logo.gif
@@ -136,25 +134,41 @@
 missingInput = Sie m\u00fcssen einen Wert eingeben.
 too_many_values = Nur ein Eingabewert erlaubt
 
+addPointsTooltip = Manuelle Punkte hinzuf\u00fcgen
+addWSPTooltip = Manuelle WSP hinzuf\u00fcgen
+downloadPNGTooltip = Diagramm als PNG herunterladen
+downloadPDFTooltip = Diagramm als PDF herunterladen
+downloadSVGTooltip = Diagramm als SVG herunterladen
+downloadCSVTooltip = Daten als CSV herunterladen
+zoomToMaxExtentTooltip = Auf maximale Ausdehnung zoomen
+zoomOutTooltip = Herauszoomen
+historyBackTooltip = Voriger Zoom
+panControlTooltip = Verschieben
+zoomboxTooltip = Ausschnitt vergr\u00f6\u00dfern
+chartPropertiesTooltip = Diagrammeigenschaften
+printTooltip = Drucken
+
 description = Beschreibung
 from = von
 to = bis
+riverside = Flussseite
 bottom_edge = Unterkante
 top_edge = Oberkante
-riverside = Flussseite
 name = Name
 type = Typ
-minfo_type = Aufnahmeart
 starttime = Reihe von
 stoptime = Reihe bis
+wq_table_w = Kennzeichnende Wasserst\u00e4nde
 wq_waterlevel_label = Kennzeichnender Wassterstand
-wq_table_w = Kennzeichnende Wasserst\u00e4nde
 wq_table_q = Kennzeichnende Abfl\u00fcsse / Dauerzahlen
 wq_value_w = W [cm am Pegel]
 wq_value_q = Q [m\u00b3/s]
 river_km = Fluss-Km
 uesk_profile_distance = Abstand [m]
 
+minfo_type = Aufnahmeart
+analyzed_range = ausgewertete Strecke
+
 wqTitle = Eingabe f\u00fcr W/Q Daten
 wqadaptedTitle = Eingabe f\u00fcr W/Q Daten
 noMainValueAtGauge = Ausgew\u00e4hlter Wert nicht f\u00fcr alle Pegel vorhanden
@@ -205,30 +219,15 @@
 askThemeRemove = Sind Sie sicher, dass sie die gew\u00e4hlten / das gew\u00e4lte Thema l\u00f6schen wollen?
 add = Hinzuf\u00fcgen
 
-addPointsTooltip = Manuelle Punkte hinzuf\u00fcgen
-addWSPTooltip = Manuelle WSP hinzuf\u00fcgen
-downloadPNGTooltip = Diagramm als PNG herunterladen
-downloadPDFTooltip = Diagramm als PDF herunterladen
-downloadSVGTooltip = Diagramm als SVG herunterladen
-downloadCSVTooltip = Daten als CSV herunterladen
-zoomToMaxExtentTooltip = Auf maximale Ausdehnung zoomen
-zoomOutTooltip = Herauszoomen
-historyBackTooltip = Voriger Zoom
-panControlTooltip = Verschieben
-zoomboxTooltip = Ausschnitt vergr\u00f6\u00dfern
-chartPropertiesTooltip = Diagrammeigenschaften
-printTooltip = Drucken
-
 static_sqrelation = Transport-Abfluss Beziehung
 discharge_curve = Abflusskurve am Pegel
 discharge_curve_gaugeless = Abflusskurve
 gauge_discharge_curve = Abflusstafel am Pegel
-current_gauge = Modell-Abflusskurve am Pegel
 computed_discharge_curve = Abflusskurve
 computed_discharge_curves = Abflusskurven
-historical_discharge_curves = Historische Abflusskurven
 longitudinal_section = L\u00e4ngsschnitt
 duration_curve = Dauerlinie
+historical_discharge_curves = Historische Abflusskurven
 discharge_longitudinal_section = W f\u00fcr benutzerdefinierten Abflussl\u00e4ngsschnitt
 floodmap = \u00dcberschwemmungsfl\u00e4che
 historical_discharge = Zeit-Diagramm
@@ -260,7 +259,7 @@
 extreme_wq_curve = W/Q
 fix_wq_curve = W/Q-Diagramm
 fix_deltawt_curve = \u0394 W/t
-fix_longitudinal_section_curve = L\u00e4ngsschnitt
+fix_longitudinal_section_curve = \u0394W-L\u00e4ngsschnitt
 fix_derivate_curve = Ableitungskurve
 fix_vollmer_wq_curve = W/Q-Diagramm
 datacage_add_pair = Differenzenpaar hinzuf\u00fcgen
@@ -274,6 +273,8 @@
 bed_difference_height_year = Sohlh\u00f6hendifferenz pro Jahr
 bedheight_difference_export = Sohlh\u00f6hendifferenz Export
 
+exportATTooltip = Export as AT file
+
 waterlevel_export = Wasserstand/Wasserspiegellagen Export
 waterlevel_report = Wasserstand/Wasserspiegellagen Bericht
 computed_dischargecurve_export = Abflusskurven Export
@@ -289,13 +290,14 @@
 pdf = PDF
 computed_dischargecurve_at_export = Abflusskurven Export
 gauge_discharge_curve_at_export = Abflusskurve am Pegel
+current_gauge = Modell-Abflusskurve am Pegel
 gauge_class = Abflussklasse
 eventselect = Ereignisauswahl
 events = Ereignisse
 kmchart = W/Q-Vorschau
 fix_waterlevel_export = Fixierungsanalysen Export
-
-exportATTooltip = Daten als AT Datei exportieren
+sinfo_floodduration_export = \u00dcberflutungsdauern Infrastrukturen BWaStr Export
+sinfo_floodduration_report = \u00dcberflutungsdauern Infrastrukturen BWaStr Bericht
 
 chart_themepanel_header_themes = Thema
 chart_themepanel_header_actions = Aktionen
@@ -324,6 +326,8 @@
 ele_window_save_error = Fehler beim Speichern der H\u00f6hen.
 ele_window_geometry_error = Die Geometrie wird nicht unterst\u00fctzt:
 
+error_limit_exceeded_salix = Die Eingabe ist auf 5 Werte beschr\u00e4nkt.
+error_no_data_for_river = F\u00fcr das gew\u00e4hlte Gew\u00e4sser liegen keine Daten vor.
 unexpected_exception = Ein unerwarteter Fehler ist aufgetreten
 error_years_wrong = Das zweite Jahr muss gr\u00f6\u00dfer als das erste sein.
 error_read_minmax_values = Fehler beim Lesen der min/max Werte. Es kann keine Validierung der eingegebenen Strecke durchgef\u00fchrt werden.
@@ -356,8 +360,8 @@
 error_no_sedimentloadinfo_data = F\u00fcr die gew\u00e4te Parametrisierung liegen keine Daten vor.
 
 error_feed_no_data = Keine Eingabedaten gefunden.
-error_feed_from_out_of_range = Der untere Wert liegt au\u00dferhalb des g\u00fcltigen Wertebereiches.
-error_feed_to_out_of_range = Der obere Wert liegt au\u00dferhalb des g\u00fcltigen Wertebereiches.
+error_feed_from_out_of_range = Der Start-Wert liegt au\u00dferhalb des g\u00fcltigen Wertebereiches.
+error_feed_to_out_of_range = Der End-Wert liegt au\u00dferhalb des g\u00fcltigen Wertebereiches.
 error_feed_from_bigger_to = Der untere Wert ist gr\u00f6\u00dfer als der obere Wert.
 error_feed_invalid_wq_mode = Ung\u00fcltiger Modus f\u00fcr die WQ-Eingabe gew\u00e4hlt.
 error_feed_number_format_float = Der eingegebene Wert ist keine Flie\u00dfkommazahl.
@@ -399,6 +403,8 @@
 warning_cannot_parse_date = Datum ist ung\u00fcltig!
 warning_select_two_values = Bitte zwei Werte w\u00e4hlen!
 
+waterlevel_ground_state = Differenzen zwischen Wasserspiegel und Gel\u00e4nde [m]
+
 ## map related strings
 digitize = images/digitize.png
 pipe1 = Rohr1
@@ -435,10 +441,6 @@
 requireDGM = Sie m\u00fcssen ein DGM ausw\u00e4hlen.
 upload_file = hochladen
 shape_file_upload = Shapedatei hochladen
-attribution = &copyIntevation GmbH 2013<br>Data &copy<a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>
-wmsURLMenuItem = WMS URL
-wmsURLBoxTitle = WMS URL der Kartenebene
-requireTheme = Sie m\u00fcssen ein Thema ausw\u00e4hlen.
 
 # data cage
 historical_discharges = Historische Abflusskurven
@@ -545,6 +547,7 @@
 bed_load = Geschiebefracht
 suspended_load = Suspensionsfracht
 
+# No translation for the pegelonline wms service layer names.
 gauge_points = Pegelmessstelle (WMS)
 gauge_level = Wasserstand (WMS)
 gauge_names = Pegelname (WMS)
@@ -571,7 +574,7 @@
 capabilitiesEmail = Email
 capabilitiesPhone = Telefon
 
-#Property dialog
+#Properties dialog
 chart = Diagramm
 export = Export
 width = Breite
@@ -635,11 +638,12 @@
 showborder = Linie anzeigen
 transparent = Transparent
 transparency = Transparenz
-showarea = Show area
+showarea = Fl\u00e4che anzeigen
 showarealabel = Fl\u00e4che beschriften
 showmiddleheight = Mittlere Tiefe anzeigen
 fillcolor = F\u00fcllfarbe
 areabgcolor = F\u00fcllfarbe
+areabgpattern = Fl\u00e4chentyp
 areashowborder = Fl\u00e4chenumrandung
 areashowbg = Fl\u00e4chenhintergrund
 areabordercolor = Umrandungsfarbe
@@ -649,6 +653,10 @@
 wsplgen_cat3 = F\u00fcllfarbe 2.0 <= DIFF < 3
 wsplgen_cat4 = F\u00fcllfarbe 3.0 <= DIFF < 4
 wsplgen_cat5 = F\u00fcllfarbe 4.0 <= DIFF
+attribution = &copyIntevation GmbH 2013<br>Data &copy<a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>
+wmsURLMenuItem = WMS URL
+wmsURLBoxTitle = WMS URL der Kartenebene
+requireTheme = Sie m\u00fcssen ein Thema ausw\u00e4hlen.
 
 # Manual Points Editor
 addpoints = Punkte hinzuf\u00fcgen
@@ -658,8 +666,8 @@
 standby = Erstelle Parameterisierung ... bitte warten.
 points = Punktthema
 editpoints = Eintr\u00e4ge editieren
+addWSPButton = WSP Thema
 addWSP = Neues WSP Thema anlegen
-addWSPButton = WSP Thema
 selection = Auswahl
 manual_date_points_y = Y ([m\u00b3/s]/[cm])
 
@@ -675,6 +683,7 @@
 
 fix_parameters_export = Angepasste Koeffizienten
 fix_parameters = CSV
+
 sq_overview=\u00dcbersicht
 sq_relations=Feststofftransport-Abfluss-Beziehung
 
@@ -732,19 +741,110 @@
 SOURCE = Quelle
 WATERBODY = Gew\u00e4sser
 FEDSTATE_KM = Landes-Stationierung
+
 official_regulation = amtl. Festlegung
 negative_values_not_allowed_for_to=Keine negativen Werte bei 'bis' erlaubt.
-river=Fluss
-ld_locations=Ort
+
+reference_gauge=Pegelnummer
 gauge_name=Pegel
-reference_gauge=Pegelnummer
+
 station=Messstellennummer
+
 station_name=Messstelle
 
-potentiel = Potentiell
-bandwidthcolot = Bandbreitenfarbe
+river=Fluss
+
+ld_locations=Ort
 
 lower_time = von
 upper_time = bis
 
 no_data_for_year = F\u00fcr das Jahr $1 liegen keine Daten vor.
+no_data_sediment_difference = Der Wert $1 ist ung\u00fcltig.
+
+sinfo = S-INFO
+sinfo_collision_export = Grundber\u00fchrungen Export
+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.
+sinfo_flow_depths = Flie\u00dftiefen
+sinfo_flow_depths_minmax = Min./max. Flie\u00dftiefen
+sinfo_flow_depth_minmax = Min./max. Flie\u00dftiefen
+sinfo_flow_depth_developments = Flie\u00dftiefenentwicklung
+sinfo_flow_depth_development = Flie\u00dftiefenentwicklung
+sinfo_flow_depth_development_peryear = Flie\u00dftiefenentwicklung pro Jahr
+sinfo_flow_depth_development_twin_panel_max_count_msg = Es kann nur ein Differenzenpaar ausgew\u00e4hlt werden.
+sinfo_waterlevel_differences = Differenzen
+sinfo_waterlevel_difference = Differenzen
+sinfo_bedheight_differences = Sohlh\u00f6hendifferenzen
+sinfo_bedheight_difference = Sohlh\u00f6hendifferenzen
+sinfo_tkh_export = Transportk\u00f6rperh\u00f6hen Export
+sinfo_tkh_report = Transportk\u00f6rperh\u00f6hen Bericht
+sinfo_tkhs = Transportk\u00f6rperh\u00f6hen
+sinfo_tkk = Transportk\u00f6rperh\u00f6hen
+
+sinfo_velocities = Flie\u00dfgeschwindigkeiten
+sinfo_taus = Sohlschubspannung
+sinfo_bedqualities = Sohlbeschaffenheit  
+sinfo_d50s = Korndurchmesser
+
+sinfo_flowdepthminmax_export = min/max Flie\u00dftiefen Export
+sinfo_flowdepthdevelopment_export = Flie\u00dftiefenentwicklung Export
+
+sinfo_additional_ls = Selektierte zus. L\u00e4ngsschnitte
+sinfo_additional_ls_withQ = mit Abfluss
+sinfo_additional_ls_withoutQ = ohne Abfluss
+
+sinfo_predefined_channel = Zu gew\u00e4hrleistende Fahrrinnenverh\u00e4ltnisse
+
+sinfo_predefined_tkh = Transportk\u00f6rperh\u00f6hen
+predefined_tkh_berechnung = Berechnungsergebnisse
+predefined_tkh_messung = Naturmessungen
+
+sinfo_predefined_depthevol = Flie\u00dftiefenentwicklung
+predefined_depthevol_aktuell = Bezug aktueller GlW
+predefined_depthevol_etappe = GlW-Etappen
+
+sinfo_predefined_flowdepths = Modellierte Datens\u00e4tze
+sinfo_predefined_flowdepth = Flie\u00dftiefen
+
+sinfo_infrastructure = Infrastrukturen BWaStr
+
+sinfo_collisions = Grundber\u00fchrungen
+sinfo_collision = Grundber\u00fchrungen
+
+sinfo_flood_duration = \u00dcberflutungsdauer Infrastrukturen BWaStr
+sinfo_flood_height = H\u00f6he Infrastrukturen BWaStr
+sinfo_floodduration_curve = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie
+
+uinfo = U-INFO
+uinfo_salix_dmwspl_short = \u0394MW [cm]
+uinfo_inundation_duration_export = \u00dcberflutungsdauern Export
+uinfo_salix_line_export = Salix-Linie Export
+uinfo_vegetation_zones_export = Vegetationszonen Export
+
+uinfo_vegetation_zone_label = Vegetationszone
+uinfo_vegetation_zones_label = Vegetationszonen
+uinfo_vegetation_zones_from = \u00dcfd von [d/a]
+uinfo_vegetation_zones_to = \u00dcfd bis [d/a]
+uinfo_vegetation_zones_validation_empty = Eingabefeld leer.
+uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen.
+uinfo_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis".
+uinfo_vegetation_zones_invalid_integer = Nur Ganzzahlen erlaubt.
+uinfo_salix_invalid_double = Nur Zahlen erlaubt.
+uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs.
+uinfo_salix_km_overlap = Km-Bereiche \u00fcberlappen.
+uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt.
+uinfo_salix_km_anschluss = Der eingegebene Bereich schlie\u00dft nicht an den letzten Wert an.
+uinfo_salix_input_complete = Die gesamte Strecke ist bereits mit Werten belegt.
+
+bundu = Betrieb und Unterhaltung
+
+chart_settings_export_metadata = Metadaten anzeigen
+export_csv_title = Titel: 
+
+sinfo_columnlabel_soundings = Wahl der Peilung
+sinfo_columnlabel_waterlevels = Wahl des Wasserspiegels
+sinfo_sounding_waterlevel_select_waterlevel = W\u00e4hlen Sie zuerst eine Peilung
+sinfo_deactivate_intelligent_datacord = Intelligente Datenkorbfilterung ausschalten
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Fri Feb 09 15:39:49 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,787 +0,0 @@
-fullname = Flusshydrologische Software
-user = User:
-guest = guest
-logout = Logout
-projects = Projects
-open_project = Open Project
-delete_project = Delete Project
-rename_project = Rename Project
-clone_project = Clone Project
-copy_of = Copy
-manage_projects = Manage Projects
-favorite_tooltip = Permanently store?
-favorite_tooltip_meaning = Golden star: stored
-projectlist_creationTime = Creation time
-projectlist_title = Title
-projectlist_favorite = Permanent
-projectlist_close = Close
-really_delete = Do you really want to delete this project?
-project_name_too_long = The entered project name is too long. Max length is $LEN characters.
-switch_language = German
-info = Info
-warning = Attention
-warning_language = Choosing a new language starts a new session. All open windows will be closed.
-no_projects = No existing calculations found.
-load_projects = Load calculations...
-empty_table = Loading data...
-empty_filter = No data found.
-date_format = yyyy-MM-dd
-datetime_format = yyyy-MM-dd HH:mm
-new_project = New Project
-new_calculation = New Calculation
-module_selection = Module
-river_selection = Rivers
-winfo = WINFO
-minfo = MINFO
-map = Map
-new_map = New Map
-new_chart = New Chart
-diagram = Chart
-axes = Axes
-legend = Legend
-wms_legend= WMS Legend
-chart_title = Title
-chart_subtitle = Subtitle
-grid = Grid
-antialiasing = Antialiasing
-axis_name = Name
-chart_start = Start
-chart_end = End
-x_axis = X-Axis
-y1_axis = Y1-Axis
-y2_axis = Y2-Axis
-y3_axis = Y3-Axis
-legend_name = Name
-show_legend = Show
-aggregation_threshold = Threshold for aggregation of legend entries
-scale = Scale
-databasket = Databasket
-databasket_loading = Loading Databasket content
-fix = Fixing
-fixanalysis = Fixing Analysis
-next = Next
-location_distance_state = Choose calculation location(s) / range [km]
-distance_state = Choose calculation range [km]
-waterlevel_ground_state = Choose differences betweeen waterlevel and ground [m]
-location = Location(s)
-locations = Locations
-single_location = Location
-distance = Range
-unitFrom = km
-unitTo = km a
-unitWidth = m
-search = Search
-discharge = FIXME(Name)
-properties = Properties
-activateTheme = Activate
-deactivateTheme = Deactivate
-removeTheme = Remove
-manageThemes = Manage themes
-label_ok = Ok
-label_cancel = Cancel
-cancelCalculationLabel = Stop the current calculation.
-calculationCanceled = The calculation has been canceled.
-range = Range
-resultCount = Hits
-bfg_id = BfG-ID
-start_year = Start
-end_year = end
-period = Period
-year = Year
-sedimentload_ls = Sediment Load
-welcome = Welcome to Flusshydrologische Software
-welcome_open_or_create = Please open a project from the project list or create a
-
-# Header images
-flysLogo = images/flys_logo.gif
-bfgLogo = images/bfg_logo.gif
-bfgLogoSmall = images/bfg_logo_small.png
-
-# Images
-downloadPNG = images/png_export.png
-downloadPDF = images/pdf_export.png
-downloadSVG = images/svg_export.png
-downloadCSV = images/save.png
-downloadAT = images/save_at.png
-downloadWST = images/save_wst.png
-loadingImg = images/loading.gif
-cancelCalculation = images/cancelCalculation.png
-markerRed = images/marker_red.png
-markerGreen = images/marker_green.png
-riverMap = images/FLYS_Karte.png
-properties_ico = images/properties.png
-
-dpLabelFrom = from
-dpUnitFrom = km
-dpLabelTo = to
-dpUnitTo = km
-dpLabelStep = a
-dpUnitStep = m
-
-wgLabelFrom = From
-wgUnitFrom = m
-wgLabelTo = To
-wgUnitTo = m
-wgLabelStep = a
-wgUnitStep = m
-
-unitFromInM = From [m]:
-unitToInM = To [m]:
-unitDiffInM = Diff [m]:
-unitLocation = km
-wrongFormat = Wrong format
-toShouldNotBeNegative = Field 'to' has to contain a positive value.
-atLeastOneValue = You need to insert at least one value.
-missingInput = You need to enter a value.
-too_many_values = Only one value allowed
-
-addPointsTooltip = Add manual points
-addWSPTooltip = Add manual LS
-downloadPNGTooltip = Download chart as PNG
-downloadPDFTooltip = Download chart as PDF
-downloadSVGTooltip = Download chart as SVG
-downloadCSVTooltip = Download data as CSV
-zoomToMaxExtentTooltip = Zoom to max extent
-zoomOutTooltip = Zoom out
-historyBackTooltip = Previous zoom
-panControlTooltip = Pan
-zoomboxTooltip = Zoombox
-chartPropertiesTooltip = Chartproperties
-
-description = Description
-from = From
-to = To
-riverside = Riverside
-bottom_edge = Bottom edge
-top_edge = Top edge
-name = Name
-type = Type
-starttime = Start Time
-stoptime = Stop Time
-wq_waterlevel_label = Characteristic Waterlevel
-wq_table_w = Characteristic Waterlevels
-wq_table_q = Characteristic Discharges / Durations
-wq_value_w = W [cm at Gauge]
-wq_value_q = Q [m\u00b3/s]
-river_km = River-Km
-uesk_profile_distance = Distance [m]
-
-minfo_type = Type
-analyzed_range = Analyzed Range
-
-wqTitle = Input for W/Q Data
-wqadaptedTitle = Input for W/Q Data
-noMainValueAtGauge = Selected main value not present at all gauges
-wqHistorical = Selection of Analyse Type
-calcTableTitle = Values
-helperPanelTitle = Input Support
-gaugePanelTitle = Gauge Information
-measurementStationPanelTitle = Measurement Station Information
-wqW = W at Gauge [cm]
-wqQ = Q [m\u00b3/s]
-wqQatGauge = Q at Gauge [m\u00b3/s]
-wqWFree = W at free position [m+NHN]
-wqQGauge = Discharge at Gauge
-wqSingle = Single values
-wqRange = Range
-unitWNN = W [NN+m]
-unitWSingle = cm
-unitWFree = m+NHN
-unitWFrom = cm&nbsp;-
-unitWTo = cm&nbsp;a
-unitWStep = cm
-unitQSingle = m\u00b3/s
-unitQFrom = m\u00b3/s&nbsp;-
-unitQTo = m\u00b3/s&nbsp;a
-unitQStep = m\u00b3/s
-main_channel = Main Channel
-total_channel = Total Channel
-footerHome = Home
-footerContact = Contact
-footerImpressum = Legal info
-
-projectListMin = format-indent-less.png
-projectListAdd = list-add.png
-buttonNext = Next
-imageBack = images/back_en.png
-imageSave = images/save.png
-theme_top = images/go-first.png
-theme_up = images/go-up.png
-theme_down = images/go-down.png
-theme_bottom = images/go-bottom.png
-zoom_all = images/mag_100.png
-zoom_in = images/mag_zoom_box.png
-zoom_out = images/mag_zoom_minus.png
-zoom_back = images/mag_zoom_back.png
-pan = images/hand.png
-askThemeRemove = Are you sure that you want to remove the selected theme / themes?
-add = Add
-
-static_sqrelation = SQ relation
-discharge_curve = Discharge Curve at Gauge
-discharge_curve_gaugeless = Discharge Curve
-current_gauge = Current Gauge Discharge Curve
-gauge_discharge_curve = Discharge Table at Gauge
-computed_discharge_curve = Discharge Curve
-computed_discharge_curves = Discharge Curves
-longitudinal_section = Longitudinal Section Curve
-duration_curve = Duration Curve
-discharge_longitudinal_section = Discharge Longitudinal Section
-floodmap = Floodmap
-historical_discharge = Time Chart
-historical_discharge_curves = Historical Discharge Curve
-historical_discharge_wq = W/Q Chart
-flow_velocity = Flow Velocity
-flow_velocities = Flow Velocities
-flow_velocity_export = Flow Velocity Export
-bedheight_middle = Middle Bed Height
-bedheight_middle_export = Middle Bed Height Export
-bed_longitudinal_section = Bed Quality
-bed_longitudinal_section_export = Bed Quality Export
-
-sq_relation_a = A Fine material
-sq_relation_b = B Sand (suspended)
-sq_relation_c = C Sand (bed load)
-sq_relation_d = D Fine/middle
-sq_relation_e = E Coarse
-sq_relation_f = F Bed load total
-sq_relation_g = G Bed load total (bed height-relevant)
-sq_relation_export = SQ Export
-
-cross_section = Cross Section
-cross_sections = Cross Sections
-w_differences = Differences
-w_differences_export = Differences Export
-reference_curve_export = Reference Curve Export
-historical_discharge_export = Historical Discharge Curve Export
-showextramark = Show begin of extrapolation
-extreme_wq_curve = W/Q
-fix_wq_curve = W/Q-Diagram
-fix_deltawt_curve = \u0394 W/t
-fix_longitudinal_section_curve = Longitudinal Section
-fix_derivate_curve = Derivate
-fix_vollmer_wq_curve = W/Q-Diagram
-datacage_add_pair = Add difference pair
-load_diameter = Bedload Diameter
-bed_diameter = Bed Diameter
-soundings = Soundings
-soundings_width = Soundings Width
-porosities = Porosity
-bed_difference_year = Bedheight Differences
-bed_difference_epoch = Epoch Bedheight Differences
-bed_difference_height_year = Bedheight Difference per year
-bedheight_difference_export = Bedheight Differences Export
-
-exportATTooltip = Export as AT file
-
-waterlevel_export = Waterlevel Export
-waterlevel_report = Waterlevel Report
-computed_dischargecurve_export = Discharge Curve Export
-computed_dischargecurve_report = Discharge Curve Report
-discharge_longitudinal_section_export = Discharge Longitudinal Section Export
-discharge_longitudinal_section_report = Discharge Longitudinal Section Report
-durationcurve_export = Duration Curve Export
-durationcurve_report = Duration Curve Report
-dataexport = Data export
-csv = CSV
-wst = WST
-at = AT
-pdf = PDF
-computed_dischargecurve_at_export = Discharge Curve Export
-gauge_discharge_curve_at_export = Gauge Discharge Curve
-gauge_class = Gauge Class
-eventselect = Eventselection
-events = Events
-kmchart = W/Q-Preview
-fix_waterlevel_export = Fixing analysis export
-
-chart_themepanel_header_themes = Theme
-chart_themepanel_header_actions = Actions
-chart_themepanel_synchron = Navigate synchronously
-chart_themepanel_asynchron = Navigate independently
-chart_themepanel_set_master = Reference
-chart_themepanel_new_area = New Area...
-chart_themepanel_area_under = under ...
-chart_themepanel_area_over = over ...
-chart_themepanel_area_between = between ...
-against_x_axis = Over X-Axis
-
-gauge_mnq = around MNQ
-gauge_mq  = around MQ
-gauge_mhq = around MHQ
-gauge_hq5 = above HQ5
-
-ele_window_title = Elevation Node
-ele_window_label = Elevation settings in m \u00fc. NN.
-ele_window_x_col = X
-ele_window_y_col = Y
-ele_window_z_col = Z-Coordinate
-ele_window_ok_button = Set elevations
-ele_window_cancel_button = Cancel
-ele_window_format_error = The elevation you have entered is invalid:
-ele_window_save_error = Error while saving elevations.
-ele_window_geometry_error = The geometry is not supported:
-
-unexpected_exception = There occured an unexpected exception
-error_years_wrong = The second year needs to be bigger than the first year.
-error_read_minmax_values = Error while reading min/max values for the location input.
-error_validate_range = The value $1 needs to be between $2 and $3.
-error_validate_date_range = Start date needs to be before end date.
-error_validate_date_range_invalid = The specified timerange is invalid.
-error_validate_lower_range = The lower value $1 needs to be bigger than $2.
-error_validate_upper_range = The upper value $1 needs to be smaller than $2.
-error_validate_positive = The value $1 must be positive.
-error_empty_state = Required inputs are missing.
-error_invalid_double_value = Wrong format for a floating point number.
-error_create_artifact = Error while creating new project.
-error_describe_artifact = Error while loading the parameterization.
-error_feed_data = Error while inserting new data.
-error_advance_artifact = Error while changing the project's state.
-error_add_artifact = Error while inserting new data.
-error_remove_artifact = Error while removing data.
-error_create_collection = Error while creating a new collection.
-error_describe_collection = Error while fetching the projects state.
-error_no_rivers_found = Error while reading supported rivers.
-error_no_such_user = Error - no such user found.
-error_no_users = Error - no users found.
-error_no_waterlevel_pair_selected = Error - no waterlevel pair for building differences selected.
-error_same_waterlevels_in_pair = Error - minuend and subtrahend have to differ.
-error_not_logged_in = You need to log in before you are allowed to start your work.
-error_load_parameterization = Could not load the parameterization.
-error_wrong_date = Please enter valid dates.
-error_no_gaugeoverviewinfo_found = Error while fetching the river and gauge info
-error_no_sedimentloadinfo_found = Error while fetching sedimentload info.
-error_no_sedimentloadinfo_data = No Sedimentload data for the current parameters.
-
-error_feed_no_data = No input data found.
-error_feed_from_out_of_range = The lower value is bigger than the upper value.
-error_feed_to_out_of_range = The upper value is out or the valid range.
-error_feed_from_bigger_to = The lower value is bigger than the upper value.
-error_feed_invalid_wq_mode = Invalid WQ-Mode selected.
-error_feed_number_format_float = The inserted value is no floating point number.
-error_feed_invalid_calculation_mode = The chosen calculation method is invalid.
-error_feed_no_calculation_mode = No calculation method chosen.
-error_feed_no_such_river = The selected river is not provided.
-error_feed_no_river_selected = No river selected.
-error_feed_no_wq_mode_selected = No W/Q mode selected.
-error_feed_q_values_invalid = Selected Q values are outside the valid range.
-error_feed_w_values_invalid = Selected W values are outside the valid range.
-error_chart_info_service = Could not fetch meta information of the chart.
-error_no_meta_data_found = No meta data found.
-error_load_artifact = Error while adding data to the current project.
-error_no_calc_result=No calculation results found.
-error_no_theme_styles_found=No style for the selected theme found.
-error_no_feature_selected = No object selected.
-error_no_map_config = No Map configuration found.
-error_no_map_output_type = No Map output found.
-error_no_valid_gfi_url = No valid GetFeatureInfo response found.
-error_gfi_req_failed = GetFeatureInfo request failed.
-error_gfi_parsing_failed = Failed to read GetFeatureInfo response.
-error_gc_req_failed = Error while loading Capabilities document.
-error_gc_doc_not_valid = Capabilities document is not valid.
-error_malformed_url = The URL you have entered is not valid.
-error_no_dgm_selected = No DEM selected.
-error_invalid_dgm_selected = An error occured while selecting the DEM.
-error_bad_dgm_range = You have selected a DEM with an invalid range.
-error_bad_dgm_river = You have selected a DEM for a wrong river.
-error_dialog_not_valid = One or more values are not valid.
-error_invalid_date = The entered date is not valid.
-error_same_location = Reference location equals selected location.
-error_contains_same_location = Target locations contains reference location.
-error_update_collection_attribute = Error while updating the collection attribut
-error_values_needed = You must provide values.
-error_no_module_found = No modules found
-
-warning_use_first_feature = You have more that one object selected. The first one is used.
-warning_no_wsp_selected = No waterlevel selected!
-warning_cannot_parse_date = Date is invalid!
-warning_select_two_values = Please select two values!
-
-## map related strings
-digitize = images/digitize.png
-pipe1 = Pipe1
-pipe2 = Pipe12
-ditch = Ditch
-dam = Dam
-ring_dike = Ringdike
-selectFeature = images/selectFeature.png
-removeFeature = images/removeFeature.png
-getFeatureInfo = images/info.png
-getFeatureInfoTooltip = Information Tool
-getFeatureInfoWindowTitle = Information for Map Layer:
-addWMS = images/add_map.png
-printMapSettings = images/print_map_settings.png
-addWMSTooltip = Load layers from external WMS service.
-adjustElevation = images/adjustElevation.png
-measureLine = images/measure_line.png
-measurePolygon = images/measure_plane.png
-step = Step
-calculationStarted = Calculation started.
-zoomMaxExtent = Max extent
-zoomIn = Zoom in
-zoomOut = Zoom out
-zoomLayer = Zoom to layer
-moveMap = Move
-digitizeObjects = Creation of pipes, ditches, dams and ringdikes
-selectObject = Select tool
-removeObject = Remove selected object
-adjustElevationTooltip = Define elevations for barriers
-measureDistance = Measure line
-measureArea = Measure area
-map_themepanel_header_style = Style
-zoomToLayer = Layer-Zoom
-requireDGM = You need to choose a DEM.
-upload_file = upload
-shape_file_upload = Upload shapefile
-attribution = &copyIntevation GmbH 2013<br>Data &copy<a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>
-wmsURLMenuItem = WMS URL
-wmsURLBoxTitle = Layer WMS URL
-requireTheme = You need to choose a Layer.
-
-# data cage
-historical_discharges = Historical discharge curves
-reference_curves = Reference Curves
-waterlevels = Waterlevels
-waterlevels_ls = Longitudinal Section
-waterlevels_discharge = Discharge Longitudinal Section
-waterlevels_fix = Fixation analysis
-waterlevels_fix_vollmer = Fixation analysis (Vollmer)
-beddifferences = Bedheight Differences
-bedheight_differences = Bedheight Differences
-middle_bedheights = Middle Bedheights
-vollmer_waterlevels = Vollmer Waterlevels
-old_calculations = Former Calculations
-officiallines = Official lines
-datacageAdd = Add data
-heightmarks = Height Marks
-basedata = Base Data
-fixations = Fixations
-flood_protections = Flood Protections
-columns = Columns
-annotation = Annotations
-annotations = Annotations
-all_annotations = All annotations
-flowvelocitymeasurement = Flowvelocity measurements
-flowvelocitymodel = Flowvelocity model
-bed_quality = Bed Quality
-additionals = Additional Longitudinal Section Curves
-differences = Differences
-kilometrage = Kilometrage
-riveraxis = Riveraxis
-km = Km
-qps = Crosssection Tracks
-hws = Floodplain Protection Work
-catchments = Catchments
-catchment_wms = Catchment (WMS)
-floodplain = Floodplain
-lines = Lines
-buildings = Buildings
-fixpoints = Fixpoints
-uesk = Floodmaps
-calculations = Calculations
-current = Current
-potentiel = Potential
-bfg = BfG
-land = Land
-rastermap = Rastermap
-background = Background Layer (WMS)
-discharge_tables_chart = W/Q-Preview
-discharge_table_nn = Discharge Tables at Gauge
-discharge_table_gauge = Discharge Table at Gauge
-mainvalue = Mainvalue
-mainvalues = Mainvalues
-wmainvalue = Mainvalues (W)
-qmainvalue = Mainvalues (Q)
-show_mainvalues = Show Mainvalues
-dems = Digital Elevation Models
-hydrboundaries = Hydrological Boundaries
-gaugelocations = Location of Gauges (WMS)
-single = Year
-epoch = Epoch
-bedheights = Bedheights
-morph_width = morphologic Width
-datacage = Datacage
-delta_w = Waterleveldifferences
-delta_w_cm = cm
-delta_w_cma = cm/a
-wlevel = Waterlevels
-sedimentloads = Sedimentloads
-sources_sinks = sources_sinks
-years = years
-epochs = epochs
-off_epochs = official epochs
-densities = Sediment Densities
-
-sediment_load = Sediment Load
-sediment_load_ls = Longitudinal sections
-measurement_stations = Measurement stations
-coarse = Coarse
-fine_middle = Fine Middle
-sand = Sand
-susp_sand = Suspended Sand
-susp_sand_bed = Suspended Sand (bed)
-suspended_sediment = Suspended Sediment
-total = Total load
-bed_load = Bed load
-suspended_load = Suspended load
-
-startcolor = Colorrange start color
-endcolor = Colorrange end color
-numclasses = Number of classes
-
-# capabilities information panel
-addwmsInputTitle = Base URL of WMS service
-addwmsInfoTitle = Information about WMS service
-addwmsLayerTitle = Choose Layer
-addwmsBack = Back
-addwmsContinue = Continue
-addwmsCancel = Cancel
-addwmsInvalidURL = The URL is not valid.
-capabilitiesHint = Please notice the information of the WMS service.
-capabilitiesTitle = Title
-capabilitiesURL = URL
-capabilitiesAccessConstraints = Access Constraints
-capabilitiesFees = Fees
-capabilitiesContactInformation = Further Information
-capabilitiesEmail = Email
-capabilitiesPhone = Phone
-
-#Properties dialog
-chart = Chart
-export = Export
-width = Width
-height = Height
-visibility = Visibility
-upper = to
-lower = from
-fixation = Fix
-font_size = Fontsize
-label = Title
-title = Title
-subtitle = Subtitle
-display_grid = Display grid
-display_logo = Display logo
-logo_placeh = Horiz. Place for logo
-logo_placev = Vertic. Place for logo
-suggested_label = Suggested Label
-top = top
-bottom = bottom
-center = center
-left = left
-right = right
-none = none
-
-notselected = none
-
-linetype = Linetype
-textstyle = Textstyle
-linecolor = Linecolor
-showhorizontalline = Show horizonal line
-showverticalline = Show vertical line
-textcolor = Textcolor
-textsize = Textsize
-font = Font
-showpoints = Show points
-showbackground = Show background
-textshowbg = Show background
-backgroundcolor = Backgroundcolor
-bandwidthcolot = Bandwidthcolor
-textbgcolor = Backgroundcolor
-textorientation = Textorientation
-linesize = Linesize
-pointsize = Pointsize
-bandwidth = Bandwidth
-pointcolor = Pointcolor
-showlines = Show lines
-showlinelabel = Show label
-showpointlabel = Show point label
-labelfontface = Label: Font
-labelfontcolor = Label: Color
-labelfontsize = Label: Size
-labelfontstyle = Label: Style
-labelbgcolor = Label: Background Color
-labelshowbg = Label: Show Background
-horizontal = horizontal
-vertical = vertical
-showwidth = Show width
-showlevel = Show waterlevel
-showminimum = Show minimum
-showmaximum = Show maximum
-showborder = Show line
-transparent = Transparency
-transparency = Transparency
-showarea = Show area
-showarealabel = Show area label
-showmiddleheight = Show middle depth
-fillcolor = Fill Color
-areabgcolor = Fill Color
-areashowborder = Show area border
-areashowbg = Show area background
-areabordercolor = Border color
-areatransparency = Tranparency
-wsplgen_cat1 = Fill Color 0.0 <= DIFF < 1
-wsplgen_cat2 = Fill Color 1.0 <= DIFF < 2
-wsplgen_cat3 = Fill Color 2.0 <= DIFF < 3
-wsplgen_cat4 = Fill Color 3.0 <= DIFF < 4
-wsplgen_cat5 = Fill Color 4.0 <= DIFF
-
-# Manual Points Editor
-addpoints = Add points
-pointname = Name
-removepoint = Remove
-newpoint = New Point
-standby = Creating Artifact ... please wait.
-points = Points
-editpoints = Edit Points
-addWSP = Add Manual LS
-addWSPButton = Add Manual LS
-selection = Selection
-manual_date_points_y = Y ([m\u00b3/s]/[cm])
-
-# Reference Curves
-reference_curve = Reference Curve
-reference_curve_normalized = Reduced Reference Curve
-reference_startpoint = Point of reference
-reference_endpoint = Point(s) of projection
-
-fix_deltawt_export = \u0394 W/t
-select=Selected
-add_date=Add
-
-fix_parameters_export = Adjusted coefficient
-fix_parameters = CSV
-sq_overview=Overview
-sq_relations=SQ Relations
-
-gauge_zero = GZG
-gauge_q_unit = m\u00b3/s
-gauge_river_info_link = Riverinfo
-gauge_info_link = Gaugeinfo
-gauge_url = /PegelInfo/
-gauge_river_url = /GewaesserInfo/
-gauge_curve_link = model dischargecurve/-table
-discharge_timeranges = DC-Timeranges
-discharge_chart = W/Q-Preview
-
-measurement_station_type = Type of Measurement Station
-measurement_station_operator = Operator
-measurement_station_start_time = Observation Start Time
-measurement_station_url = /MessstellenInfo/
-measurement_station_info_link = Measurement Station Info
-measurement_station_gauge_name = Reference Gauge
-measurement_station_comment = Comment
-
-# Get Feature Info Window
-PATH = Path
-official_regulation = Official Regulation
-negative_values_not_allowed_for_to=Negative are not allowed for 'to'.
-river=River
-ld_locations=Location
-gauge_name=Gauge
-reference_gauge=Gaugenumber
-station=Measurementstationnumber
-station_name=Measurementstation
-
-mapfish_data_range = mapfish_data_3Bereich
-mapfish_data_subtitle = mapfish_data_0Untertitel
-mapfish_data_strech = mapfish_data_2Strecke
-mapfish_data_institution = mapfish_data_5Institution
-mapfish_data_source = mapfish_data_6Datenquelle
-mapfish_data_creator = mapfish_data_4Bearbeiter
-mapfish_data_dateplace = mapfish_data_7Ort, Datum
-mapfish_data_river = mapfish_data_1Gew\u00e4sser
-
-custom_lines = Own red lining
-
-mapSource = Data source
-
-printWindowTitle = PDF print settings
-
-LOCATION = Location
-
-mapCreator = Issuer
-
-gauge_points = Gauge measurement station (WMS)
-
-axis = Axis
-
-hws_points = Point data
-
-gauge_level = Water levels (WMS)
-
-print = Print
-
-bandwidthcolor = Band width color
-
-pegel_had_measurement_points = HAD discharge stations (WMS)
-
-hws_lines = Line data
-
-printTooltip = Print
-
-mapTitle = Title
-
-potential = Potential
-
-Z = Height
-
-mapStretch = Map extent
-
-areas = Display type: Areas
-
-inofficial = Inofficial
-
-KM = Station
-
-DIFF = DIFF
-
-federal = Federal state
-
-gauge_tendency = Tendency of water level (WMS)
-
-jetties = Jetties
-
-gauge_names = Names of gauges (WMS)
-
-WATERBODY = Water body
-
-FEDSTATE_KM = Station of federal states
-
-SOURCE = Source
-
-sobek_flooded = SOBEK border-Grenzlinie with or without flow through
-
-route_data = Route data
-
-mapLogo = Logo
-
-bfg_model = BfG model
-
-measurements = Measurements
-
-floodmarks = Flood markings
-
-mapSubtitle = Subtitle
-
-mapDate = Place and time
-
-HPGP = HP/GP
-
-mapRange = Range
-
-official = official
-
-hws_fed_unknown = Unknown federal state
-
-mapInstitution = Institutions
-
-other = Other
-
-sobek_areas = SOBEK areas
-
-DESCRIPTION = Description
-
-lower_time = from
-upper_time = to
-
-no_data_for_year = No data available for: $1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/artifacthelper/ArtifactHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.artifacthelper;
+
+import org.dive4elements.river.client.shared.model.Artifact;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataList;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class ArtifactHelper {
+
+    private final Artifact artifact;
+
+    public ArtifactHelper(final Artifact artifact) {
+        this.artifact = artifact;
+    }
+
+    public Data getOldDataByKey(final String keyLabel) {
+        final DataList[] oldData = this.artifact.getArtifactDescription().getOldData();
+        for (final DataList dataList : oldData) {
+            for (final Data data : dataList.getAll()) {
+                if (data.getLabel().equals(keyLabel)) {
+                    return data;
+                }
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractEpochPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,241 @@
+/** 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.river.client.client.ui.FromToTableHelperPanel.IColumnClickHandler;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class AbstractEpochPanel extends AbstractUIProvider {
+
+    private static final long serialVersionUID = 1L;
+
+    protected enum Type {
+        single, multi
+        // Type single: nur eine Epoche kann gesetzt werden; minMax vorbelegt aus Datenquelle
+        // Type multi: mehrere epochs können eingegeben werden
+    }
+
+    private TextItem start;
+
+    private TextItem end;
+
+    private ListGrid elements;
+
+    private List<String> validInputs = new ArrayList<String>();
+
+    private final Type type;
+
+    public AbstractEpochPanel(final Type type) {
+        this.type = type;
+    }
+
+    protected abstract String getDatakey();
+
+    protected abstract Canvas createWidget(final DataList data);
+
+    protected final TextItem createStartInputItem(final String title) {
+        this.start = PanelHelper.createItem(title);
+        return this.start;
+    }
+
+    protected final TextItem createEndInputItem(final String title) {
+        this.end = PanelHelper.createItem(title);
+        return this.end;
+    }
+
+    protected final ListGrid createListGrid() {
+        this.elements = new ListGrid();
+        this.elements.setShowHeaderContextMenu(false);
+        this.elements.setCanReorderFields(false);
+        this.elements.setCanSort(false);
+        this.elements.setCanEdit(false);
+        return this.elements;
+    }
+
+    @Override
+    public final Canvas createOld(final DataList dataList) {
+        final HLayout layout = new HLayout();
+        layout.setWidth("400px");
+        final VLayout vLayout = new VLayout();
+        vLayout.setWidth(130);
+        final Label label = new Label(dataList.getLabel());
+        label.setWidth("200px");
+        label.setHeight(25);
+
+        final List<Data> items = dataList.getAll();
+        final Data str = getData(items, getDatakey());
+        final DataItem[] strItems = str.getItems();
+
+        final String[] pairs = strItems[0].getLabel().split(";");
+        for (final String pair : pairs) {
+            final Label dateLabel = new Label(pair.replace(",", " - "));
+            dateLabel.setHeight(20);
+            vLayout.addMember(dateLabel);
+        }
+        final Canvas back = getBackButton(dataList.getState());
+        layout.addMember(label);
+        layout.addMember(vLayout);
+        layout.addMember(back);
+
+        return layout;
+    }
+
+    @Override
+    public final Canvas create(final DataList data) {
+        final VLayout layout = new VLayout();
+        final Canvas submit = getNextButton();
+        final Canvas widget = createWidget(data);
+
+        layout.addMember(widget);
+        layout.addMember(submit);
+
+        final IColumnClickHandler fromHandler = createHandler(this.start);
+        final IColumnClickHandler toHandler = createHandler(this.end);
+
+        final FromToTableHelperPanel helper = new FromToTableHelperPanel(data, getDatakey(), this.MSG, fromHandler, toHandler);
+        this.validInputs = helper.getKeycolEntries();
+        final Canvas table = helper.getTable();
+
+        this.helperContainer.addMember(table);
+
+        return layout;
+    }
+
+    private final IColumnClickHandler createHandler(final TextItem field) {
+        final IColumnClickHandler handler = new IColumnClickHandler() {
+
+            @Override
+            public void columnClicked(final String value) {
+                field.setValue(value);
+            }
+        };
+        return handler;
+    }
+
+    /*
+     * Validate the epoch input. We do this here and not in an overridden
+     * validate method as we want to validate before an epoch is added
+     * to the list of epochs.
+     */
+    protected final boolean isValidEpoch(final String y1, final String y2) {
+        // First check that both are integer
+        // int iY1;
+        // int iY2;
+        final List<String> errors = new ArrayList<String>();
+        try {
+            // iY1 =
+            Integer.parseInt(y1);
+        }
+        catch (final NumberFormatException e) {
+            errors.add(this.MSG.wrongFormat() + ": " + y1);
+        }
+        try {
+            // iY2 =
+            Integer.parseInt(y2);
+        }
+        catch (final NumberFormatException e) {
+            errors.add(this.MSG.wrongFormat() + ": " + y2);
+        }
+        if (!errors.isEmpty()) {
+            showErrors(errors);
+            return false;
+        }
+        boolean startIsGood = false;
+        boolean endIsGood = false;
+        for (final String validYear : this.validInputs) {
+            if (startIsGood || y1.equals(validYear)) {
+                startIsGood = true;
+            }
+            if (endIsGood || y2.equals(validYear)) {
+                endIsGood = true;
+            }
+            if (startIsGood && endIsGood) {
+                break;
+            }
+            /*
+             * alternative check if data lies in between
+             * int aYear = Integer.parseInt(validYear);
+             * if (aYear >= iY1 && aYear <= iY2) {
+             * isGood = true;
+             * break;
+             * }
+             */
+        }
+        if (!startIsGood) {
+            String tmp = this.MSG.no_data_for_year();
+            tmp = tmp.replace("$1", y1);
+            errors.add(tmp);
+        }
+        if (!endIsGood) {
+            String tmp = this.MSG.no_data_for_year();
+            tmp = tmp.replace("$1", y2);
+            errors.add(tmp);
+        }
+        if (!errors.isEmpty()) {
+            showErrors(errors);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    protected final Data[] getData() {
+        final List<Data> data = new ArrayList<Data>();
+        switch (this.type) {
+
+        case single:
+            data.add(buildResult(this.start.getValueAsString(), this.end.getValueAsString()));
+
+            break;
+        case multi:
+            final ListGridRecord[] lgr = this.elements.getRecords();
+            if (lgr.length == 0) {
+                return new Data[0];
+            }
+            for (final ListGridRecord element : lgr) {
+                data.add(buildResult(element.getAttribute("from"), element.getAttribute("to")));
+            }
+            break;
+        default:
+            throw new IllegalStateException();
+        }
+        return data.toArray(new Data[data.size()]);
+    }
+
+    private final Data buildResult(final String startStr, final String endStr) {
+        final StringBuilder builder = new StringBuilder();
+        builder.append(startStr);
+        builder.append(",");
+        builder.append(endStr);
+        builder.append(";");
+        final DataItem item = new DefaultDataItem(getDatakey(), null, builder.toString());
+        return new DefaultData(getDatakey(), null, null, new DataItem[] { item });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractPairRecommendationPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,506 @@
+/* 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.client.client.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.event.StepForwardEvent;
+import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
+import org.dive4elements.river.client.client.services.RemoveArtifactServiceAsync;
+import org.dive4elements.river.client.shared.model.Artifact;
+import org.dive4elements.river.client.shared.model.Collection;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.Recommendation;
+import org.dive4elements.river.client.shared.model.Recommendation.Facet;
+import org.dive4elements.river.client.shared.model.Recommendation.Filter;
+import org.dive4elements.river.client.shared.model.User;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+// TODO Probably better to branch off AbstractUIProvider.
+// TODO Merge with other datacage-widget impls.
+/**
+ * Panel containing a Grid and a "next" button. The Grid is fed by a
+ * DatacagePairWidget which is put in the input-helper area.
+ */
+public abstract class AbstractPairRecommendationPanel
+extends      TextProvider {
+
+    /**
+     * Allows for abstraction on how to handle/serialize the recommendation and the used factories.
+     * Basically this allows to tweak the factory that is delivered from the datacage to be replaced by a specific one...
+     *
+     * @author Gernot Belger
+     */
+    public static interface IRecommendationInfo	{
+
+        String getFactory(String originalFactory);
+
+        /**
+         * Separate factory for the 'createDataString' method, because in the case of waterlevels. See HOTFIX/FIXME there.
+         * @param recommendation
+         */
+        String getDataStringFactory(Recommendation recommendation);
+
+        /**
+         * Set factory of recommendation such that the correct artifacts will
+         * be cloned for difference calculations.
+         */
+        void adjustRecommendation(Recommendation recommendation);
+    }
+
+    public static interface IValidator
+    {
+        List<String> validate(ListGrid differencesList, FLYSConstants msgProvider);
+    }
+
+    private static final long serialVersionUID = 8906629596491827857L;
+
+    private String dataName;
+
+    private final User user;
+
+    /** ListGrid that displays user-selected pairs to build differences with. */
+    private ListGrid differencesList;
+
+    /**
+     * List to track previously selected but now removed pairs. (Needed to
+     * be able to identify artifacts that can be removed from the collection.
+     */
+    private final List<RecommendationPairRecord> removedPairs =
+            new ArrayList<RecommendationPairRecord>();
+
+    /** Service handle to clone and add artifacts to collection. */
+    private final LoadArtifactServiceAsync loadArtifactService = GWT.create(
+            org.dive4elements.river.client.client.services.LoadArtifactService.class);
+
+    /** Service to remove artifacts from collection. */
+    private final RemoveArtifactServiceAsync removeArtifactService = GWT.create(
+            org.dive4elements.river.client.client.services.RemoveArtifactService.class);
+
+    private final IRecommendationInfo leftInfo;
+
+    private final IRecommendationInfo rightInfo;
+
+    private final IValidator validator;
+
+    /**
+     * @param Validates the content of this form when the user clicks 'apply'
+     * @param leftInfo Delegate for handling the left part of the recommendation-pair
+     * @param rightInfo Delegate for handling the right part of the recommendation-pair
+     */
+    public AbstractPairRecommendationPanel(final User user, final IValidator validator, final IRecommendationInfo leftInfo, final IRecommendationInfo rightInfo ) {
+        this.user = user;
+        this.validator = validator;
+        this.leftInfo = leftInfo;
+        this.rightInfo = rightInfo;
+    }
+
+    // FIXME: better than copy/pasting the MSG field into every sub-class but not really nice yet.
+    protected final static FLYSConstants msg() {
+        return MSG;
+    }
+
+    /**
+     * Remove first occurrence of "[" and "]" (if both do occur).
+     * @param value String to be stripped of [] (might be null).
+     * @return input string but with [ and ] removed, or input string if no
+     *         brackets were found.
+     * @see StringUtil.unbracket
+     */
+    // FIXME: check if this is the same as STringUItils#unbracket
+    private static final String unbracket(final String value) {
+        // null- guard.
+        if (value == null) return value;
+
+        final int start = value.indexOf("[");
+        final int end   = value.indexOf("]");
+
+        if (start < 0 || end < 0) {
+            return value;
+        }
+
+        return value.substring(start + 1, end);
+    }
+
+    /**
+     * Create a recommendation from a string representation of it.
+     * @param from string in format as shown above.
+     * @param leftInfo2
+     * @return recommendation from input string.
+     */
+    private Recommendation createRecommendationFromString(final String from, final IRecommendationInfo info) {
+        // TODO Construct "real" filter.
+        final String[] parts = unbracket(from).split(";");
+        final Recommendation.Filter filter = new Recommendation.Filter();
+        final Recommendation.Facet  facet  = new Recommendation.Facet(
+                parts[1],
+                parts[2]);
+
+        final List<Recommendation.Facet> facets = new ArrayList<Recommendation.Facet>();
+        facets.add(facet);
+        filter.add("longitudinal_section", facets);
+
+        final String factory = info.getFactory( parts[1] );
+
+        final  Recommendation r = new Recommendation(factory, parts[0], this.artifact.getUuid(), filter);
+        r.setDisplayName(parts[3]);
+        return r;
+    }
+
+
+    /**
+     * Add RecomendationPairRecords from input String to the ListGrid.
+     */
+    private void populateGridFromString(final String from){
+        // Split this string.
+        // Create according recommendations and display strings.
+        final String[] recs = from.split("#");
+        if (recs.length % 2 != 0) return;
+        for (int i = 0; i < recs.length; i+=2) {
+            final Recommendation minuend =
+                    createRecommendationFromString(recs[i+0], this.leftInfo);
+            final Recommendation subtrahend =
+                    createRecommendationFromString(recs[i+1], this.rightInfo);
+
+            final RecommendationPairRecord pr = new RecommendationPairRecord(
+                    minuend, subtrahend);
+            // This Recommendation Pair comes from the data string and was thus
+            // already cloned.
+            pr.setIsAlreadyLoaded(true);
+            this.differencesList.addData(pr);
+        }
+    }
+
+    /**
+     * Creates the graphical representation and interaction widgets for the data.
+     * @param dataList the data.
+     * @return graphical representation and interaction widgets for data.
+     */
+    @Override
+    public final Canvas create(final DataList dataList) {
+
+        final Canvas widget = createWidget();
+
+        final Canvas canvas = createChooserWidgets(widget, dataList, this.user, this.differencesList);
+
+        populateGrid(dataList);
+
+        return canvas;
+    }
+
+    /**
+     * Creates the individual parts of the input-helper area ('Eingabeunterstützung') for choosing the content of this widget.
+     */
+    protected abstract Canvas createChooserWidgets(final Canvas widget, final DataList dataList, final User auser, final ListGrid diffList);
+
+    private void populateGrid(final DataList dataList) {
+        final Data data     = dataList.get(0);
+        this.dataName = data.getLabel();
+        for (int i = 0; i < dataList.size(); i++) {
+            if (dataList.get(i) != null && dataList.get(i).getItems() != null) {
+                if (dataList.get(i).getItems() != null) {
+                    populateGridFromString(
+                            dataList.get(i).getItems()[0].getStringValue());
+                }
+            }
+        }
+    }
+
+    @Override
+    public final List<String> validate() {
+        return this.validator.validate(this.differencesList, msg());
+    }
+
+    /**
+     * Creates layout with grid that displays selection inside.
+     */
+    protected final Canvas createWidget() {
+        final VLayout layout  = new VLayout();
+        this.differencesList = new ListGrid();
+
+        this.differencesList.setCanEdit(false);
+        this.differencesList.setCanSort(false);
+        this.differencesList.setShowHeaderContextMenu(false);
+        this.differencesList.setHeight(150);
+        this.differencesList.setShowAllRecords(true);
+
+        final ListGridField nameField    = new ListGridField("first",  "Minuend");
+        final ListGridField capitalField = new ListGridField("second", "Subtrahend");
+        // Track removed rows, therefore more or less reimplement
+        // setCanRecomeRecords.
+        final ListGridField removeField  =
+                new ListGridField("_removeRecord", "Remove Record"){{
+                    setType(ListGridFieldType.ICON);
+                    setIcon(GWT.getHostPageBaseURL() + msg().removeFeature());
+                    setCanEdit(false);
+                    setCanFilter(false);
+                    setCanSort(false);
+                    setCanGroupBy(false);
+                    setCanFreeze(false);
+                    setWidth(25);
+                }};
+
+                this.differencesList.setFields(new ListGridField[] {nameField,
+                        capitalField, removeField});
+
+                this.differencesList.addRecordClickHandler(new RecordClickHandler() {
+                    @Override
+                    public void onRecordClick(final RecordClickEvent event) {
+                        // Just handle remove-clicks
+                        if(!event.getField().getName().equals(removeField.getName())) {
+                            return;
+                        }
+                        trackRemoved(event.getRecord());
+                        event.getViewer().removeData(event.getRecord());
+                    }
+                });
+                layout.addMember(this.differencesList);
+
+                return layout;
+    }
+
+
+    /**
+     * Add record to list of removed records.
+     */
+    protected final void trackRemoved(final Record r) {
+        final RecommendationPairRecord pr = (RecommendationPairRecord) r;
+        this.removedPairs.add(pr);
+    }
+
+    /**
+     * Validates data, does nothing if invalid, otherwise clones new selected
+     * waterlevels and add them to collection, forward the artifact.
+     */
+    @Override
+    public void onClick(final ClickEvent e) {
+        GWT.log("AbstractPairRecommendationPanel.onClick");
+
+        final List<String> errors = validate();
+        if (errors != null && !errors.isEmpty()) {
+            showErrors(errors);
+            return;
+        }
+
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
+
+        final ListGridRecord[] records = this.differencesList.getRecords();
+
+        final List<Recommendation> ar  = new ArrayList<Recommendation>();
+        final List<Recommendation> all = new ArrayList<Recommendation>();
+
+        for (final ListGridRecord record : records) {
+            final RecommendationPairRecord r =
+                    (RecommendationPairRecord) record;
+            // Do not add "old" recommendations.
+            if (!r.isAlreadyLoaded()) {
+                // Check whether one of those is a dike or similar.
+                // TODO differentiate and merge: new clones, new, old.
+                final Recommendation firstR = r.getFirst();
+                this.leftInfo.adjustRecommendation(firstR);
+
+                final Recommendation secondR = r.getSecond();
+                this.rightInfo.adjustRecommendation(secondR);
+                ar.add(firstR);
+                ar.add(secondR);
+            }
+            else {
+                all.add(r.getFirst());
+                all.add(r.getSecond());
+            }
+        }
+
+        final Recommendation[] toClone = ar.toArray(new Recommendation[ar.size()]);
+        final Recommendation[] toUse   = all.toArray(new Recommendation[all.size()]);
+
+        // Find out whether "old" artifacts have to be removed.
+        final List<String> artifactIdsToRemove = new ArrayList<String>();
+        for (final RecommendationPairRecord rp: this.removedPairs) {
+            Recommendation first  = rp.getFirst();
+            Recommendation second = rp.getSecond();
+
+            for (final Recommendation recommendation: toUse) {
+                if (first != null && first.getIDs().equals(recommendation.getIDs())) {
+                    first = null;
+                }
+                if (second != null && second.getIDs().equals(recommendation.getIDs())) {
+                    second = null;
+                }
+
+                if (first == null && second == null) {
+                    break;
+                }
+            }
+            if (first != null) {
+                artifactIdsToRemove.add(first.getIDs());
+            }
+            if (second != null) {
+                artifactIdsToRemove.add(second.getIDs());
+            }
+        }
+
+        // Remove old artifacts, if any. Do this asychronously without much
+        // feedback.
+        for(final String uuid: artifactIdsToRemove) {
+            this.removeArtifactService.remove(this.collection,
+                    uuid,
+                    locale,
+                    new AsyncCallback<Collection>() {
+                @Override
+                public void onFailure(final Throwable caught) {
+                    GWT.log("RemoveArtifact (" + uuid + ") failed.");
+                }
+                @Override
+                public void onSuccess(final Collection coll) {
+                    GWT.log("RemoveArtifact succeeded");
+                }
+            });
+        }
+
+        // Clone new ones (and spawn statics), go forward.
+        this.parameterList.lockUI();
+        this.loadArtifactService.loadMany(
+                this.collection,
+                toClone,
+                //"staticwkms" and "waterlevel"
+                null,
+                locale,
+                new AsyncCallback<Artifact[]>() {
+                    @Override
+                    public void onFailure(final Throwable caught) {
+                        caught.printStackTrace();
+                        GWT.log("Failure of cloning with factories!");
+                        AbstractPairRecommendationPanel.this.parameterList.unlockUI();
+                    }
+                    @Override
+                    public void onSuccess(final Artifact[] artifacts) {
+                        GWT.log("Successfully cloned " + toClone.length +
+                                " with factories.");
+
+                        fireStepForwardEvent(new StepForwardEvent(
+                                getData(toClone, artifacts, toUse)));
+                        AbstractPairRecommendationPanel.this.parameterList.unlockUI();
+                    }
+                });
+    }
+
+    /**
+     * Create Data and DataItem from selection (a long string with identifiers
+     * to construct diff-pairs).
+     *
+     * @param newRecommendations "new" recommendations (did not survive a
+     *        backjump).
+     * @param newArtifacts artifacts cloned from newRecommendations.
+     * @param oldRecommendations old recommendations that survived a backjump.
+     *
+     * @return dataitem with a long string with identifiers to construct
+     *         diff-pairs.
+     */
+    protected final Data[] getData(
+            final Recommendation[] newRecommendations,
+            final Artifact[] newArtifacts,
+            final Recommendation[] oldRecommendations)
+    {
+        // Construct string with info about selections.
+        String dataItemString = "";
+        for (int i = 0; i < newRecommendations.length; i++) {
+            final Recommendation r = newRecommendations[i];
+            final Artifact newArtifact = newArtifacts[i];
+            final String uuid = newArtifact.getUuid();
+            r.setMasterArtifact(uuid);
+
+            if (i>0)
+                dataItemString += "#";
+
+            // REMARK: ugly, but we know that the recommandations comes in left/right pairs.
+            final IRecommendationInfo info = i % 2 == 0 ? this.leftInfo : this.rightInfo;
+
+            dataItemString += createDataString(uuid, r, info);
+        }
+
+        for (int i = 0; i < oldRecommendations.length; i++) {
+            final Recommendation r = oldRecommendations[i];
+            final String uuid = r.getIDs();
+
+            if (dataItemString.length() > 0)
+                dataItemString += "#";
+
+            // REMARK: ugly, but we know that the recommandations comes in left/right pairs.
+            final IRecommendationInfo info = i % 2 == 0 ? this.leftInfo : this.rightInfo;
+
+            dataItemString += createDataString(uuid, r, info);
+        }
+
+        // TODO some hassle could be resolved by using multiple DataItems
+        // (e.g. one per pair).
+        final DataItem item = new DefaultDataItem(this.dataName, this.dataName, dataItemString);
+        return new Data[] { new DefaultData(
+                this.dataName, null, null, new DataItem[] {item}) };
+    }
+
+    /**
+     * Creates part of the String that encodes minuend or subtrahend.
+     * @param recommendation Recommendation to wrap in string.
+     * @param info Provides the factory to encode.
+     */
+    protected static final String createDataString(final String artifactUuid, final Recommendation recommendation, final IRecommendationInfo info) {
+        final String factory = info.getDataStringFactory( recommendation );
+
+        final Filter filter = recommendation.getFilter();
+        Facet  f      = null;
+
+        if(filter != null) {
+            final Map<String, List<Facet>>               outs = filter.getOuts();
+            final Set<Map.Entry<String, List<Facet>>> entries = outs.entrySet();
+
+            for (final Map.Entry<String, List<Facet>> entry: entries) {
+                final List<Facet> fs = entry.getValue();
+
+                f = fs.get(0);
+                if (f != null) {
+                    break;
+                }
+            }
+
+            return "[" + artifactUuid + ";"
+            + f.getName()
+            + ";"
+            + f.getIndex()
+            + ";"
+            + recommendation.getDisplayName() + "]";
+        }
+
+        return "["
+        + artifactUuid
+        + ";" + factory + ";0;"
+        + recommendation.getDisplayName() + "]";
+    }
+}
\ 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/AbstractSingleItemPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,258 @@
+/** 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.river.client.client.ui.FromToTableHelperPanel.IColumnClickHandler;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class AbstractSingleItemPanel extends AbstractUIProvider {
+
+    private static final long serialVersionUID = 1L;
+
+    public enum Type {
+        single, multi, limit5 // "SingleItem" (Klassenname) meint, dass es nur ein einziges Eingabefeld gibt (nicht from-to; epoch)
+        // Type multi: append (year): es können mehrere Werte eingegeben werden; Leerzeichen-getrennt
+        // Type single: append (year, sohlhöhendifferenz): nur ein Wert ist zulässig
+        // Type limit5 TODO: generalize, if needed
+    }
+
+    private final Type type;
+
+    private TextItem inputItem;
+
+    private List<String> validInputs = new ArrayList<String>();
+
+    protected abstract String getDatakey();
+
+    protected abstract Canvas createWidget(final DataList data);
+
+    public AbstractSingleItemPanel(final Type type) {
+        this.type = type;
+    }
+
+    @Override
+    public final Canvas create(final DataList data) {
+        final VLayout layout = new VLayout();
+        final IColumnClickHandler fromHandler = new IColumnClickHandler() { // add to external class
+
+            @Override
+            public void columnClicked(final String value) {
+                appendValue(value);
+            }
+        };
+
+        final FromToTableHelperPanel helper = new FromToTableHelperPanel(data, getDatakey(), this.MSG, fromHandler, null);
+        final Canvas table = helper.getTable();
+        this.validInputs = helper.getKeycolEntries();
+
+        this.helperContainer.addMember(table);
+
+        final Canvas submit = getNextButton();
+        final Canvas widget = createWidget(data);
+
+        layout.addMember(widget);
+        layout.addMember(submit);
+
+        return layout;
+    }
+
+    @Override
+    public final Canvas createOld(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
+        final Data years = getData(items, getDatakey());
+        final DataItem[] yearsItems = years.getItems();
+
+        final String v1 = yearsItems[0].getStringValue().replace(" ", ", ");
+
+        final Label old = new Label(v1);
+        final HLayout layout = new HLayout();
+        layout.setWidth("400px");
+
+        final Label label = new Label(dataList.getLabel());
+        label.setWidth("200px");
+
+        final Canvas back = getBackButton(dataList.getState());
+
+        layout.addMember(label);
+        layout.addMember(old);
+        layout.addMember(back);
+
+        return layout;
+    }
+
+    @Override
+    protected final Data[] getData() {
+        final List<String> errors = this.validate();
+        if (errors.size() > 0) {
+            showErrors(errors); // TODO: do not allow advance state
+            // return null;
+        }
+        if (this.inputItem != null && !this.inputItem.getValueAsString().isEmpty()) {
+            final List<Data> data = new ArrayList<Data>();
+
+            final DataItem yearsdata = new DefaultDataItem(getDatakey(), getDatakey(), this.inputItem.getValueAsString().trim());
+            data.add(new DefaultData(getDatakey(), null, null, new DataItem[] { yearsdata }));
+
+            return data.toArray(new Data[data.size()]);
+        }
+        return new Data[0];
+    }
+
+    protected final TextItem createInputItem(final String title) {
+        this.inputItem = PanelHelper.createItem(title);// new TextItem(title);
+        return this.inputItem;
+    }
+
+    private final List<String> checkForEmpty() {
+        final List<String> errors = new ArrayList<String>();
+
+        if (this.inputItem.getValueAsString() == null || this.inputItem.getValueAsString().trim().isEmpty()) {
+            errors.add(this.MSG.empty_filter());
+            return errors;
+        }
+        return errors;
+    }
+
+    private final List<String> validateSingleInput(final String sValue) {
+        final List<String> errors = new ArrayList<String>();
+        // String filtered = "";
+        // int goodValues = 0;
+        errors.addAll(validateNumber(sValue));
+        boolean isGood = false;
+        for (final String validYear : this.validInputs) {
+            /* No list contains for strings? */
+            if (sValue.equals(validYear)) {
+                isGood = true;
+                break;
+            }
+        }
+        if (!isGood) {
+            String tmp = errorForItemMsg();
+            tmp = tmp.replace("$1", sValue);
+            errors.add(tmp);
+            // continue;
+        }
+
+        return errors;
+    }
+
+    private final List<String> validateNumber(final String sValue) {
+        final List<String> errors = new ArrayList<String>();
+
+        try {
+            Integer.parseInt(sValue);
+        }
+        catch (final NumberFormatException e) {
+            errors.add(this.MSG.wrongFormat() + ": " + sValue);
+
+        }
+        return errors;
+    }
+
+    protected abstract String errorForItemMsg();
+
+    protected final void appendValue(final String value) {
+
+        switch (this.type) {
+        case multi:
+            // APPEND = ADD to existing -> MULTI YEAR
+            final String oldYears = this.inputItem.getValueAsString();
+            if (oldYears != null && !oldYears.isEmpty())
+                this.inputItem.setValue(oldYears.trim() + " " + value);
+            else
+                this.inputItem.setValue(value);
+
+            break;
+
+        case limit5:
+            // APPEND = ADD to existing -> MULTI YEAR
+            final String oldValues = this.inputItem.getValueAsString();
+            if (oldValues != null && !oldValues.isEmpty()) {
+                final String[] oldVals = oldValues.split(" ");
+                if (oldVals.length < 5)// TODO: generalize, if needed
+                    this.inputItem.setValue(oldValues.trim() + " " + value);
+                else {
+                    // msg TODO: generalize, if needed
+                    SC.warn(this.MSG.error_limit_exceeded_salix());
+                }
+            }
+
+            else
+                this.inputItem.setValue(value);
+
+            break;
+
+        case single:
+            this.inputItem.setValue(value);
+            break;
+
+        default:
+            throw new IllegalStateException();
+        }
+    }
+
+    @Override
+    public final List<String> validate() {
+
+        final List<String> errors = new ArrayList<String>();
+        errors.addAll(this.checkForEmpty());
+
+        final String sValue = this.inputItem.getValueAsString();
+
+        switch (this.type) {
+        case multi:
+            if (sValue != null) {
+                final String[] sValues = sValue.trim().split(" ");
+                for (final String value : sValues) {
+                    errors.addAll(this.validateSingleInput(value));
+                }
+            }
+            break;
+        case limit5:
+            if (sValue != null) {
+                final String[] values = sValue.trim().split(" ");
+                if (values.length > 5) {
+                    errors.add(this.MSG.error_limit_exceeded_salix());// TODO generalize if needed
+                }
+                for (int i = 0; i < values.length; i++) {
+                    if (i < 5)
+                        errors.addAll(this.validateNumber(values[i]));
+                }
+            }
+            break;
+        case single:
+            errors.addAll(this.validateSingleInput(sValue));
+            break;
+
+        default:
+            throw new IllegalStateException();
+        }
+
+        return errors;
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,18 +8,11 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
+import java.util.ArrayList;
+import java.util.List;
 
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Button;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Img;
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-import com.smartgwt.client.widgets.layout.VLayout;
-
+import org.dive4elements.river.client.client.FLYS;
 import org.dive4elements.river.client.client.FLYSConstants;
-import org.dive4elements.river.client.client.FLYS;
 import org.dive4elements.river.client.client.event.HasStepBackHandlers;
 import org.dive4elements.river.client.client.event.HasStepForwardHandlers;
 import org.dive4elements.river.client.client.event.StepBackEvent;
@@ -35,19 +28,21 @@
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 
-import java.util.ArrayList;
-import java.util.List;
-
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Img;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.layout.VLayout;
 
 /**
  * An abstract UIProvider that provides some basic methods.
  *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public abstract class AbstractUIProvider
-implements   UIProvider, HasStepForwardHandlers, ClickHandler,
-             HasStepBackHandlers
-{
+public abstract class AbstractUIProvider implements UIProvider, HasStepForwardHandlers, ClickHandler, HasStepBackHandlers {
     private static final long serialVersionUID = -1610874613377494184L;
 
     /** The message class that provides i18n strings. */
@@ -75,90 +70,86 @@
      * Creates a new UIProvider instance of this class.
      */
     public AbstractUIProvider() {
-        forwardHandlers = new ArrayList<StepForwardHandler>();
-        backHandlers    = new ArrayList<StepBackHandler>();
+        this.forwardHandlers = new ArrayList<StepForwardHandler>();
+        this.backHandlers = new ArrayList<StepBackHandler>();
     }
 
-
     /**
      * Appends a StepBackHandler that wants to listen to StepBackEvents.
      *
-     * @param handler A new StepBackHandler.
+     * @param handler
+     *            A new StepBackHandler.
      */
     @Override
-    public void addStepBackHandler(StepBackHandler handler) {
+    public void addStepBackHandler(final StepBackHandler handler) {
         if (handler != null) {
-            backHandlers.add(handler);
+            this.backHandlers.add(handler);
         }
     }
 
-
     /**
      * Appends a StepForwardHandler that wants to listen to StepForwardEvents.
      *
-     * @param handler A new StepForwardHandler.
+     * @param handler
+     *            A new StepForwardHandler.
      */
     @Override
-    public void addStepForwardHandler(StepForwardHandler handler) {
+    public void addStepForwardHandler(final StepForwardHandler handler) {
         if (handler != null) {
-            forwardHandlers.add(handler);
+            this.forwardHandlers.add(handler);
         }
     }
 
-
     /**
      * This method is called after the user has clicked one of the buttons to
      * step back to a previous state.
      *
-     * @param e The StepBackEvent.
+     * @param e
+     *            The StepBackEvent.
      */
-    protected void fireStepBackEvent(StepBackEvent e) {
-        GWT.log("AbstractUIProvider - fireStepBackEvent() handlers: "
-            + backHandlers.size());
-        for (StepBackHandler handler: backHandlers) {
+    protected void fireStepBackEvent(final StepBackEvent e) {
+        GWT.log("AbstractUIProvider - fireStepBackEvent() handlers: " + this.backHandlers.size());
+        for (final StepBackHandler handler : this.backHandlers) {
             handler.onStepBack(e);
         }
     }
 
-
     /**
      * This method is called after the user has clicked on the 'next' button to
      * step to the next state.
      *
-     * @param e The StepForwardEvent.
+     * @param e
+     *            The StepForwardEvent.
      */
-    protected void fireStepForwardEvent(StepForwardEvent e) {
-        GWT.log("AbstractUIProvider - fireStepForwardEvent() handlers: "
-            + forwardHandlers.size());
-        for (StepForwardHandler handler: forwardHandlers) {
+    protected void fireStepForwardEvent(final StepForwardEvent e) {
+        GWT.log("AbstractUIProvider - fireStepForwardEvent() handlers: " + this.forwardHandlers.size());
+        for (final StepForwardHandler handler : this.forwardHandlers) {
             handler.onStepForward(e);
         }
     }
 
-
     /**
      * This method is used to listen to click events on the 'next' button. The
      * fireStepForwardEvent() method is called here.
      *
-     * @param e The click event.
+     * @param e
+     *            The click event.
      */
     @Override
-    public void onClick(ClickEvent e) {
-        List<String> errors = validate();
+    public void onClick(final ClickEvent e) {
+        final List<String> errors = validate();
         if (errors == null || errors.isEmpty()) {
-            Data[] data = getData();
+            final Data[] data = getData();
             fireStepForwardEvent(new StepForwardEvent(data));
-        }
-        else {
+        } else {
             showErrors(errors);
         }
     }
 
+    protected void showErrors(final List<String> errors) {
+        final StringBuilder sb = new StringBuilder();
 
-    protected void showErrors(List<String> errors) {
-        StringBuilder sb = new StringBuilder();
-
-        for (String error: errors) {
+        for (final String error : errors) {
             sb.append(error);
             sb.append("<br>");
         }
@@ -166,43 +157,41 @@
         SC.warn(sb.toString());
     }
 
-
     /**
      * Creates the 'next' button to step forward to the next state.
      *
      * @return the 'next' button.
      */
     protected Canvas getNextButton() {
-        Button next = new Button(MSG.buttonNext());
+        final Button next = new Button(this.MSG.buttonNext());
         next.addClickHandler(this);
 
         return next;
     }
 
-
     @Override
-    public Canvas createHelpLink(DataList dataList, Data data, FLYS instance) {
-        String iUrl    = GWT.getHostPageBaseURL() + MSG.getFeatureInfo();
-        String helpUrl = dataList.getHelpText();
+    public Canvas createHelpLink(final DataList dataList, final Data data, final FLYS instance) {
+        final String iUrl = GWT.getHostPageBaseURL() + this.MSG.getFeatureInfo();
+        final String helpUrl = dataList.getHelpText();
 
         return new WikiImgLink(iUrl, helpUrl, 30, 30, instance);
     }
 
-
     /**
      * Creates the 'back' button to step back to a previous state.
      *
-     * @param targetState The identifier of the target state.
+     * @param targetState
+     *            The identifier of the target state.
      *
      * @return the 'back' button.
      */
     protected Canvas getBackButton(final String targetState) {
-        String url = GWT.getHostPageBaseURL() + MSG.imageBack();
-        Img back   = new Img(url, 16, 16);
+        final String url = GWT.getHostPageBaseURL() + this.MSG.imageBack();
+        final Img back = new Img(url, 16, 16);
 
         back.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(ClickEvent event) {
+            public void onClick(final ClickEvent event) {
                 fireStepBackEvent(new StepBackEvent(targetState));
             }
         });
@@ -210,77 +199,73 @@
         return back;
     }
 
-
     /**
      * This method injects a container that is used to position helper widgets.
      *
-     * @param helperContainer A container that is used to position helper
-     * widgets.
+     * @param helperContainer
+     *            A container that is used to position helper
+     *            widgets.
      */
     @Override
-    public void setContainer(VLayout helperContainer) {
+    public void setContainer(final VLayout helperContainer) {
         this.helperContainer = helperContainer;
     }
 
-
     /**
      * This method injects an artifact that contains the status information.
      *
-     * @param art An artifact containing status information.
+     * @param art
+     *            An artifact containing status information.
      */
     @Override
-    public void setArtifact(Artifact art) {
+    public void setArtifact(final Artifact art) {
         this.artifact = art;
     }
 
-
     @Override
-    public void setCollection(Collection collection) {
+    public void setCollection(final Collection collection) {
         this.collection = collection;
     }
 
-
     @Override
-    public void setParameterList(ParameterList list) {
+    public void setParameterList(final ParameterList list) {
         this.parameterList = list;
     }
 
-
     public Collection getCollection() {
-        return collection;
+        return this.collection;
     }
 
-
     /**
      * This method greps the Data with name <i>name</i> from the list and
      * returns it.
      *
-     * @param items A list of Data.
-     * @param name The name of the Data that we are searching for.
+     * @param items
+     *            A list of Data.
+     * @param name
+     *            The name of the Data that we are searching for.
      *
      * @return the Data with the name <i>name</i>.
      */
-    protected Data getData(List<Data> data, String name) {
-        for (Data d: data) {
+    protected Data getData(final List<Data> data, final String name) {
+        for (final Data d : data) {
             if (name.equals(d.getLabel())) {
                 return d;
             }
         }
-
         return null;
     }
 
+    protected String getDataValue(final String state, final String name) {
+        final ArtifactDescription desc = this.artifact.getArtifactDescription();
 
-    protected String getDataValue(String state, String name) {
-        ArtifactDescription desc = artifact.getArtifactDescription();
+        final DataList[] old = desc.getOldData();
 
-        DataList[] old = desc.getOldData();
-
-        for (DataList list: old) {
+        for (final DataList list : old) {
             if (list == null) {
                 continue;
             }
-            Data d = getData(list.getAll(), name);
+            final Data d = getData(list.getAll(), name);
 
             if (d != null) {
                 return d.getItems()[0].getStringValue();
@@ -294,13 +279,15 @@
      * This method greps the DataItem with name <i>name</i> from the list and
      * returns it.
      *
-     * @param items A list of DataItems.
-     * @param name The name of the DataItem that we are searching for.
+     * @param items
+     *            A list of DataItems.
+     * @param name
+     *            The name of the DataItem that we are searching for.
      *
      * @return the DataItem with the name <i>name</i>.
      */
-    protected DataItem getDataItem(DataItem[] items, String name) {
-        for (DataItem item: items) {
+    protected DataItem getDataItem(final DataItem[] items, final String name) {
+        for (final DataItem item : items) {
             if (name.equals(item.getLabel())) {
                 return item;
             }
@@ -309,38 +296,34 @@
         return null;
     }
 
-
+    /**
+     * Validates the selection.
+     *
+     * @return List of internationalized errror messages (if any).
+     */
     public List<String> validate() {
         return new ArrayList<String>(); // FIXME: What's this?
     }
 
-
     /** Create simple DefaultData with single DataItem inside. */
-    public static DefaultData createDataArray(String name, String value) {
-        DataItem item = new DefaultDataItem(
-            name,
-            name,
-            value);
+    public static DefaultData createDataArray(final String name, final String value) {
+        final DataItem item = new DefaultDataItem(name, name, value);
 
-        return new DefaultData(name,
-            null,
-            null,
-            new DataItem[] {item});
+        return new DefaultData(name, null, null, new DataItem[] { item });
     }
 
-
     /**
      * This method needs to be implemented by concrete subclasses. It should
      * create a new Canvas object with a representation of <i>data</i>.
      *
-     * @param data The data that should be displayed.
+     * @param data
+     *            The data that should be displayed.
      *
      * @return a Canvas object that displays <i>data</i>.
      */
     @Override
     public abstract Canvas create(DataList data);
 
-
     /**
      * This method needs to be implemented by concrete subclasses. It should
      * return the selected data.
@@ -348,5 +331,11 @@
      * @return the selected data.
      */
     protected abstract Data[] getData();
+
+    protected String getRiverName() {
+        final ArtifactDescription adescr = this.artifact.getArtifactDescription();
+        return adescr.getRiver();
+    }
+
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/CollectionView.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/CollectionView.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,28 +8,16 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import com.smartgwt.client.util.SC;
-
-import com.smartgwt.client.widgets.Window;
-
-import com.smartgwt.client.widgets.events.CloseClickEvent;
-import com.smartgwt.client.widgets.events.CloseClickHandler;
-
-import com.smartgwt.client.widgets.layout.Layout;
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import com.smartgwt.client.widgets.tab.TabSet;
-
-import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
 
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYS;
 import org.dive4elements.river.client.client.FLYSConstants;
-
 import org.dive4elements.river.client.client.event.CollectionChangeEvent;
 import org.dive4elements.river.client.client.event.CollectionChangeHandler;
 import org.dive4elements.river.client.client.event.HasCollectionChangeHandlers;
@@ -38,7 +26,6 @@
 import org.dive4elements.river.client.client.event.OutputModesChangeHandler;
 import org.dive4elements.river.client.client.event.ParameterChangeEvent;
 import org.dive4elements.river.client.client.event.ParameterChangeHandler;
-
 import org.dive4elements.river.client.client.services.AddArtifactService;
 import org.dive4elements.river.client.client.services.AddArtifactServiceAsync;
 import org.dive4elements.river.client.client.services.ArtifactService;
@@ -51,7 +38,6 @@
 import org.dive4elements.river.client.client.services.DescribeCollectionServiceAsync;
 import org.dive4elements.river.client.client.services.LoadArtifactService;
 import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
-
 import org.dive4elements.river.client.shared.model.Artifact;
 import org.dive4elements.river.client.shared.model.ArtifactDescription;
 import org.dive4elements.river.client.shared.model.Collection;
@@ -61,45 +47,37 @@
 import org.dive4elements.river.client.shared.model.ReportMode;
 import org.dive4elements.river.client.shared.model.User;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Window;
+import com.smartgwt.client.widgets.events.CloseClickEvent;
+import com.smartgwt.client.widgets.events.CloseClickHandler;
+import com.smartgwt.client.widgets.layout.Layout;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.TabSet;
+import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
 
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class CollectionView
-extends      Window
-implements   CollectionChangeHandler, HasCollectionChangeHandlers,
-             OutputModesChangeHandler, HasOutputModesChangeHandlers,
-             ParameterChangeHandler, CloseClickHandler
-{
+public class CollectionView extends Window implements CollectionChangeHandler, HasCollectionChangeHandlers, OutputModesChangeHandler, HasOutputModesChangeHandlers, ParameterChangeHandler, CloseClickHandler {
     /** The ArtifactService used to communicate with the Artifact server. */
-    protected CreateCollectionServiceAsync createCollectionService =
-        GWT.create(CreateCollectionService.class);
+    protected CreateCollectionServiceAsync createCollectionService = GWT.create(CreateCollectionService.class);
 
     /** The ArtifactService used to communicate with the Artifact server. */
-    protected ArtifactServiceAsync createArtifactService =
-        GWT.create(ArtifactService.class);
+    protected ArtifactServiceAsync createArtifactService = GWT.create(ArtifactService.class);
 
     /** The AddArtifactService used to add an artifact to a collection. */
-    protected AddArtifactServiceAsync addArtifactService =
-        GWT.create(AddArtifactService.class);
+    protected AddArtifactServiceAsync addArtifactService = GWT.create(AddArtifactService.class);
 
     /** The DescribeCollectionService used to update the existing collection. */
-    protected DescribeCollectionServiceAsync describeCollectionService =
-        GWT.create(DescribeCollectionService.class);
+    protected DescribeCollectionServiceAsync describeCollectionService = GWT.create(DescribeCollectionService.class);
 
-    protected CollectionAttributeServiceAsync updater =
-        GWT.create(CollectionAttributeService.class);
+    protected CollectionAttributeServiceAsync updater = GWT.create(CollectionAttributeService.class);
 
-    /** The LoadArtifactService used to load recommendations*/
-    protected LoadArtifactServiceAsync loadArtifactService =
-        GWT.create(LoadArtifactService.class);
+    /** The LoadArtifactService used to load recommendations */
+    protected LoadArtifactServiceAsync loadArtifactService = GWT.create(LoadArtifactService.class);
 
     /** The message class that provides i18n strings. */
     protected FLYSConstants messages = GWT.create(FLYSConstants.class);
@@ -137,7 +115,7 @@
     protected int recommendationQueue;
     protected Stack<Recommendation> newRecommendations;
 
-    /** Values for fix analysis charts*/
+    /** Values for fix analysis charts */
     protected double currentKm;
     protected double minKm;
     protected double maxKm;
@@ -147,18 +125,17 @@
      * This constructor creates a new CollectionView that is used to display the
      * <i>collection</i>.
      */
-    public CollectionView(FLYS flys) {
-        this.flys          = flys;
-        this.tabs          = new TabSet();
-        this.outputTabs    = new HashMap<String, OutputTab>();
-        this.handlers      = new ArrayList<CollectionChangeHandler>();
-        this.outHandlers   = new ArrayList<OutputModesChangeHandler>();
-        this.layout        = new VLayout();
-        this.parameterList = new ParameterList(
-            flys, this, messages.new_project());
-        this.artifactsQueue      = 0;
+    public CollectionView(final FLYS flys) {
+        this.flys = flys;
+        this.tabs = new TabSet();
+        this.outputTabs = new HashMap<String, OutputTab>();
+        this.handlers = new ArrayList<CollectionChangeHandler>();
+        this.outHandlers = new ArrayList<OutputModesChangeHandler>();
+        this.layout = new VLayout();
+        this.parameterList = new ParameterList(flys, this, this.messages.new_project());
+        this.artifactsQueue = 0;
         this.recommendationQueue = 0;
-        this.newRecommendations  = new Stack<Recommendation>();
+        this.newRecommendations = new Stack<Recommendation>();
 
         this.currentKm = -1d;
         this.minKm = -1d;
@@ -166,29 +143,30 @@
         this.steps = -1d;
 
         addCollectionChangeHandler(this);
-        addCollectionChangeHandler(parameterList);
+        addCollectionChangeHandler(this.parameterList);
         addCollectionChangeHandler(flys);
         addOutputModesChangeHandler(this);
-        addOutputModesChangeHandler(parameterList);
+        addOutputModesChangeHandler(this.parameterList);
         addCloseClickHandler(this);
 
-        parameterList.addParameterChangeHandler(this);
+        this.parameterList.addParameterChangeHandler(this);
 
         init();
     }
 
     /**
-     * @param collection The collection to be displayed.
+     * @param collection
+     *            The collection to be displayed.
      */
-    public CollectionView(FLYS flys, Collection collection, Artifact artifact) {
-        this.flys          = flys;
-        this.artifact      = artifact;
-        this.collection    = collection;
-        this.tabs          = new TabSet();
-        this.outputTabs    = new HashMap<String, OutputTab>();
-        this.handlers      = new ArrayList<CollectionChangeHandler>();
-        this.outHandlers   = new ArrayList<OutputModesChangeHandler>();
-        this.layout        = new VLayout();
+    public CollectionView(final FLYS flys, final Collection collection, final Artifact artifact) {
+        this.flys = flys;
+        this.artifact = artifact;
+        this.collection = collection;
+        this.tabs = new TabSet();
+        this.outputTabs = new HashMap<String, OutputTab>();
+        this.handlers = new ArrayList<CollectionChangeHandler>();
+        this.outHandlers = new ArrayList<OutputModesChangeHandler>();
+        this.layout = new VLayout();
 
         this.currentKm = -1d;
         this.minKm = -1d;
@@ -196,28 +174,27 @@
         this.steps = -1d;
 
         if (artifact != null) {
-            this.parameterList = new ParameterList(
-                flys,
-                this,
-                messages.getString(artifact.getName()),
-                artifact);
-        }
-        else {
-            this.parameterList = new ParameterList(
-                flys, this, messages.new_project());
+            this.parameterList = new ParameterList(flys, this,
+                    // FIXME: literally every information about the artifact is transported from the server side
+                    // but... the international name is resolved client-side.... Instead also transport the description of the artifact and
+                    // use it!
+                    // FIXME: the same holds for a very few other international strings (e.g. names of facets used in Tabs)
+                    this.messages.getString(artifact.getName()), artifact);
+        } else {
+            this.parameterList = new ParameterList(flys, this, this.messages.new_project());
         }
 
-        this.artifactsQueue     = 0;
+        this.artifactsQueue = 0;
         this.newRecommendations = new Stack<Recommendation>();
 
         addCollectionChangeHandler(this);
-        addCollectionChangeHandler(parameterList);
+        addCollectionChangeHandler(this.parameterList);
         addCollectionChangeHandler(flys);
         addOutputModesChangeHandler(this);
-        addOutputModesChangeHandler(parameterList);
+        addOutputModesChangeHandler(this.parameterList);
         addCloseClickHandler(this);
 
-        parameterList.addParameterChangeHandler(this);
+        this.parameterList.addParameterChangeHandler(this);
 
         init();
 
@@ -228,7 +205,6 @@
         }
     }
 
-
     /**
      * This method handles the initial layout stuff.
      */
@@ -238,7 +214,7 @@
 
         setMaximized(true);
 
-        layout.setWidth100();
+        this.layout.setWidth100();
 
         setCanDragReposition(true);
         setCanDragResize(true);
@@ -247,79 +223,72 @@
 
         setTitle("");
 
-        addItem(layout);
+        addItem(this.layout);
 
-        layout.addMember(tabs);
-        tabs.addTab(parameterList);
+        this.layout.addMember(this.tabs);
+        this.tabs.addTab(this.parameterList);
     }
 
     protected FLYS getFlys() {
-        return flys;
+        return this.flys;
     }
 
-
     /**
      * This method registers a new CollectionChangeHandler.
      *
-     * @param handler The new CollectionChangeHandler.
+     * @param handler
+     *            The new CollectionChangeHandler.
      */
     @Override
-    public void addCollectionChangeHandler(CollectionChangeHandler handler) {
+    public void addCollectionChangeHandler(final CollectionChangeHandler handler) {
         if (handler != null) {
-            handlers.add(handler);
+            this.handlers.add(handler);
         }
     }
 
-
     /**
      * This method registers a new OutputModesChangeHandler.
      *
-     * @param handler The new OutputModesChangeHandler.
+     * @param handler
+     *            The new OutputModesChangeHandler.
      */
     @Override
-    public void addOutputModesChangeHandler(OutputModesChangeHandler handler) {
+    public void addOutputModesChangeHandler(final OutputModesChangeHandler handler) {
         if (handler != null) {
-            outHandlers.add(handler);
+            this.outHandlers.add(handler);
         }
     }
 
-
     /**
      * This method calls the <code>onValueChange()</code> method of all
      * registered ValueChangeHanders.
      */
-    protected void fireCollectionChangeEvent(
-        Collection old, Collection newCol)
-    {
-        for (CollectionChangeHandler handler: handlers) {
+    protected void fireCollectionChangeEvent(final Collection old, final Collection newCol) {
+        for (final CollectionChangeHandler handler : this.handlers) {
             handler.onCollectionChange(new CollectionChangeEvent(old, newCol));
         }
     }
 
-
-    protected void fireOutputModesChangeEvent(OutputMode[] outputs) {
-        if (collection == null) {
+    protected void fireOutputModesChangeEvent(final OutputMode[] outputs) {
+        if (this.collection == null) {
             return;
         }
 
-        for (OutputModesChangeHandler handler: outHandlers) {
+        for (final OutputModesChangeHandler handler : this.outHandlers) {
             handler.onOutputModesChange(new OutputModesChangeEvent(outputs));
         }
     }
 
-
     /** Disables input, grey out, show spinning wheel of joy. */
     public void lockUI() {
-        lockScreen = ScreenLock.lockUI(layout, lockScreen);
+        this.lockScreen = ScreenLock.lockUI(this.layout, this.lockScreen);
     }
 
-
     /** Enable input, remove grey, remove spinning wheel of joy. */
     public void unlockUI() {
-        ScreenLock.unlockUI(layout, lockScreen);
+        ScreenLock.unlockUI(this.layout, this.lockScreen);
     }
 
-
     /**
      * This method returns true, if the Collection is new and no plugins has
      * been chosen.
@@ -327,67 +296,62 @@
      * @return true, if the Collection is new.
      */
     public boolean isNew() {
-        return collection.hasItems();
+        return this.collection.hasItems();
     }
 
-
     /**
      * Returns the artifact that is used for the parameterization.
      *
      * @return the artifact that is used for the parameterization.
      */
     public Artifact getArtifact() {
-        return artifact;
+        return this.artifact;
     }
 
-
     public User getUser() {
         return getFlys().getCurrentUser();
     }
 
-
     /**
      * Set the current artifact that is the master of the parameterization.
      *
-     * @param artifact The new artifact.
+     * @param artifact
+     *            The new artifact.
      */
-    public void setArtifact(Artifact artifact) {
+    public void setArtifact(final Artifact artifact) {
         this.artifact = artifact;
 
         onArtifactChanged(artifact);
     }
 
-
-    public void onArtifactChanged(Artifact artifact) {
+    public void onArtifactChanged(final Artifact artifact) {
         artifactChanged();
 
         if (artifact.isInBackground()) {
-            LoadingPanel p = new LoadingPanel(this, artifact);
-            p.addStepBackHandler(parameterList);
+            final LoadingPanel p = new LoadingPanel(this, artifact);
+            p.addStepBackHandler(this.parameterList);
         }
     }
 
-
     /**
      * Implements the onCollectionChange() method to do update the GUI after the
      * parameterization has changed.
      *
-     * @param event The ParameterChangeEvent.
+     * @param event
+     *            The ParameterChangeEvent.
      */
     @Override
-    public void onParameterChange(ParameterChangeEvent event) {
+    public void onParameterChange(final ParameterChangeEvent event) {
         GWT.log("CollectionView.onParameterChange");
         setArtifact(event.getNewValue());
     }
 
-
     protected void artifactChanged() {
-        Collection c = getCollection();
+        final Collection c = getCollection();
 
         if (c != null) {
             loadCollection(c);
-        }
-        else {
+        } else {
             updateView();
         }
     }
@@ -395,70 +359,68 @@
     /**
      * Loads all information of a collection.
      * If 'recommendations' present, load these.
-     * @param c the Collection
+     * 
+     * @param c
+     *            the Collection
      */
-    private void loadCollection(Collection c) {
-        ArtifactDescription desc = getArtifact().getArtifactDescription();
+    private void loadCollection(final Collection c) {
+        final ArtifactDescription desc = getArtifact().getArtifactDescription();
         final Recommendation[] recom = desc.getRecommendations();
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-        describeCollectionService.describe(c.identifier(), locale,
-            new AsyncCallback<Collection>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Could not DESCRIBE collection.");
-                    SC.warn(FLYS.getExceptionString(messages, caught));
-                }
+        this.describeCollectionService.describe(c.identifier(), locale, new AsyncCallback<Collection>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Could not DESCRIBE collection.");
+                SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught));
+            }
 
-                @Override
-                public void onSuccess(Collection newCollection) {
-                    GWT.log("Successfully DESCRIBED collection.");
-                    boolean loaded = true;
-                    for (Recommendation r: recom) {
-                        if(!newCollection.loadedRecommendation(r)) {
-                            loaded = false;
-                        }
-                    }
-                    if  (!loaded) {
-                        loadRecommendedArtifacts(recom);
-                    }
-                    else {
-                        setCollection(newCollection);
+            @Override
+            public void onSuccess(final Collection newCollection) {
+                GWT.log("Successfully DESCRIBED collection.");
+                boolean loaded = true;
+                for (final Recommendation r : recom) {
+                    if (!newCollection.loadedRecommendation(r)) {
+                        loaded = false;
                     }
                 }
+                if (!loaded) {
+                    loadRecommendedArtifacts(recom);
+                } else {
+                    setCollection(newCollection);
+                }
             }
-        );
+        });
     }
 
-
     /**
      * Returns the collection of displayed by this view.
      *
      * @return the collection of this view.
      */
     public Collection getCollection() {
-        return collection;
+        return this.collection;
     }
 
-
-    protected void setCollection(Collection collection) {
+    protected void setCollection(final Collection collection) {
         setCollection(collection, false);
     }
 
-
     /**
      * Set the current collection.
      *
-     * @param collection The new collection.
-     * @param suppress Whether to fire a collectionchangeevent.
+     * @param collection
+     *            The new collection.
+     * @param suppress
+     *            Whether to fire a collectionchangeevent.
      */
-    protected void setCollection(Collection collection, boolean suppress) {
+    protected void setCollection(final Collection collection, final boolean suppress) {
         if (collection != null && this.collection == null) {
-            flys.getWorkspace().addView(collection.identifier(), this);
+            this.flys.getWorkspace().addView(collection.identifier(), this);
         }
 
-        Collection tmp  = this.collection;
+        final Collection tmp = this.collection;
         this.collection = collection;
 
         setTitle(collection.getDisplayName());
@@ -468,23 +430,22 @@
         }
     }
 
-
     @Override
-    public void onCollectionChange(CollectionChangeEvent event) {
-        if (artifactsQueue > 0) {
+    public void onCollectionChange(final CollectionChangeEvent event) {
+        if (this.artifactsQueue > 0) {
             GWT.log("Do not update UI because we are still loading Artifacts.");
             return;
         }
 
-        Collection newCol = event.getNewValue();
+        final Collection newCol = event.getNewValue();
 
-        Map<String, OutputMode> outs = newCol.getOutputModes();
+        final Map<String, OutputMode> outs = newCol.getOutputModes();
 
-        Set<String>  keys     = outs.keySet();
-        OutputMode[] prepared = new OutputMode[outs.size()];
+        final Set<String> keys = outs.keySet();
+        final OutputMode[] prepared = new OutputMode[outs.size()];
 
         int idx = 0;
-        for (String outname: keys) {
+        for (final String outname : keys) {
             prepared[idx++] = outs.get(outname);
         }
 
@@ -493,11 +454,10 @@
         updateView();
     }
 
-
     @Override
-    public void onOutputModesChange(OutputModesChangeEvent event) {
+    public void onOutputModesChange(final OutputModesChangeEvent event) {
         clearOutputTabs();
-        OutputMode[] outs = event.getOutputModes();
+        final OutputMode[] outs = event.getOutputModes();
 
         if (outs == null) {
             return;
@@ -505,11 +465,11 @@
 
         boolean hasCSV = false;
 
-        for (OutputMode out: outs) {
+        for (final OutputMode out : outs) {
             addOutputTab(out.getName(), out);
 
             if (out instanceof ExportMode) {
-                ExportMode export = (ExportMode) out;
+                final ExportMode export = (ExportMode) out;
 
                 if (export.getFacet("csv") != null) {
                     hasCSV = true;
@@ -518,25 +478,25 @@
         }
 
         if (!hasCSV) {
-            parameterList.removeTable();
+            this.parameterList.removeTable();
         }
     }
 
-
     /**
      * Adds a new tab for the OutputMode <i>out</i>.
      *
-     * @param name The name and title of the output.
+     * @param name
+     *            The name and title of the output.
      */
-    protected void addOutputTab(String name, OutputMode out) {
+    protected void addOutputTab(final String name, final OutputMode out) {
         if (out instanceof ExportMode) {
-            ExportMode export = (ExportMode) out;
+            final ExportMode export = (ExportMode) out;
 
-            if (export.getFacet("csv") != null && !parameterList.hasTable()) {
-                TableDataPanel p = new TableDataPanel();
-                p.setUuid(collection.identifier());
+            if (export.getFacet("csv") != null && !this.parameterList.hasTable()) {
+                final TableDataPanel p = new TableDataPanel();
+                p.setUuid(this.collection.identifier());
                 p.setName(out.getName());
-                parameterList.setTable(p);
+                this.parameterList.setTable(p);
             }
 
             return;
@@ -549,31 +509,29 @@
 
         GWT.log("Add new output tab for '" + name + "'");
 
-        String title  = messages.getString(name);
-        OutputTab tab = out.createOutputTab(title, getCollection(), this);
+        final String title = this.messages.getString(name);
+        final OutputTab tab = out.createOutputTab(title, getCollection(), this);
 
         if (tab != null) {
-            outputTabs.put(name, tab);
+            this.outputTabs.put(name, tab);
         }
     }
 
-
     /**
      * Removes all output mode tabs from tab bar.
      */
     protected void clearOutputTabs() {
         GWT.log("Clear OutputTabs.");
 
-        int num = tabs.getNumTabs();
+        final int num = this.tabs.getNumTabs();
 
-        for (int i = num-1; i >= 1; i--) {
-            tabs.removeTab(i);
+        for (int i = num - 1; i >= 1; i--) {
+            this.tabs.removeTab(i);
         }
 
-        outputTabs.clear();
+        this.outputTabs.clear();
     }
 
-
     /**
      * Update the view (refresh the list of old and current data).
      */
@@ -582,189 +540,158 @@
         updateOutputTabs();
     }
 
-
     /**
      * This method is used to update the tabs to show specific output modes.
      */
     protected void updateOutputTabs() {
         GWT.log("Update output tabs.");
-        if (outputTabs != null) {
-            Set<String> keys = outputTabs.keySet();
+        if (this.outputTabs != null) {
+            final Set<String> keys = this.outputTabs.keySet();
 
-            for (String key: keys) {
-                tabs.addTab(outputTabs.get(key));
+            for (final String key : keys) {
+                this.tabs.addTab(this.outputTabs.get(key));
             }
         }
     }
 
-
     @Override
-    public void onCloseClick(CloseClickEvent event) {
-        if (collection != null) {
-            if(artifact != null) {
-                flys.closeProject(collection.identifier());
+    public void onCloseClick(final CloseClickEvent event) {
+        if (this.collection != null) {
+            if (this.artifact != null) {
+                this.flys.closeProject(this.collection.identifier());
+            } else {
+                this.flys.getProjectList().deleteCollection(this.collection);
             }
-            else {
-                flys.getProjectList().deleteCollection(collection);
-            }
-        }
-        else {
+        } else {
             hide();
             destroy();
         }
     }
 
-
-    public void addArtifactToCollection(Artifact artifact) {
-        Config config               = Config.getInstance();
-        final String locale         = config.getLocale();
+    public void addArtifactToCollection(final Artifact artifact) {
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
         final Collection collection = getCollection();
 
         GWT.log("CollectionView.addArtifactToCollection " + collection);
 
         if (collection != null) {
-            addArtifactService.add(
-                collection, artifact, locale,
-                new AsyncCallback<Collection>() {
-                    @Override
-                    public void onFailure(Throwable caught) {
-                        GWT.log("An error occured while adding artifact.");
-                        SC.warn(FLYS.getExceptionString(messages, caught));
-                    }
+            this.addArtifactService.add(collection, artifact, locale, new AsyncCallback<Collection>() {
+                @Override
+                public void onFailure(final Throwable caught) {
+                    GWT.log("An error occured while adding artifact.");
+                    SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught));
+                }
 
-                    @Override
-                    public void onSuccess(Collection newCollection) {
-                        GWT.log("Successfully added artifacts.");
-                        setCollection(newCollection);
-                    }
+                @Override
+                public void onSuccess(final Collection newCollection) {
+                    GWT.log("Successfully added artifacts.");
+                    setCollection(newCollection);
                 }
-            );
-        }
-        else {
+            });
+        } else {
             // Create new collection and add artifact.
             final Artifact art = artifact;
-            createCollectionService.create(
-                locale,
-                flys.getCurrentUser().identifier(),
-                new AsyncCallback<Collection>() {
-                    @Override
-                    public void onFailure(Throwable caught) {
-                        GWT.log("Could not create the new collection.");
-                        SC.warn(FLYS.getExceptionString(messages, caught));
-                    }
+            this.createCollectionService.create(locale, this.flys.getCurrentUser().identifier(), new AsyncCallback<Collection>() {
+                @Override
+                public void onFailure(final Throwable caught) {
+                    GWT.log("Could not create the new collection.");
+                    SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught));
+                }
 
-                    @Override
-                    public void onSuccess(Collection collection) {
-                        GWT.log("Successfully created a new collection.");
-                        addArtifactService.add(
-                            collection, art, locale,
-                            new AsyncCallback<Collection>() {
-                                @Override
-                                public void onFailure(Throwable caught) {
-                                    GWT.log("An error occured while "
-                                        + "adding artifact.");
-                                    SC.warn(FLYS.getExceptionString(
-                                            messages, caught));
-                                }
+                @Override
+                public void onSuccess(final Collection collection) {
+                    GWT.log("Successfully created a new collection.");
+                    CollectionView.this.addArtifactService.add(collection, art, locale, new AsyncCallback<Collection>() {
+                        @Override
+                        public void onFailure(final Throwable caught) {
+                            GWT.log("An error occured while " + "adding artifact.");
+                            SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught));
+                        }
 
-                                @Override
-                                public void onSuccess(
-                                    Collection newCollection) {
-                                    GWT.log("Successfully added artifacts.");
-                                    setCollection(newCollection);
-                                }
-                            }
-                        );
-                    }
+                        @Override
+                        public void onSuccess(final Collection newCollection) {
+                            GWT.log("Successfully added artifacts.");
+                            setCollection(newCollection);
+                        }
+                    });
                 }
-            );
+            });
         }
     }
 
-
     protected void addRecommendationsToCollection() {
-        Config config               = Config.getInstance();
-        final String locale         = config.getLocale();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
         final Collection collection = getCollection();
 
-        collection.addRecommendations(newRecommendations);
-
-        updater.update(collection, locale,
-            new AsyncCallback<Collection>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    newRecommendations.removeAllElements();
-                    setCollection(collection);
+        collection.addRecommendations(this.newRecommendations);
 
-                    GWT.log("An error occured while saving recommendations.");
-                    SC.warn(FLYS.getExceptionString(messages, caught));
-                }
+        this.updater.update(collection, locale, new AsyncCallback<Collection>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                CollectionView.this.newRecommendations.removeAllElements();
+                setCollection(collection);
 
-                @Override
-                public void onSuccess(Collection newCol) {
-                    GWT.log("Successfully saved recommendations.");
-                    newRecommendations.removeAllElements();
-                    setCollection(newCol);
-                }
+                GWT.log("An error occured while saving recommendations.");
+                SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught));
             }
-        );
+
+            @Override
+            public void onSuccess(final Collection newCol) {
+                GWT.log("Successfully saved recommendations.");
+                CollectionView.this.newRecommendations.removeAllElements();
+                setCollection(newCol);
+            }
+        });
     }
 
-
-    protected void loadRecommendedArtifacts(Recommendation[] recommendations) {
-        Config config               = Config.getInstance();
-        final String locale         = config.getLocale();
+    protected void loadRecommendedArtifacts(final Recommendation[] recommendations) {
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
         final Collection collection = getCollection();
 
-        Artifact masterArtifact = getArtifact();
+        final Artifact masterArtifact = getArtifact();
 
         if (recommendations == null) {
             GWT.log("WARNING: Currently no recommendations.");
             return;
         }
 
-        for (final Recommendation recommendation: recommendations) {
+        for (final Recommendation recommendation : recommendations) {
             if (collection.loadedRecommendation(recommendation)) {
                 continue;
             }
-            newRecommendations.push(recommendation);
+            this.newRecommendations.push(recommendation);
 
             // XXX: UGLY! If no reference artifact given use uuid of
-            //      current artifact as reference.
+            // current artifact as reference.
             if (recommendation.getMasterArtifact() == null) {
                 recommendation.setMasterArtifact(masterArtifact.getUuid());
             }
 
         }
 
-        loadArtifactService.loadMany(
-            collection,
-            recommendations,
-            null,
-            locale,
-            new AsyncCallback<Artifact[]>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Error loading recommendations: " +
-                        caught.getMessage());
-                    SC.warn(FLYS.getExceptionString(messages, caught));
-                }
+        this.loadArtifactService.loadMany(collection, recommendations, null, locale, new AsyncCallback<Artifact[]>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Error loading recommendations: " + caught.getMessage());
+                SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught));
+            }
 
-                @Override
-                public void onSuccess(Artifact[] artifacts) {
-                    GWT.log("Loaded artifacts: " + artifacts.length);
-                    addRecommendationsToCollection();
-                }
+            @Override
+            public void onSuccess(final Artifact[] artifacts) {
+                GWT.log("Loaded artifacts: " + artifacts.length);
+                addRecommendationsToCollection();
+            }
         });
     }
 
-
-    public void registerTabHandler(TabSelectedHandler tse) {
-        tabs.addTabSelectedHandler(tse);
+    public void registerTabHandler(final TabSelectedHandler tse) {
+        this.tabs.addTabSelectedHandler(tse);
     }
 
-
-    public void setCurrentKm(double currentKm) {
+    public void setCurrentKm(final double currentKm) {
         this.currentKm = currentKm;
     }
 
@@ -772,7 +699,7 @@
         return this.currentKm;
     }
 
-    public void setMinKm(double km) {
+    public void setMinKm(final double km) {
         this.minKm = km;
     }
 
@@ -780,7 +707,7 @@
         return this.minKm;
     }
 
-    public void setMaxKm(double km) {
+    public void setMaxKm(final double km) {
         this.maxKm = km;
     }
 
@@ -788,7 +715,7 @@
         return this.maxKm;
     }
 
-    public void setSteps(double step) {
+    public void setSteps(final double step) {
         this.steps = step;
     }
 
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacagePairWidget.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacagePairWidget.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,8 +8,10 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.shared.model.ToLoad;
+
 import com.google.gwt.core.client.GWT;
-
 import com.smartgwt.client.util.SC;
 import com.smartgwt.client.widgets.Button;
 import com.smartgwt.client.widgets.events.ClickEvent;
@@ -18,98 +20,104 @@
 import com.smartgwt.client.widgets.layout.HLayout;
 import com.smartgwt.client.widgets.layout.VLayout;
 
-import org.dive4elements.river.client.client.FLYSConstants;
-import org.dive4elements.river.client.shared.model.Artifact;
-import org.dive4elements.river.client.shared.model.ToLoad;
-import org.dive4elements.river.client.shared.model.User;
-
-
 /**
  * Widget showing two Datacages and a add-this-button.
  * Insert a record into a listgrid when add-this-button clicked.
  */
-public class DatacagePairWidget
-extends      VLayout
-{
-    /** i18n resource. */
-    protected FLYSConstants MSG =
-        GWT.create(FLYSConstants.class);
-
-    /** The "remote" ListGrid to insert data to when add-button is clicked. */
-    protected ListGrid grid;
-
-    /** First (upper) DataCage Grid. */
-    protected DatacageWidget firstDatacageWidget;
-
-    /** Second (lower) DataCage Grid. */
-    protected DatacageWidget secondDatacageWidget;
-
+public class DatacagePairWidget extends VLayout {
 
     /**
-     *
-     * @param artifact Artifact to query datacage with.
-     * @param user     User to query datacage with.
-     * @param outs     outs to query datacage with.
-     * @param grid     Grid into which to insert selection of pairs.
+     * Allows for advanced controlling of the behavior of this pair widget.
      */
-    public DatacagePairWidget(Artifact artifact,
-         User user,
-         String outs,
-         ListGrid grid) {
+    public static interface IDatacagePairControler {
+        void setup(DatacageWidget leftWidget, DatacageWidget rightWidget, HLayout toolbarLayout);
+    }
+
+    /**
+     * {@link IDatacagePairControler} implementation that does nothing.
+     */
+    public static final IDatacagePairControler NIL_CONTROLER = new IDatacagePairControler() {
+        @Override
+        public void setup(final DatacageWidget leftWidget, final DatacageWidget rightWidget, final HLayout toolbarLayout) {
+            // does nothing
+        }
+    };
+
+    /** i18n resource. */
+    private static final FLYSConstants MSG = GWT.create(FLYSConstants.class);
+
+    /** The "remote" ListGrid to insert data to when add-button is clicked. */
+    private final ListGrid grid;
+
+    /** First (upper) DataCage Grid. */
+    private final DatacageWidget firstDatacageWidget;
+
+    /** Second (lower) DataCage Grid. */
+    private final DatacageWidget secondDatacageWidget;
+
+    /** Max number of recommendation pairs to be added */
+    private final int maxCount;
+
+    /** errorMsg maxCount */
+    private final String msgMaxCount;
+
+    public DatacagePairWidget(final IDatacagePairControler controler, final DatacageWidgetData leftData, final DatacageWidgetData rightData,
+            final ListGrid grid, final int maxCount, final String msgMaxCount) {
+
+        this.msgMaxCount = msgMaxCount;
+        this.maxCount = maxCount;
         this.grid = grid;
 
-        HLayout hLayout      = new HLayout();
-        firstDatacageWidget  = new DatacageWidget(
-            artifact,
-            user,
-            outs,
-            "load-system:true",
-            false);
-        secondDatacageWidget = new DatacageWidget(
-            artifact,
-            user,
-            outs,
-            "load-system:true",
-            false);
-        firstDatacageWidget.setIsMutliSelectable(false);
-        secondDatacageWidget.setIsMutliSelectable(false);
+        final HLayout hLayout = new HLayout();
 
-        hLayout.addMember(firstDatacageWidget);
-        hLayout.addMember(secondDatacageWidget);
+        this.firstDatacageWidget = new DatacageWidget(leftData);
+        this.secondDatacageWidget = new DatacageWidget(rightData);
 
-        // TODO: icon
-        Button plusBtn = new Button(MSG.datacage_add_pair());
+        this.firstDatacageWidget.setIsMutliSelectable(false);
+        this.secondDatacageWidget.setIsMutliSelectable(false);
+
+        hLayout.addMember(this.firstDatacageWidget);
+        hLayout.addMember(this.secondDatacageWidget);
+
+        final HLayout toolbarLayout = new HLayout();
+        toolbarLayout.setAutoHeight();
+
+        final Button plusBtn = new Button(MSG.datacage_add_pair());
         plusBtn.setAutoFit(true);
         plusBtn.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(ClickEvent event) {
+            public void onClick(final ClickEvent event) {
                 plusClicked();
             }
         });
+        toolbarLayout.addMember(plusBtn);
 
         addMember(hLayout);
-        addMember(plusBtn);
+        addMember(toolbarLayout);
+
+        controler.setup(this.firstDatacageWidget, this.secondDatacageWidget, toolbarLayout);
     }
 
-
     /**
      * Callback for add-button.
      * Fires to load for every selected element and handler.
      */
-    public void plusClicked() {
-        ToLoad toLoad1 = firstDatacageWidget.getSelection();
-        ToLoad toLoad2 = secondDatacageWidget.getSelection();
+    protected final void plusClicked() {
+        final ToLoad toLoad1 = this.firstDatacageWidget.getSelection();
+        final ToLoad toLoad2 = this.secondDatacageWidget.getSelection();
 
-        if (toLoad1 == null || toLoad2 == null ||
-            toLoad1.toRecommendations().isEmpty() ||
-            toLoad2.toRecommendations().isEmpty()) {
+        // FIXME: allows to select folders... but it should not
+
+        if (toLoad1 == null || toLoad2 == null || toLoad1.toRecommendations().isEmpty() || toLoad2.toRecommendations().isEmpty()) {
             SC.say(MSG.warning_select_two_values());
             return;
         }
 
-        grid.addData(new RecommendationPairRecord(
-            toLoad1.toRecommendations().get(0),
-            toLoad2.toRecommendations().get(0)));
+        if (this.grid.getTotalRows() >= this.maxCount) {
+            SC.say(this.msgMaxCount);
+            return;
+        }
+
+        this.grid.addData(new RecommendationPairRecord(toLoad1.toRecommendations().get(0), toLoad2.toRecommendations().get(0)));
     }
-}
-// 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/ui/DatacagePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacagePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,18 +8,18 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.ToLoad;
+import org.dive4elements.river.client.shared.model.User;
+
 import com.smartgwt.client.widgets.Canvas;
 import com.smartgwt.client.widgets.Label;
 import com.smartgwt.client.widgets.layout.VLayout;
 
-import org.dive4elements.river.client.shared.model.Data;
-import org.dive4elements.river.client.shared.model.DataList;
-import org.dive4elements.river.client.shared.model.User;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
@@ -27,34 +27,35 @@
 
     private static final long serialVersionUID = 6937994648371673222L;
 
-    protected String dataName;
-
-    protected User user;
+    private String dataName;
 
-    protected DatacageWidget widget;
+    private final User user;
 
+    private DatacageWidget widget;
 
-    public DatacagePanel() {
-        super();
+    private final String outs;
+
+    private final String parameters;
+
+    private final boolean multiSelectable;
+
+    public DatacagePanel(final User user, final String outs, final String parameters, final boolean multiSelectable) {
+        this.user = user;
+        this.outs = outs;
+        this.parameters = parameters;
+        this.multiSelectable = multiSelectable;
     }
 
-
-    public DatacagePanel(User user) {
-        super();
-        this.user = user;
-    }
-
-
     @Override
-    public Canvas create(DataList dataList) {
-        Data   data   = dataList.get(0);
+    public Canvas create(final DataList dataList) {
+        final Data data = dataList.get(0);
         this.dataName = data.getLabel();
 
         createWidget();
 
-        Canvas label   = new Label(data.getDescription());
-        Canvas submit  = getNextButton();
-        VLayout layout = new VLayout();
+        final Canvas label = new Label(data.getDescription());
+        final Canvas submit = getNextButton();
+        final VLayout layout = new VLayout();
         label.setHeight(25);
 
         layout.addMember(label);
@@ -64,39 +65,36 @@
         return layout;
     }
 
+    private void createWidget() {
 
-    protected void createWidget() {
-        widget = new DatacageWidget(
-            artifact,
-            getUser(),
-            getOuts(),
-            getParameters(),
-            false);
+        final DatacageWidgetData data = new DatacageWidgetData(this.artifact, this.user, this.outs, this.parameters, false);
 
-        widget.setHeight100();
+        this.widget = new DatacageWidget(data);
 
-        helperContainer.addMember(widget);
+        this.widget.setHeight100();
+
+        this.helperContainer.addMember(this.widget);
+
+        this.widget.setIsMutliSelectable(this.multiSelectable);
     }
 
-
     @Override
     public List<String> validate() {
         return new ArrayList<String>();
     }
 
-
-    public User getUser() {
-        return user;
+    /**
+     * Unclear if this may implement super.getDataName...
+     */
+    protected final String getMyDataName() {
+        return this.dataName;
     }
 
-
-    public String getOuts() {
-        return null;
+    protected final ToLoad getSelection() {
+        return this.widget.getSelection();
     }
 
-
-    public String getParameters() {
-        return null;
+    protected final String[] getSelectionTitles() {
+        return this.widget.getSelectionTitles();
     }
-}
-// 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/ui/DatacageTwinPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageTwinPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,531 +8,81 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import org.dive4elements.river.client.client.ui.DatacagePairWidget.IDatacagePairControler;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.User;
+
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import com.smartgwt.client.data.Record;
-import com.smartgwt.client.types.ListGridFieldType;
 import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.Label;
 import com.smartgwt.client.widgets.grid.ListGrid;
-import com.smartgwt.client.widgets.grid.ListGridField;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
-import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
 import com.smartgwt.client.widgets.layout.HLayout;
 import com.smartgwt.client.widgets.layout.VLayout;
 
-import org.dive4elements.river.client.client.Config;
-import org.dive4elements.river.client.client.FLYSConstants;
-import org.dive4elements.river.client.client.event.StepForwardEvent;
-import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
-import org.dive4elements.river.client.client.services.RemoveArtifactServiceAsync;
-import org.dive4elements.river.client.shared.model.Artifact;
-import org.dive4elements.river.client.shared.model.Collection;
-import org.dive4elements.river.client.shared.model.Data;
-import org.dive4elements.river.client.shared.model.DataItem;
-import org.dive4elements.river.client.shared.model.DataList;
-import org.dive4elements.river.client.shared.model.DefaultData;
-import org.dive4elements.river.client.shared.model.DefaultDataItem;
-import org.dive4elements.river.client.shared.model.Recommendation;
-import org.dive4elements.river.client.shared.model.Recommendation.Facet;
-import org.dive4elements.river.client.shared.model.Recommendation.Filter;
-import org.dive4elements.river.client.shared.model.User;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-// TODO Probably better to branch off AbstractUIProvider.
-// TODO Merge with other datacage-widget impls.
 /**
- * Panel containing a Grid and a "next" button. The Grid is fed by a
+ * A {@link AbstractPairRecommendationPanel} that uses a 'TwinDatacage' in the help-input area.
  * DatacagePairWidget which is put in the input-helper area.
  */
-public class DatacageTwinPanel
-extends      TextProvider {
-
-    private static final long serialVersionUID = 8906629596491827857L;
-
-    protected static FLYSConstants MSG = GWT.create(FLYSConstants.class);
-
-    protected String dataName;
-
-    protected User user;
-
-    /** ListGrid that displays user-selected pairs to build differences with. */
-    protected ListGrid differencesList;
+public abstract class DatacageTwinPanel extends AbstractPairRecommendationPanel {
 
-    /**
-     * List to track previously selected but now removed pairs. (Needed to
-     * be able to identify artifacts that can be removed from the collection.
-     */
-    protected List<RecommendationPairRecord> removedPairs =
-        new ArrayList<RecommendationPairRecord>();
+    private static final long serialVersionUID = 1L;
 
-    /** Service handle to clone and add artifacts to collection. */
-    LoadArtifactServiceAsync loadArtifactService = GWT.create(
-        org.dive4elements.river.client.client.services
-        .LoadArtifactService.class);
+    private final IDatacageTwinPanelInfo leftInfo;
+    private final IDatacageTwinPanelInfo rightInfo;
 
-    /** Service to remove artifacts from collection. */
-    RemoveArtifactServiceAsync removeArtifactService = GWT.create(
-        org.dive4elements.river.client.client.services
-        .RemoveArtifactService.class);
+    private final int maxCount;
+    private final String msgMaxCount;
 
+    private final IDatacagePairControler controler;
 
-    public DatacageTwinPanel(User user) {
-        super();
-        this.user = user;
+    public static interface IDatacageTwinPanelInfo extends IRecommendationInfo {
+        String getOuts();
+
+        String getColumnLabel();
     }
 
+    public DatacageTwinPanel(final User user, final IValidator validator, final IDatacagePairControler controler, final IDatacageTwinPanelInfo leftInfo,
+            final IDatacageTwinPanelInfo rightInfo,
+            final int maxCount, final String msgMaxCount) {
+        super(user, validator, leftInfo, rightInfo);
 
-    /**
-     * Remove first occurrence of "[" and "]" (if both do occur).
-     * @param value String to be stripped of [] (might be null).
-     * @return input string but with [ and ] removed, or input string if no
-     *         brackets were found.
-     * @see StringUtil.unbracket
-     */
-    public static final String unbracket(String value) {
-        // null- guard.
-        if (value == null) return value;
-
-        int start = value.indexOf("[");
-        int end   = value.indexOf("]");
-
-        if (start < 0 || end < 0) {
-            return value;
-        }
-
-        value = value.substring(start + 1, end);
-
-        return value;
+        this.controler = controler;
+        this.maxCount = maxCount;
+        this.msgMaxCount = msgMaxCount;
+        this.leftInfo = leftInfo;
+        this.rightInfo = rightInfo;
     }
 
-
-    /**
-     * Create a recommendation from a string representation of it.
-     * @param from string in format as shown above.
-     * @return recommendation from input string.
-     */
-    public Recommendation createRecommendationFromString(
-        String from,
-        String factory
-    ) {
-        // TODO Construct "real" filter.
-        String[] parts = unbracket(from).split(";");
-        Recommendation.Filter filter = new Recommendation.Filter();
-        Recommendation.Facet  facet  = new Recommendation.Facet(
-                parts[1],
-                parts[2]);
-
-        List<Recommendation.Facet> facets = new ArrayList<Recommendation.Facet>
-            ();
-        facets.add(facet);
-        filter.add("longitudinal_section", facets);
-        Recommendation r = new Recommendation(factory, parts[0],
-            this.artifact.getUuid(), filter);
-        r.setDisplayName(parts[3]);
-        return r;
-    }
-
-
-    /**
-     * Add RecomendationPairRecords from input String to the ListGrid.
-     */
-    public void populateGridFromString(String from, String factory){
-        // Split this string.
-        // Create according recommendations and display strings.
-        String[] recs = from.split("#");
-        if (recs.length % 2 != 0) return;
-        for (int i = 0; i < recs.length; i+=2) {
-            Recommendation minuend =
-                createRecommendationFromString(recs[i+0], factory);
-            Recommendation subtrahend =
-                createRecommendationFromString(recs[i+1], factory);
-
-            RecommendationPairRecord pr = new RecommendationPairRecord(
-                minuend, subtrahend);
-            // This Recommendation Pair comes from the data string and was thus
-            // already cloned.
-            pr.setIsAlreadyLoaded(true);
-            this.differencesList.addData(pr);
-        }
-    }
-
-
-    /**
-     * Creates the graphical representation and interaction widgets
-     * for the data.
-     * @param dataList the data.
-     * @return graphical representation and interaction widgets for data.
-     */
     @Override
-    public Canvas create(DataList dataList) {
+    protected final Canvas createChooserWidgets(final Canvas widget, final DataList dataList, final User user, final ListGrid differencesList) {
         GWT.log("createData()");
 
-        Canvas widget = createWidget();
-        Canvas submit = getNextButton();
+        final Canvas submit = getNextButton();
 
-        VLayout layout       = new VLayout();
-        HLayout helperLayout = new HLayout();
-        helperLayout.addMember(new DatacagePairWidget(this.artifact,
-            user, "winfo_diff_twin_panel", differencesList));
+        final VLayout layout = new VLayout();
+        final HLayout helperLayout = new HLayout();
+
+        final String leftOuts = this.leftInfo.getOuts();
+        final String leftLabel = this.leftInfo.getColumnLabel();
+        final DatacageWidgetData leftData = new DatacageWidgetData(this.artifact, user, leftOuts, "load-system:true", false, leftLabel);
+
+        final String rightOuts = this.rightInfo.getOuts();
+        final String rightLabel = this.rightInfo.getColumnLabel();
+        final DatacageWidgetData rightData = new DatacageWidgetData(this.artifact, user, rightOuts, "load-system:true", false, rightLabel);
+
+        helperLayout.addMember(new DatacagePairWidget(this.controler, leftData, rightData, differencesList, this.maxCount, this.msgMaxCount));
+
+        if (dataList != null && dataList.get(0) != null && dataList.get(0).getDescription() != null) {
+            final Label title = new Label(dataList.get(0).getDescription());
+            title.setHeight("25px");
+            layout.addMember(title);
+        }
 
         layout.addMember(widget);
         layout.addMember(submit);
         layout.setMembersMargin(10);
         this.helperContainer.addMember(helperLayout);
 
-        populateGrid(dataList, "waterlevel");
-        return layout;
-    }
-
-    protected void populateGrid(DataList dataList, String factory) {
-        Data data     = dataList.get(0);
-        this.dataName = data.getLabel();
-        for (int i = 0; i < dataList.size(); i++) {
-            if (dataList.get(i) != null
-                && dataList.get(i).getItems() != null
-            ) {
-                if (dataList.get(i).getItems() != null) {
-                    populateGridFromString(
-                        dataList.get(i).getItems()[0].getStringValue(),
-                        factory);
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Validates the selection.
-     * @return List of internationalized errror messages (if any).
-     */
-    @Override
-    public List<String> validate() {
-        List<String> errors = new ArrayList<String>();
-        if (differencesList.getRecords().length == 0) {
-            errors.add(MSG.error_no_waterlevel_pair_selected());
-        }
-        // Check whether minuend and subtrahend are equal.
-        for (ListGridRecord record: differencesList.getRecords()) {
-            RecommendationPairRecord r = (RecommendationPairRecord) record;
-            if (r.getFirst().equals(r.getSecond())) {
-                errors.add(MSG.error_same_waterlevels_in_pair());
-            }
-        }
-
-        return errors;
-    }
-
-
-    /**
-     * Creates layout with grid that displays selection inside.
-     */
-    public Canvas createWidget() {
-        VLayout layout  = new VLayout();
-        differencesList = new ListGrid();
-
-        differencesList.setCanEdit(false);
-        differencesList.setCanSort(false);
-        differencesList.setShowHeaderContextMenu(false);
-        differencesList.setHeight(150);
-        differencesList.setShowAllRecords(true);
-
-        ListGridField nameField    = new ListGridField("first",  "Minuend");
-        ListGridField capitalField = new ListGridField("second", "Subtrahend");
-        // Track removed rows, therefore more or less reimplement
-        // setCanRecomeRecords.
-        final ListGridField removeField  =
-            new ListGridField("_removeRecord", "Remove Record"){{
-                setType(ListGridFieldType.ICON);
-                setIcon(GWT.getHostPageBaseURL() + MSG.removeFeature());
-                setCanEdit(false);
-                setCanFilter(false);
-                setCanSort(false);
-                setCanGroupBy(false);
-                setCanFreeze(false);
-                setWidth(25);
-        }};
-
-        differencesList.setFields(new ListGridField[] {nameField,
-           capitalField, removeField});
-
-        differencesList.addRecordClickHandler(new RecordClickHandler() {
-                @Override
-                public void onRecordClick(final RecordClickEvent event) {
-                    // Just handle remove-clicks
-                    if(!event.getField().getName()
-                        .equals(removeField.getName())
-                    ) {
-                        return;
-                    }
-                    trackRemoved(event.getRecord());
-                    event.getViewer().removeData(event.getRecord());
-                }
-            });
-        layout.addMember(differencesList);
-
         return layout;
     }
-
-
-    /**
-     * Add record to list of removed records.
-     */
-    public void trackRemoved(Record r) {
-        RecommendationPairRecord pr = (RecommendationPairRecord) r;
-        this.removedPairs.add(pr);
-    }
-
-    /**
-     * Set factory of recommendation such that the correct artifacts will
-     * be cloned for difference calculations.
-     */
-    public void adjustRecommendation(Recommendation recommendation) {
-        // XXX: THIS IS AN EVIL HACK TO MAKE W-DIFFERENCES WORK AGAIN!
-        // TODO: Throw all this code away and do it with server side
-        // recommendations!
-        recommendation.setTargetOut("w_differences");
-
-        if (recommendation.getIDs() != null) {
-            GWT.log("Setting staticwkms factory for rec with ID "
-                + recommendation.getIDs());
-            recommendation.setFactory("staticwkms");
-        }
-        /*
-        // So far, we do not need to rewrite the factory anymore,
-        // except for staticwkms; probably other cases will pop up later.
-        else if (recommendation.getFactory().equals("winfo")) {
-            GWT.log("Setting waterlevel factory for a winfo rec.");
-            recommendation.setFactory("waterlevel");
-        }
-        */
-        else {
-           GWT.log("Leave rec. id " + recommendation.getIDs() + ", factory "
-               + recommendation.getFactory() + " untouched.");
-        }
-    }
-
-    /**
-     * Validates data, does nothing if invalid, otherwise clones new selected
-     * waterlevels and add them to collection, forward the artifact.
-     */
-    @Override
-    public void onClick(ClickEvent e) {
-        GWT.log("DatacageTwinPanel.onClick");
-
-        List<String> errors = validate();
-        if (errors != null && !errors.isEmpty()) {
-            showErrors(errors);
-            return;
-        }
-
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
-
-        ListGridRecord[] records = differencesList.getRecords();
-
-        List<Recommendation> ar  = new ArrayList<Recommendation>();
-        List<Recommendation> all = new ArrayList<Recommendation>();
-
-        for (ListGridRecord record : records) {
-            RecommendationPairRecord r =
-                (RecommendationPairRecord) record;
-            // Do not add "old" recommendations.
-            if (!r.isAlreadyLoaded()) {
-                // Check whether one of those is a dike or similar.
-                // TODO differentiate and merge: new clones, new, old.
-                Recommendation firstR = r.getFirst();
-                adjustRecommendation(firstR);
-
-                Recommendation secondR = r.getSecond();
-                adjustRecommendation(secondR);
-                ar.add(firstR);
-                ar.add(secondR);
-            }
-            else {
-                all.add(r.getFirst());
-                all.add(r.getSecond());
-            }
-        }
-
-        final Recommendation[] toClone = ar.toArray(
-            new Recommendation[ar.size()]);
-        final Recommendation[] toUse   = all.toArray(
-            new Recommendation[all.size()]);
-
-        // Find out whether "old" artifacts have to be removed.
-        List<String> artifactIdsToRemove = new ArrayList<String>();
-        for (RecommendationPairRecord rp: this.removedPairs) {
-            Recommendation first  = rp.getFirst();
-            Recommendation second = rp.getSecond();
-
-            for (Recommendation recommendation: toUse) {
-                if (first != null
-                    && first.getIDs().equals(recommendation.getIDs())
-                ) {
-                    first = null;
-                }
-                if (second != null
-                    && second.getIDs().equals(recommendation.getIDs())
-                ) {
-                    second = null;
-                }
-
-                if (first == null && second == null) {
-                    break;
-                }
-            }
-            if (first != null) {
-                artifactIdsToRemove.add(first.getIDs());
-            }
-            if (second != null) {
-                artifactIdsToRemove.add(second.getIDs());
-            }
-        }
-
-        // Remove old artifacts, if any. Do this asychronously without much
-        // feedback.
-        for(final String uuid: artifactIdsToRemove) {
-            removeArtifactService.remove(this.collection,
-                uuid,
-                locale,
-                new AsyncCallback<Collection>() {
-                    @Override
-                    public void onFailure(Throwable caught) {
-                        GWT.log("RemoveArtifact (" + uuid + ") failed.");
-                    }
-                    @Override
-                    public void onSuccess(Collection collection) {
-                        GWT.log("RemoveArtifact succeeded");
-                    }
-                });
-        }
-
-        // Clone new ones (and spawn statics), go forward.
-        parameterList.lockUI();
-        loadArtifactService.loadMany(
-            this.collection,
-            toClone,
-            //"staticwkms" and "waterlevel"
-            null,
-            locale,
-            new AsyncCallback<Artifact[]>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Failure of cloning with factories!");
-                    parameterList.unlockUI();
-                }
-                @Override
-                public void onSuccess(Artifact[] artifacts) {
-                    GWT.log("Successfully cloned " + toClone.length +
-                        " with factories.");
-
-                    fireStepForwardEvent(new StepForwardEvent(
-                        getData(toClone, artifacts, toUse)));
-                    parameterList.unlockUI();
-                }
-            });
-    }
-
-
-    /**
-     * Create Data and DataItem from selection (a long string with identifiers
-     * to construct diff-pairs).
-     *
-     * @param newRecommendations "new" recommendations (did not survive a
-     *        backjump).
-     * @param newArtifacts artifacts cloned from newRecommendations.
-     * @param oldRecommendations old recommendations that survived a backjump.
-     *
-     * @return dataitem with a long string with identifiers to construct
-     *         diff-pairs.
-     */
-    protected Data[] getData(
-            Recommendation[] newRecommendations,
-            Artifact[] newArtifacts,
-            Recommendation[] oldRecommendations)
-    {
-        // Construct string with info about selections.
-        String dataItemString = "";
-        for (int i = 0; i < newRecommendations.length; i++) {
-            Recommendation r = newRecommendations[i];
-            Artifact newArtifact = newArtifacts[i];
-            String uuid = newArtifact.getUuid();
-            r.setMasterArtifact(uuid);
-            if (i>0) dataItemString += "#";
-
-            dataItemString += createDataString(uuid, r);
-        }
-
-        for (int i = 0; i < oldRecommendations.length; i++) {
-            Recommendation r = oldRecommendations[i];
-            String uuid = r.getIDs();
-            if (dataItemString.length() > 0) dataItemString += "#";
-
-            dataItemString += createDataString(uuid, r);
-        }
-
-        // TODO some hassle could be resolved by using multiple DataItems
-        // (e.g. one per pair).
-        DataItem item = new DefaultDataItem(dataName, dataName, dataItemString);
-        return new Data[] { new DefaultData(
-            dataName, null, null, new DataItem[] {item}) };
-    }
-
-
-    protected String createDataString(
-        String artifact,
-        Recommendation recommendation
-    ) {
-        return createDataString(artifact, recommendation, "staticwkms");
-    }
-
-    /**
-     * Creates part of the String that encodes minuend or subtrahend.
-     * @param artifact Artifacts UUID.
-     * @param recommendation Recommendation to wrap in string.
-     * @param factory The factory to encode.
-     */
-    protected String createDataString(
-        String artifact,
-        Recommendation recommendation,
-        String factory)
-    {
-        Filter filter = recommendation.getFilter();
-        Facet  f      = null;
-
-        if(filter != null) {
-            Map<String, List<Facet>>               outs = filter.getOuts();
-            Set<Map.Entry<String, List<Facet>>> entries = outs.entrySet();
-
-            for (Map.Entry<String, List<Facet>> entry: entries) {
-                List<Facet> fs = entry.getValue();
-
-                f = fs.get(0);
-                if (f != null) {
-                    break;
-                }
-            }
-
-            return "[" + artifact + ";"
-                + f.getName()
-                + ";"
-                + f.getIndex()
-                + ";"
-                + recommendation.getDisplayName() + "]";
-        }
-        else {
-            return "["
-                + artifact
-                + ";" + factory + ";0;"
-                + recommendation.getDisplayName() + "]";
-        }
-    }
-}
-// 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/ui/DatacageWidget.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageWidget.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,468 +8,421 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import com.smartgwt.client.types.SelectionStyle;
-import com.smartgwt.client.types.TreeModelType;
-
-import com.smartgwt.client.util.SC;
-
-import com.smartgwt.client.widgets.Button;
-
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-
-import com.smartgwt.client.widgets.grid.HoverCustomizer;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-
-import com.smartgwt.client.widgets.grid.events.RecordDoubleClickEvent;
-import com.smartgwt.client.widgets.grid.events.RecordDoubleClickHandler;
-
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import com.smartgwt.client.widgets.tree.Tree;
-import com.smartgwt.client.widgets.tree.TreeGrid;
-import com.smartgwt.client.widgets.tree.TreeNode;
-
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.MissingResourceException;
 import java.util.Stack;
 
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYSConstants;
-
 import org.dive4elements.river.client.client.event.DatacageDoubleClickHandler;
 import org.dive4elements.river.client.client.event.DatacageHandler;
-
 import org.dive4elements.river.client.client.services.MetaDataService;
 import org.dive4elements.river.client.client.services.MetaDataServiceAsync;
-
-import org.dive4elements.river.client.shared.model.Artifact;
 import org.dive4elements.river.client.shared.model.AttrList;
 import org.dive4elements.river.client.shared.model.DataCageNode;
 import org.dive4elements.river.client.shared.model.DataCageTree;
 import org.dive4elements.river.client.shared.model.ToLoad;
 import org.dive4elements.river.client.shared.model.User;
 
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.SelectionStyle;
+import com.smartgwt.client.types.TreeModelType;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.grid.HoverCustomizer;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordDoubleClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordDoubleClickHandler;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tree.Tree;
+import com.smartgwt.client.widgets.tree.TreeGrid;
+import com.smartgwt.client.widgets.tree.TreeNode;
+
 // TODO: refactor, extract ~DataCageGrid
 /**
  * Display tree of, for example, previous calculations and allows
  * selection in order to access/clone these.
  */
-public class DatacageWidget
-extends      VLayout
-{
+public final class DatacageWidget extends VLayout {
+
+    private static final FLYSConstants MSG = GWT.create(FLYSConstants.class);
+
     public static final int MAX_OPEN = 30;
 
-    protected MetaDataServiceAsync metaDataService =
-        GWT.create(MetaDataService.class);
-
-    protected FLYSConstants messages =
-        GWT.create(FLYSConstants.class);
-
-    protected Artifact artifact;
-    protected User     user;
-    protected String   outs;
-    protected String   parameters;
-
-    protected TreeGrid treeGrid;
-    protected Tree     tree;
-
-    protected ToLoad   toLoad;
-
-    protected List<DatacageHandler>            handlers;
-    protected List<DatacageDoubleClickHandler> doubleHandlers;
-
-    /** Layout to show spinning wheel of joy. */
-    protected VLayout lockScreen;
-
-
-    public DatacageWidget() {
-        handlers       = new ArrayList<DatacageHandler>();
-        doubleHandlers = new ArrayList<DatacageDoubleClickHandler>();
+    public interface DatacageFilter {
+        boolean accept(DataCageNode node);
     }
 
-
-    public DatacageWidget(Artifact artifact, User user) {
-        this(artifact, user, null);
-    }
-
-    public DatacageWidget(Artifact artifact, User user, String outs) {
-        this(artifact, user, outs, true);
-    }
+    public static final DatacageFilter ACCEPT_ALL_FILTER = new DatacageFilter() {
+        @Override
+        public boolean accept(final DataCageNode node) {
+            return true;
+        }
+    };
 
-    public DatacageWidget(
-        Artifact   artifact,
-        User       user,
-        String     outs,
-        boolean    showButton
-    ) {
-        this(artifact, user, outs, null, showButton);
-    }
-
+    public static final DatacageFilter ACCEPT_NONE_FILTER = new DatacageFilter() {
+        @Override
+        public boolean accept(final DataCageNode node) {
+            return false;
+        }
+    };
 
-    public DatacageWidget(
-        Artifact   artifact,
-        User       user,
-        String     outs,
-        String     parameters,
-        boolean    showButton
-    ) {
-        this();
+    private final MetaDataServiceAsync metaDataService = GWT.create(MetaDataService.class);
 
-        this.artifact   = artifact;
-        this.user       = user;
-        this.outs       = outs;
-        this.parameters = parameters;
+    private final List<DatacageHandler> handlers = new ArrayList<DatacageHandler>();
 
-        toLoad = new ToLoad();
+    private final List<DatacageDoubleClickHandler> doubleHandlers = new ArrayList<DatacageDoubleClickHandler>();
+
+    private final TreeGrid treeGrid;
+
+    private Tree tree;
+
+    private ToLoad toLoad;
+
+    /** Layout to show spinning wheel of joy. */
+    private VLayout lockScreen;
+
+    private DataCageTree dcTree;
+
+    private DatacageFilter filter = ACCEPT_ALL_FILTER;
+
+    private DatacageWidgetData data;
+
+    public DatacageWidget(final DatacageWidgetData data) {
+
+        this.data = data;
+
+        this.toLoad = new ToLoad();
 
         setWidth100();
 
-        tree = new Tree();
-        tree.setModelType(TreeModelType.CHILDREN);
-        tree.setNameProperty("name");
-        tree.setIdField("id");
-        tree.setChildrenProperty("children-nodes");
-        tree.setShowRoot(false);
+        this.treeGrid = new TreeGrid();
 
-        treeGrid = new TreeGrid();
-        treeGrid.setLoadDataOnDemand(false);
-        treeGrid.setWidth100();
-        treeGrid.setHeight100();
-        treeGrid.setShowRoot(false);
-        treeGrid.setNodeIcon("[SKIN]/../blank.gif");
-        treeGrid.setShowConnectors(true);
-        treeGrid.setLoadingMessage(messages.databasket_loading());
-        treeGrid.setEmptyMessage(messages.databasket_loading());
-        treeGrid.setLoadingDataMessage(messages.databasket_loading());
+        final String columnLabel = this.data.getColumnLabel();
+        if (columnLabel != null)
+            this.treeGrid.setTreeFieldTitle(columnLabel);
 
-        treeGrid.setHoverMoveWithMouse(true);
-        treeGrid.setCanHover(true);
-        treeGrid.setShowHover(true);
-        treeGrid.setHoverOpacity(75);
-        treeGrid.setHoverWidth(120);
+        this.treeGrid.setLoadDataOnDemand(false);
+        this.treeGrid.setWidth100();
+        this.treeGrid.setHeight100();
+        this.treeGrid.setShowRoot(false);
+        this.treeGrid.setNodeIcon("[SKIN]/../blank.gif");
+        this.treeGrid.setShowConnectors(true);
+        this.treeGrid.setLoadingMessage(MSG.databasket_loading());
+        this.treeGrid.setLoadingDataMessage(MSG.databasket_loading());
+        this.treeGrid.setEmptyMessage(MSG.databasket_empty());
 
-        treeGrid.setHoverCustomizer(new HoverCustomizer() {
+        this.treeGrid.setHoverMoveWithMouse(true);
+        this.treeGrid.setCanHover(true);
+        this.treeGrid.setShowHover(true);
+        this.treeGrid.setHoverOpacity(75);
+        this.treeGrid.setHoverWidth(120);
+
+        this.treeGrid.setHoverCustomizer(new HoverCustomizer() {
             @Override
-            public String hoverHTML(Object value,
-                ListGridRecord record,
-                int rowNum,
-                int colNum
-                ) {
-                if(record instanceof TreeNode) {
-                    TreeNode hoveredTreeNode = (TreeNode)record;
+            public String hoverHTML(final Object value, final ListGridRecord record, final int rowNum, final int colNum) {
+                if (record instanceof TreeNode) {
+                    final TreeNode hoveredTreeNode = (TreeNode) record;
                     String info = hoveredTreeNode.getAttribute("info");
                     if (info == null) {
                         info = hoveredTreeNode.getName();
                     }
                     return info;
                 }
-                else {
-                    return "";// should not happen
-                }
+
+                return "";// should not happen
             }
         });
 
-        treeGrid.addRecordDoubleClickHandler(new RecordDoubleClickHandler() {
+        this.treeGrid.addRecordDoubleClickHandler(new RecordDoubleClickHandler() {
             @Override
-            public void onRecordDoubleClick(RecordDoubleClickEvent event) {
+            public void onRecordDoubleClick(final RecordDoubleClickEvent event) {
                 doubleClickedOnTree(event);
             }
         });
 
-        addMember(treeGrid);
+        addMember(this.treeGrid);
 
-        if (showButton) {
+        if (data.isShowButton())
             addMember(createPlusButton());
-        }
 
         triggerTreeBuilding();
     }
 
+    public void setFilter(final DatacageFilter filter) {
+        assert (filter != null);
+
+        this.filter = filter;
+
+        if (this.dcTree != null)
+            updateTree(this.dcTree);
+    }
+
+    public TreeGrid getTreeGrid() {
+        return this.treeGrid;
+    }
+
     /** Disable input, show spinning wheel of joy. */
-    public void lockUI() {
-        lockScreen = ScreenLock.lockUI(this, lockScreen);
+    private void lockUI() {
+        this.lockScreen = ScreenLock.lockUI(this, this.lockScreen);
     }
 
     /** Enable input, remove grey, remove spinning wheel of joy. */
-    public void unlockUI() {
-        ScreenLock.unlockUI(this, lockScreen);
+    protected final void unlockUI() {
+        ScreenLock.unlockUI(this, this.lockScreen);
     }
 
     /**
-     * @param handler Handler to be added (notified on add-action).
+     * Sets whether more than one item can be selected.
+     *
+     * @param multi
+     *            if true, allow mutliple selections.
      */
-    public DatacageWidget(Artifact artifact, User user, String outs,
-        DatacageHandler handler) {
-        this(artifact, user, outs);
-        this.addDatacageHandler(handler);
-    }
-
-
-    public DatacageWidget(
-        Artifact        artifact,
-        User            user,
-        String          outs,
-        DatacageHandler handler,
-        String          parameters
-    ) {
-        this(artifact, user, outs, handler);
-        this.parameters = parameters;
-    }
-
-
-    /**
-     * Sets whether more than one item can be selected.
-     * @param multi if true, allow mutliple selections.
-     */
-    public void setIsMutliSelectable(boolean multi) {
+    public void setIsMutliSelectable(final boolean multi) {
         if (multi) {
-            treeGrid.setSelectionType(SelectionStyle.MULTIPLE);
-        }
-        else {
-            treeGrid.setSelectionType(SelectionStyle.SINGLE);
+            this.treeGrid.setSelectionType(SelectionStyle.MULTIPLE);
+        } else {
+            this.treeGrid.setSelectionType(SelectionStyle.SINGLE);
         }
     }
 
-
     /**
-     * @param handler Handler to be added (notified on add-action).
+     * @param handler
+     *            Handler to be added (notified on add-action).
      */
-    public void addDatacageHandler(DatacageHandler handler) {
-        if (!handlers.contains(handler)) {
-            handlers.add(handler);
-        }
-    }
-
-
-    /**
-     * @param h Handler to be added (notified on Double click on node).
-     */
-    public void addDatacageDoubleClickHandler(DatacageDoubleClickHandler h) {
-        if (!doubleHandlers.contains(h)) {
-            doubleHandlers.add(h);
+    public void addDatacageHandler(final DatacageHandler handler) {
+        if (!this.handlers.contains(handler)) {
+            this.handlers.add(handler);
         }
     }
 
+    /**
+     * @param h
+     *            Handler to be added (notified on Double click on node).
+     */
+    public void addDatacageDoubleClickHandler(final DatacageDoubleClickHandler h) {
+        if (!this.doubleHandlers.contains(h)) {
+            this.doubleHandlers.add(h);
+        }
+    }
 
     /**
-     * @param handler Handler to remove from list.
+     * @param handler
+     *            Handler to remove from list.
      */
-    public void removeDatacageHandler(DatacageHandler handler) {
-        handlers.remove(handler);
+    public void removeDatacageHandler(final DatacageHandler handler) {
+        this.handlers.remove(handler);
     }
 
-
-    public ToLoad getToLoad() {
-        return toLoad;
-    }
-
-
     public ToLoad getSelection() {
         // Reset content of toLoads.
-        toLoad = new ToLoad();
 
-        if (treeGrid == null) {
-            return toLoad;
-        }
+        // FIXME: bad... instead we should react to selection events and update toLoad in this way.
 
-        ListGridRecord [] selection = treeGrid.getSelectedRecords();
+        this.toLoad = new ToLoad();
+
+        if (this.treeGrid == null)
+            return this.toLoad;
+
+        final ListGridRecord[] selection = this.treeGrid.getSelectedRecords();
 
         if (selection != null) {
-            for (ListGridRecord record: selection) {
+            for (final ListGridRecord record : selection) {
                 if (record instanceof TreeNode) {
-                    collectToLoads((TreeNode)record);
+                    collectToLoads((TreeNode) record);
                 }
             }
         }
 
-        return toLoad;
+        return this.toLoad;
     }
 
-
     public List<TreeNode> getPlainSelection() {
-        ListGridRecord [] selection = treeGrid.getSelectedRecords();
-        List<TreeNode> nodes = new ArrayList<TreeNode>();
+        final ListGridRecord[] selection = this.treeGrid.getSelectedRecords();
+        final List<TreeNode> nodes = new ArrayList<TreeNode>();
         if (selection != null) {
-            for (ListGridRecord record: selection) {
+            for (final ListGridRecord record : selection) {
                 if (record instanceof TreeNode) {
-                    nodes.add((TreeNode)record);
+                    nodes.add((TreeNode) record);
                 }
             }
         }
         return nodes;
     }
 
-
     /**
      * Returns the titles of selected items (if any).
      */
     public String[] getSelectionTitles() {
-        if (treeGrid == null) {
+        if (this.treeGrid == null) {
             return new String[] {};
         }
 
-        ListGridRecord [] selection = treeGrid.getSelectedRecords();
+        final ListGridRecord[] selection = this.treeGrid.getSelectedRecords();
 
         if (selection == null) {
             return new String[] {};
         }
 
-        List<String> titleList = new ArrayList<String>();
-        for (ListGridRecord record: selection) {
+        final List<String> titleList = new ArrayList<String>();
+        for (final ListGridRecord record : selection) {
             if (record instanceof TreeNode) {
-                titleList.add(((TreeNode)record).getAttribute("name"));
+                titleList.add(((TreeNode) record).getAttribute("name"));
             }
         }
 
         return titleList.toArray(new String[titleList.size()]);
     }
 
-
     /**
      * Callback for add-button.
      * Fires to load for every selected element and handler.
      */
-    public void plusClicked() {
+    protected final void plusClicked() {
         if (!getSelection().isEmpty()) {
             fireToLoad();
         }
     }
 
-
-    protected Button createPlusButton() {
-        Button plusBtn = new Button(messages.datacageAdd());
+    private Button createPlusButton() {
+        final Button plusBtn = new Button(MSG.datacageAdd());
         plusBtn.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(ClickEvent event) {
+            public void onClick(final ClickEvent event) {
                 plusClicked();
             }
         });
         return plusBtn;
     }
 
-
-    protected void fireToLoad() {
-        for (DatacageHandler handler: handlers) {
-            handler.toLoad(toLoad);
+    private void fireToLoad() {
+        for (final DatacageHandler handler : this.handlers) {
+            handler.toLoad(this.toLoad);
         }
     }
 
-
     /** Notify DatacageDoubleClickHandlers that a doubleclick happened. */
-    protected void fireOnDoubleClick() {
-        for (DatacageDoubleClickHandler handler: doubleHandlers) {
-            handler.onDoubleClick(toLoad);
+    private void fireOnDoubleClick() {
+        for (final DatacageDoubleClickHandler handler : this.doubleHandlers) {
+            handler.onDoubleClick(this.toLoad);
         }
     }
 
-
-    protected void doubleClickedOnTree(RecordDoubleClickEvent event) {
-        TreeNode node = (TreeNode)event.getRecord();
+    protected final void doubleClickedOnTree(final RecordDoubleClickEvent event) {
+        final TreeNode node = (TreeNode) event.getRecord();
         collectToLoads(node);
         fireOnDoubleClick();
     }
 
-
     /**
      * Adds to toLoad, from info in node.
      * Afterwards, add all children of node to stack to parse (next time
      * collectToLoads is called).
      */
-    protected void collectToLoads(TreeNode node) {
-        Stack<TreeNode> stack = new Stack<TreeNode>();
+    private void collectToLoads(final TreeNode root1) {
+        final Stack<TreeNode> stack = new Stack<TreeNode>();
 
-        stack.push(node);
+        stack.push(root1);
 
         while (!stack.isEmpty()) {
-            node = stack.pop();
-            String factory = node.getAttribute("factory");
+            final TreeNode node = stack.pop();
+            final String factory = node.getAttribute("factory");
             if (factory != null) { // we need at least a factory
-                String artifact = node.getAttribute("artifact-id");
-                String out      = node.getAttribute("out");
-                String name     = node.getAttribute("facet");
-                String ids      = node.getAttribute("ids");
-                String displayname = node.getAttribute("name");
-                String targetOut = node.getAttribute("target_out");
+                final String artifact = node.getAttribute("artifact-id");
+                final String out = node.getAttribute("out");
+                final String name = node.getAttribute("facet");
+                final String ids = node.getAttribute("ids");
+                final String displayname = node.getAttribute("name");
+                final String targetOut = node.getAttribute("target_out");
                 String debugAttributeValues = "";
-                for (String attr: node.getAttributes()) {
-                    debugAttributeValues += ("[" + attr +": "
-                        + node.getAttributeAsString(attr) + "] ");
+                for (final String attr : node.getAttributes()) {
+                    debugAttributeValues += ("[" + attr + ": " + node.getAttributeAsString(attr) + "] ");
                 }
-                GWT.log("DatacageWidget.collectToLoad, attributes are "
-                    + debugAttributeValues);
+                GWT.log("DatacageWidget.collectToLoad, attributes are " + debugAttributeValues);
 
-                toLoad.add(artifact,
-                     factory,
-                     out,
-                     name,
-                     ids,
-                     displayname,
-                     targetOut);
+                this.toLoad.add(artifact, factory, out, name, ids, displayname, targetOut);
             }
-            TreeNode [] children = tree.getChildren(node);
+            final TreeNode[] children = this.tree.getChildren(node);
             if (children != null) {
-                for (TreeNode child: children) {
+                for (final TreeNode child : children) {
                     stack.push(child);
                 }
             }
         }
     }
 
-
     /** Get meta-data and populate tree with it. */
-    protected void triggerTreeBuilding() {
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
-
-        String artifactId = artifact.getUuid();
-        String userId     = (user != null) ? user.identifier() : null;
-
+    private void triggerTreeBuilding() {
         lockUI();
 
-        metaDataService.getMetaData(
-            locale,
-            artifactId,
-            userId,
-            outs,
-            parameters,
-            new AsyncCallback<DataCageTree>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Could not load meta data.");
-                    SC.warn(caught.getMessage());
-                    unlockUI();
-                }
+        final String locale = Config.getInstance().getLocale();
 
-                @Override
-                public void onSuccess(DataCageTree dcTree) {
-                    GWT.log("Successfully loaded meta data.");
-                    IdGenerator idGenerator = new IdGenerator();
-                    DataCageNode dcRoot = dcTree.getRoot();
-                    TreeNode root = buildRecursiveChildren(
-                        dcRoot, idGenerator);
-                    tree.setRoot(root);
+        final String artifactId = this.data.getArtifact().getUuid();
+        final User user = this.data.getUser();
+        final String userId = user != null ? user.identifier() : null;
+        final String outs = this.data.getOuts();
+        final String parameters = this.data.getParameters();
 
-                    TreeNode[] nodes = tree.getChildren(root);
-                    for (TreeNode node: nodes) {
-                        if (node.getAttribute("factory") == null &&
-                                !tree.hasChildren(node)) {
-                            node.setIsFolder(true);
-                        }
-                    }
+        this.metaDataService.getMetaData(locale, artifactId, userId, outs, parameters, new AsyncCallback<DataCageTree>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Could not load meta data.");
+                SC.warn(caught.getMessage());
+                unlockUI();
+            }
 
-                    if (idGenerator.current() < MAX_OPEN) {
-                        tree.openAll();
-                    }
-                    treeGrid.setData(tree);
-                    unlockUI();
-                }
-            });
+            @Override
+            public void onSuccess(final DataCageTree dcData) {
+                GWT.log("Successfully loaded meta data.");
+
+                setDatacageData(dcData);
+                unlockUI();
+            }
+        });
+    }
+
+    protected final void setDatacageData(final DataCageTree dcTree) {
+
+        this.dcTree = dcTree;
+
+        if (this.tree != null)
+            this.tree.destroy();
+
+        updateTree(this.dcTree);
+    }
+
+    private void updateTree(final DataCageTree dcData) {
+
+        this.tree = new Tree();
+        this.tree.setModelType(TreeModelType.CHILDREN);
+        this.tree.setNameProperty("name");
+        this.tree.setIdField("id");
+        this.tree.setChildrenProperty("children-nodes");
+        this.tree.setShowRoot(false);
+
+        final IdGenerator idGenerator = new IdGenerator();
+        final DataCageNode dcRoot = dcData.getRoot();
+        final TreeNode root = buildRecursiveChildren(dcRoot, idGenerator);
+        if (root != null) {
+            this.tree.setRoot(root);
+
+            // FIXME: why is this necessary? an it only happens for the first level...
+            final TreeNode[] nodes = this.tree.getChildren(root);
+            for (final TreeNode node : nodes) {
+                if (node.getAttribute("factory") == null && !this.tree.hasChildren(node))
+                    node.setIsFolder(true);
+            }
+        }
+
+        if (idGenerator.current() < MAX_OPEN)
+            this.tree.openAll();
+
+        this.treeGrid.setData(this.tree);
     }
 
     private static final class IdGenerator {
@@ -479,61 +432,70 @@
         }
 
         public int next() {
-            return current++;
+            return this.current++;
         }
 
         public int current() {
-            return current;
+            return this.current;
         }
     } // class IdGenerator
 
-    private String i18n(String s) {
-        if (!(s.startsWith("${") && s.endsWith("}"))) {
+    private String i18n(final String s) {
+        if (!(s.startsWith("${") && s.endsWith("}")))
             return s;
-        }
 
-        s = s.substring(2, s.length()-1);
+        final String sub = s.substring(2, s.length() - 1);
 
         try {
-            return messages.getString(s);
+            return MSG.getString(sub);
         }
-        catch (MissingResourceException mre) {
-            GWT.log("cannot find i18n for + '" + s + "'");
-            return s;
+        catch (final MissingResourceException mre) {
+            GWT.log("cannot find i18n for + '" + sub + "'", mre);
+            return sub;
         }
     }
 
-    protected TreeNode buildRecursiveChildren(
-        DataCageNode   node,
-        IdGenerator    idGenerator
-    ) {
-        TreeNode tn = new TreeNode();
+    private TreeNode buildRecursiveChildren(final DataCageNode node, final IdGenerator idGenerator) {
+
+        if (!this.filter.accept(node))
+            return null;
+
+        final List<DataCageNode> children = node.getChildren();
+
+        final Collection<TreeNode> tns = new ArrayList<TreeNode>();
+
+        if (children != null && !children.isEmpty()) {
+
+            for (final DataCageNode child : children) {
+
+                final TreeNode childNode = buildRecursiveChildren(child, idGenerator);
+                if (childNode != null)
+                    tns.add(childNode);
+            }
+
+            /* if we should have children, but all got filtered, hide this node as well */
+            if (tns.isEmpty())
+                return null;
+        }
+
+        final TreeNode tn = new TreeNode();
         tn.setAttribute("id", idGenerator.next());
 
-        List<DataCageNode> children = node.getChildren();
-
-        if (children != null) {
-            TreeNode [] tns = new TreeNode[children.size()];
-            for (int i = 0; i < tns.length; ++i) {
-                DataCageNode child = children.get(i);
-                tns[i] = buildRecursiveChildren(child, idGenerator);
-            }
-            tn.setAttribute("children-nodes", tns);
-        }
+        if (!tns.isEmpty())
+            tn.setAttribute("children-nodes", tns.toArray(new TreeNode[tns.size()]));
 
         tn.setAttribute("name", i18n(node.getDescription()));
         tn.setAttribute("facet", node.getName());
 
-        AttrList attrs = node.getAttributes();
+        final AttrList attrs = node.getAttributes();
         if (attrs != null) {
             for (int i = 0, N = attrs.size(); i < N; ++i) {
-                String key   = attrs.getKey(i);
-                String value = attrs.getValue(i);
+                final String key = attrs.getKey(i);
+                final String value = attrs.getValue(i);
                 tn.setAttribute(key, value);
             }
         }
 
         return tn;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ 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/DatacageWidgetData.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,78 @@
+/** 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;
+
+import org.dive4elements.river.client.shared.model.Artifact;
+import org.dive4elements.river.client.shared.model.User;
+
+/**
+ * Holds all data that configures the {@link DatacageWidget}
+ *
+ * @author Gernot Belger
+ */
+public class DatacageWidgetData {
+
+    private final Artifact artifact;
+    private final User user;
+    private final String outs;
+    private final String parameters;
+    private final boolean showButton;
+    private final String columnLabel;
+
+    public DatacageWidgetData(final Artifact artifact, final User user) {
+        this(artifact, user, null);
+    }
+
+    public DatacageWidgetData(final Artifact artifact, final User user, final String outs) {
+        this(artifact, user, outs, true);
+    }
+
+    public DatacageWidgetData(final Artifact artifact, final User user, final String outs, final boolean showButton) {
+        this(artifact, user, outs, null, showButton);
+    }
+
+    public DatacageWidgetData(final Artifact artifact, final User user, final String outs, final String parameters, final boolean showButton) {
+        this(artifact, user, outs, parameters, showButton, null);
+    }
+
+    public DatacageWidgetData(final Artifact artifact, final User user, final String outs, final String parameters, final boolean showButton,
+            final String columnLabel) {
+        this.artifact = artifact;
+        this.user = user;
+        this.outs = outs;
+        this.parameters = parameters;
+        this.showButton = showButton;
+        this.columnLabel = columnLabel;
+    }
+
+    public Artifact getArtifact() {
+        return this.artifact;
+    }
+
+    public User getUser() {
+        return this.user;
+    }
+
+    public String getOuts() {
+        return this.outs;
+    }
+
+    public String getParameters() {
+        return this.parameters;
+    }
+
+    public boolean isShowButton() {
+        return this.showButton;
+    }
+
+    public String getColumnLabel() {
+        return this.columnLabel;
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageWindow.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageWindow.java	Fri Jul 13 11:56:22 2018 +0200
@@ -76,12 +76,9 @@
         setWidth(400);
         setHeight(500);
 
-        DatacageWidget dw = new DatacageWidget(
-            artifact,
-            user,
-            outs,
-            "load-system:true",
-            true);
+        final DatacageWidgetData data = new DatacageWidgetData( artifact, user, outs, "load-system:true", true );
+        
+        DatacageWidget dw = new DatacageWidget( data );
         dw.addDatacageHandler(this);
         dw.addDatacageDoubleClickHandler(this);
 
@@ -192,6 +189,7 @@
                 factory,
                 locale,
                 new AsyncCallback<Artifact>() {
+                    @Override
                     public void onFailure(Throwable caught) {
                         decreateInProgress();
                         GWT.log("Create-artifact failed: "
@@ -199,6 +197,7 @@
                         SC.warn(caught.getMessage());
                     }
 
+                    @Override
                     public void onSuccess(Artifact artifact) {
                         decreateInProgress();
                         GWT.log("Created new artifact: " + artifact.getUuid());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DefaultDatacageTwinPanelInfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,57 @@
+/** 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;
+
+import org.dive4elements.river.client.client.ui.DatacageTwinPanel.IDatacageTwinPanelInfo;
+import org.dive4elements.river.client.shared.model.Recommendation;
+
+/**
+ * This info implementation overwrites the real factory of the recommendation with a fixed value.
+ * Evil, but this is how it is done in the current code.
+ *
+ * @author Gernot Belger
+ */
+public final class DefaultDatacageTwinPanelInfo implements IDatacageTwinPanelInfo {
+
+    private final String factory;
+    private final String outs;
+    private final String columnLabel;
+
+    public DefaultDatacageTwinPanelInfo(final String columnLabel, final String factory, final String outs) {
+        this.columnLabel = columnLabel;
+        this.factory = factory;
+        this.outs = outs;
+    }
+
+    @Override
+    public String getFactory(final String originalFactory) {
+        return this.factory;
+    }
+
+    @Override
+    public String getDataStringFactory(final Recommendation recommendation) {
+        return this.factory;
+    }
+
+    @Override
+    public void adjustRecommendation(final Recommendation recommendation) {
+        recommendation.setFactory(this.factory);
+    }
+
+    @Override
+    public String getColumnLabel() {
+        return this.columnLabel;
+    }
+
+    @Override
+    public String getOuts() {
+        return this.outs;
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DemDatacagePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DemDatacagePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,6 +8,9 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.dive4elements.river.client.shared.model.Data;
 import org.dive4elements.river.client.shared.model.DataItem;
 import org.dive4elements.river.client.shared.model.DefaultData;
@@ -16,75 +19,43 @@
 import org.dive4elements.river.client.shared.model.ToLoad;
 import org.dive4elements.river.client.shared.model.User;
 
-import java.util.ArrayList;
-import java.util.List;
-
-
 public class DemDatacagePanel extends DatacagePanel {
 
     private static final long serialVersionUID = -2301633938080411687L;
 
-    public static final String OUT        = "floodmap_dem_panel";
-    public static final String PARAMETERS = "dem:true";
-
-
-    public DemDatacagePanel() {
-        super();
-    }
-
-
-    public DemDatacagePanel(User user) {
-        super(user);
-    }
-
+    private static final String OUT = "floodmap_dem_panel";
 
-    @Override
-    protected void createWidget() {
-        super.createWidget();
-        widget.setIsMutliSelectable(false);
-    }
-
+    private static final String PARAMETERS = "dem:true";
 
-    @Override
-    public String getOuts() {
-        return OUT;
+    public DemDatacagePanel(final User user) {
+        super(user, OUT, PARAMETERS, false);
     }
 
-
-    @Override
-    public String getParameters() {
-        return PARAMETERS;
-    }
-
-
     @Override
     public List<String> validate() {
-        List<String> errors = new ArrayList<String>();
+        final List<String> errors = new ArrayList<String>();
 
-        Recommendation r = getSelectedRecommendation();
-        if (r == null) {
+        final Recommendation r = getSelectedRecommendation();
+        if (r == null)
             errors.add(MSG.requireDGM());
-        }
 
         return errors;
     }
 
-
     @Override
     protected Data[] getData() {
-        Recommendation r = getSelectedRecommendation();
+        final Recommendation r = getSelectedRecommendation();
 
-        DataItem item = new DefaultDataItem(dataName, dataName, r.getIDs());
-        return new Data[] { new DefaultData(
-            dataName, null, null, new DataItem[] { item }) };
+        final String dataName = getMyDataName();
+
+        final DataItem item = new DefaultDataItem(dataName, dataName, r.getIDs());
+        return new Data[] { new DefaultData(dataName, null, null, new DataItem[] { item }) };
     }
 
-
     protected Recommendation getSelectedRecommendation() {
-        ToLoad toLoad = widget.getSelection();
-        List<Recommendation> recoms = toLoad.toRecommendations();
+        final ToLoad toLoad = getSelection();
+        final List<Recommendation> recoms = toLoad.toRecommendations();
 
         return recoms != null && recoms.size() >= 1 ? recoms.get(0) : null;
     }
-}
-// 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/ui/DistanceOnlyPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistanceOnlyPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,40 +8,37 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import java.util.List;
+
 import org.dive4elements.river.client.shared.model.Data;
 import org.dive4elements.river.client.shared.model.DataItem;
 import org.dive4elements.river.client.shared.model.DataList;
-
-import java.util.List;
-
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
 
 public class DistanceOnlyPanel extends DistancePanel {
 
     private static final long serialVersionUID = -5794138573892656947L;
 
-
     public DistanceOnlyPanel() {
         this("right");
     }
 
-
-    public DistanceOnlyPanel(String labelOrientation) {
-        distancePanel = new DoubleRangeOnlyPanel(
-            labelFrom(), labelTo(), 0d, 0d, 250, this, labelOrientation);
+    public DistanceOnlyPanel(final String labelOrientation) {
+        this.distancePanel = new DoubleRangeOnlyPanel(labelFrom(), labelTo(), 0d, 0d, 250, this, labelOrientation);
     }
 
-
     @Override
-    protected String getOldSelectionString(DataList dataList) {
-        List<Data> items = dataList.getAll();
+    protected String getOldSelectionString(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
 
-        Data dFrom = getData(items, getLowerField());
-        Data dTo   = getData(items, getUpperField());
+        final Data dFrom = getData(items, getLowerField());
+        final Data dTo = getData(items, getUpperField());
 
-        DataItem[] from = dFrom.getItems();
-        DataItem[] to   = dTo.getItems();
+        final DataItem[] from = dFrom.getItems();
+        final DataItem[] to = dTo.getItems();
 
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         sb.append(from[0].getLabel());
         sb.append(" " + getUnitFrom() + " - ");
         sb.append(to[0].getLabel());
@@ -50,33 +47,31 @@
         return sb.toString();
     }
 
-
     @Override
-    protected void initDefaultStep(DataList data) {
+    protected void initDefaultStep(final DataList data) {
         // do nothing
     }
 
-
     @Override
     public Data[] getData() {
-        Data[] data = new Data[2];
+        final Data[] data = new Data[3];
 
         data[0] = getDataFrom();
         data[1] = getDataTo();
 
+        final DataItem item = new DefaultDataItem("ld_mode", "ld_mode", "distance_only");
+        data[2] = new DefaultData("ld_mode", null, null, new DataItem[] { item });
+
         return data;
     }
 
-
     @Override
     protected String labelFrom() {
         return getUnitFrom() + " - ";
     }
 
-
     @Override
     protected String labelTo() {
         return getUnitTo();
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ 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/DistanceOnlyPartHistoricalPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,61 @@
+/* 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.client.client.ui;
+
+import java.util.List;
+
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.widgets.Canvas;
+
+public class DistanceOnlyPartHistoricalPanel extends DistanceOnlyPartPanel {
+
+    private static final long serialVersionUID = 1L;
+    private List<String> validInputs;
+
+    @Override
+    protected void initHelperPanel(final DataList data) {
+        final FromToTableHelperPanel helper = new FromToTableHelperPanel(data, "bedheights_for_part", this.MSG, null, null);
+        final Canvas table = helper.getTable();
+        this.validInputs = helper.getKeycolEntries();
+
+        this.helperContainer.addMember(table);
+
+    }
+
+    @Override
+    protected void initMinMaxValues(final DataList data) {
+        try {
+            for (final Data item : data.getAll()) {
+                if (item.getLabel().equals("ld_from_part"))// misuse ld_from_part for max container
+                    this.min = Double.valueOf(item.getItems()[0].getStringValue());
+
+                if (item.getLabel().equals("ld_to_part"))// misuse ld_to_part for max container
+                    this.max = Double.valueOf(item.getItems()[0].getStringValue());
+            }
+        }
+        catch (final NumberFormatException nfe) {
+            this.min = -Double.MAX_VALUE;
+            this.max = Double.MAX_VALUE;
+        }
+    }
+
+    @Override
+    protected void initDefaultFrom(final DataList data) {
+        final double from = (this.min < -99999.) ? 0 : this.min;
+        this.distancePanel.setFrom(from);
+    }
+
+    @Override
+    protected void initDefaultTo(final DataList data) {
+        final double to = (this.max > 99999.) ? 0 : this.max;
+        this.distancePanel.setTo(to);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistanceOnlyPartPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,62 @@
+/* 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.client.client.ui;
+
+import org.dive4elements.river.client.client.artifacthelper.ArtifactHelper;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.widgets.Label;
+
+public class DistanceOnlyPartPanel extends DistanceOnlyPanel {
+
+    private static final long serialVersionUID = -5794138573892656947L;
+
+    public DistanceOnlyPartPanel() {
+        super();
+    }
+
+    @Override
+    protected Label getLabel(final DataList data) {
+        final Data item = data.get(0);
+        return new Label(item.getDescription());//
+        // TODO: migrate distance_part_state to server
+        // item.getDescription()); // holt das Label vom Server (funktoniert schon sehr oft so!)
+    }
+
+    @Override
+    protected String getLowerField() {
+        return "ld_from_part";
+    }
+
+    @Override
+    protected String getUpperField() {
+        return "ld_to_part";
+    }
+
+    @Override
+    protected void initMinMaxValues(final DataList data) {
+        final ArtifactHelper helper = new ArtifactHelper(super.artifact);
+
+        final Data f = helper.getOldDataByKey("ld_from");
+        final Data t = helper.getOldDataByKey("ld_to");
+        try {
+            final DataItem[] fItems = f.getItems();
+            final DataItem[] tItems = t.getItems();
+
+            this.min = Double.valueOf(fItems[0].getStringValue());
+            this.max = Double.valueOf(tItems[0].getStringValue());
+        }
+        catch (final NumberFormatException nfe) {
+            this.min = -Double.MAX_VALUE;
+            this.max = Double.MAX_VALUE;
+        }
+    }
+}
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,59 +8,34 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
 
-import com.smartgwt.client.data.AdvancedCriteria;
-import com.smartgwt.client.data.Criteria;
-import com.smartgwt.client.data.Criterion;
-import com.smartgwt.client.data.Record;
-import com.smartgwt.client.types.Alignment;
-import com.smartgwt.client.types.OperatorId;
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.StaticTextItem;
-import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
-import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
-import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
-import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
-import com.smartgwt.client.widgets.grid.ListGrid;
-import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
-import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
-import com.smartgwt.client.widgets.tab.Tab;
-import com.smartgwt.client.widgets.tab.TabSet;
-import com.smartgwt.client.widgets.tab.events.TabSelectedEvent;
-import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
-
-import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYSConstants;
-import org.dive4elements.river.client.client.event.FilterHandler;
-import org.dive4elements.river.client.client.event.RangeFilterEvent;
-import org.dive4elements.river.client.client.event.StringFilterEvent;
-import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource;
-import org.dive4elements.river.client.client.ui.range.LocationsTable;
-import org.dive4elements.river.client.client.ui.range.RangeTable;
-import org.dive4elements.river.client.shared.model.ArtifactDescription;
 import org.dive4elements.river.client.shared.model.Data;
 import org.dive4elements.river.client.shared.model.DataItem;
 import org.dive4elements.river.client.shared.model.DataList;
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.NumberFormat;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.fields.StaticTextItem;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.TabSet;
 
 /** Panel to allow input of distance for calculation range. */
-public class DistancePanel
-    extends AbstractUIProvider implements BlurHandler, FilterHandler
-{
+public class DistancePanel extends AbstractUIProvider implements BlurHandler {
 
     private static final long serialVersionUID = -883142387908664588L;
 
@@ -68,13 +43,12 @@
 
     public static final String FIELD_LOWER = "ld_from";
     public static final String FIELD_UPPER = "ld_to";
-    public static final String FIELD_STEP  = "ld_step";
-
+    public static final String FIELD_STEP = "ld_step";
 
     protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
 
-    protected RangeTable     distancesTable;
-    protected LocationsTable locationsTable;
+    // protected RangeTable distancesTable;
+    // protected LocationsTable locationsTable;
 
     protected DoubleRangePanel distancePanel;
 
@@ -93,47 +67,47 @@
         this("right");
     }
 
-
-    public DistancePanel(String labelOrientation) {
-        distancePanel  = new DoubleRangePanel(
-            labelFrom(), labelTo(), labelStep(),
-            0d, 0d, 0d, 250, this, labelOrientation);
+    public DistancePanel(final String labelOrientation) {
+        this.distancePanel = new DoubleRangePanel(labelFrom(), labelTo(), labelStep(), 0d, 0d, 0d, 250, this, labelOrientation);
     }
 
-
     @Override
-    public Canvas create(DataList data) {
-        VLayout layout = new VLayout();
+    public Canvas create(final DataList data) {
+        final VLayout layout = new VLayout();
         layout.setMembersMargin(10);
 
-        Label label = new Label(getLabel());
+        final Label label = getLabel(data);
 
-        Canvas submit = getNextButton();
+        final Canvas submit = getNextButton();
 
         label.setHeight(25);
-        distancePanel.setHeight(50);
+        this.distancePanel.setHeight(50);
 
         layout.addMember(label);
-        layout.addMember(distancePanel);
+        layout.addMember(this.distancePanel);
         layout.addMember(submit);
 
         initMinMaxValues(data);
         initDefaultValues(data);
-        initHelperPanel();
+        initHelperPanel(data);
 
         return layout;
     }
 
+    protected Label getLabel(final DataList data) {
+        final Data item = data.get(0);
+        return new Label(item.getDescription()); // holt das Label vom Server (funktoniert schon sehr oft so!)
+    }
 
     @Override
-    public Canvas createOld(DataList dataList) {
-        String s = getOldSelectionString(dataList);
-        String l = dataList.getLabel();
+    public Canvas createOld(final DataList dataList) {
+        final String s = getOldSelectionString(dataList);
+        final String l = dataList.getLabel();
 
-        Label label    = new Label(l);
-        Label selected = new Label(s);
+        final Label label = new Label(l);
+        final Label selected = new Label(s);
 
-        HLayout layout = new HLayout();
+        final HLayout layout = new HLayout();
 
         layout.setWidth(400);
         label.setWidth(200);
@@ -146,19 +120,18 @@
         return layout;
     }
 
-
-    protected String getOldSelectionString(DataList dataList) {
-        List<Data> items = dataList.getAll();
+    protected String getOldSelectionString(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
 
-        Data dFrom = getData(items, getLowerField());
-        Data dTo   = getData(items, getUpperField());
-        Data dStep = getData(items, getStepField());
+        final Data dFrom = getData(items, getLowerField());
+        final Data dTo = getData(items, getUpperField());
+        final Data dStep = getData(items, getStepField());
 
-        DataItem[] from = dFrom.getItems();
-        DataItem[] to   = dTo.getItems();
-        DataItem[] step = dStep.getItems();
+        final DataItem[] from = dFrom.getItems();
+        final DataItem[] to = dTo.getItems();
+        final DataItem[] step = dStep.getItems();
 
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         sb.append(from[0].getLabel());
         sb.append(" " + getUnitFrom() + " - ");
         sb.append(to[0].getLabel());
@@ -169,78 +142,64 @@
         return sb.toString();
     }
 
-
-    protected String getLabel() {
-        return MSG.distance_state();
-    }
-
+    // protected String getLabel() {
+    // return this.MSG.distance_state();
+    // }
 
     protected String labelFrom() {
         return getLabelFrom() + " [" + getUnitFrom() + "]";
     }
 
-
     protected String getLabelFrom() {
-        return MSG.dpLabelFrom();
+        return this.MSG.dpLabelFrom();
     }
 
-
     protected String getUnitFrom() {
-        return MSG.dpUnitFrom();
+        return this.MSG.dpUnitFrom();
     }
 
-
     protected String labelTo() {
         return getLabelTo() + " [" + getUnitTo() + "]";
     }
 
-
     protected String getLabelTo() {
-        return MSG.dpLabelTo();
+        return this.MSG.dpLabelTo();
     }
 
-
     protected String getUnitTo() {
-        return MSG.dpUnitTo();
+        return this.MSG.dpUnitTo();
     }
 
-
     protected String labelStep() {
         return getLabelStep() + " [" + getUnitStep() + "]";
     }
 
-
     protected String getLabelStep() {
-        return MSG.dpLabelStep();
+        return this.MSG.dpLabelStep();
     }
 
-
     protected String getUnitStep() {
-        return MSG.dpUnitStep();
+        return this.MSG.dpUnitStep();
     }
 
-
     protected String getLowerField() {
         return FIELD_LOWER;
     }
 
-
     protected String getUpperField() {
         return FIELD_UPPER;
     }
 
-
     protected String getStepField() {
         return FIELD_STEP;
     }
 
-
     @Override
     public List<String> validate() {
-        List<String> errors = new ArrayList<String>();
+        final List<String> errors = new ArrayList<String>();
 
-        if (!distancePanel.validateForm()) {
-            errors.add(MSG.wrongFormat());
+        if (!this.distancePanel.validateForm()) {
+            errors.add(this.MSG.wrongFormat());
 
             return errors;
         }
@@ -251,414 +210,213 @@
         return errors;
     }
 
-
-    protected void validateFrom(List<String> errors) {
-        double from = distancePanel.getFrom();
+    protected void validateFrom(final List<String> errors) {
+        final double from = this.distancePanel.getFrom();
 
-        if (from < min || from > max) {
-            NumberFormat nf = NumberFormat.getDecimalFormat();
+        if (from < this.min || from > this.max) {
+            final NumberFormat nf = NumberFormat.getDecimalFormat();
 
-            String tmp = MSG.error_validate_lower_range();
-            tmp        = tmp.replace("$1", nf.format(from));
-            tmp        = tmp.replace("$2", nf.format(min));
+            String tmp = this.MSG.error_validate_lower_range();
+            tmp = tmp.replace("$1", nf.format(from));
+            tmp = tmp.replace("$2", nf.format(this.min));
 
-            distancePanel.setFrom(min);
+            this.distancePanel.setFrom(this.min);
             errors.add(tmp);
         }
     }
 
-
-    protected void validateTo(List<String> errors) {
-        double to = distancePanel.getTo();
+    protected void validateTo(final List<String> errors) {
+        final double to = this.distancePanel.getTo();
 
-        if (to < min || to > max) {
-            NumberFormat nf = NumberFormat.getDecimalFormat();
+        if (to < this.min || to > this.max) {
+            final NumberFormat nf = NumberFormat.getDecimalFormat();
 
-            String tmp = MSG.error_validate_upper_range();
-            tmp        = tmp.replace("$1", nf.format(to));
-            tmp        = tmp.replace("$2", nf.format(max));
+            String tmp = this.MSG.error_validate_upper_range();
+            tmp = tmp.replace("$1", nf.format(to));
+            tmp = tmp.replace("$2", nf.format(this.max));
 
-            distancePanel.setTo(max);
+            this.distancePanel.setTo(this.max);
             errors.add(tmp);
         }
     }
 
-
     @Override
     public Data[] getData() {
-        Data[] data = new Data[4];
+        final Data[] data = new Data[4];
 
         data[0] = getDataFrom();
         data[1] = getDataTo();
         data[2] = getDataStep();
 
-        DataItem item = new DefaultDataItem("ld_mode","ld_mode", "distance");
-        data[3]       = new DefaultData(
-            "ld_mode", null, null, new DataItem[] { item });
+        final DataItem item = new DefaultDataItem("ld_mode", "ld_mode", "distance");
+        data[3] = new DefaultData("ld_mode", null, null, new DataItem[] { item });
 
         return data;
     }
 
-
     protected Data getDataFrom() {
-        String value = String.valueOf(distancePanel.getFrom());
-        String field = getLowerField();
+        final String value = String.valueOf(this.distancePanel.getFrom());
+        final String field = getLowerField();
 
-        DataItem item = new DefaultDataItem(field, field, value);
-        return new DefaultData(
-            field, null, null, new DataItem[] { item });
+        final DataItem item = new DefaultDataItem(field, field, value);
+        return new DefaultData(field, null, null, new DataItem[] { item });
     }
 
-
     protected Data getDataTo() {
-        String value = String.valueOf(distancePanel.getTo());
-        String field = getUpperField();
+        final String value = String.valueOf(this.distancePanel.getTo());
+        final String field = getUpperField();
 
-        DataItem item = new DefaultDataItem(field, field, value);
-        return new DefaultData(
-            field, null, null, new DataItem[] { item });
+        final DataItem item = new DefaultDataItem(field, field, value);
+        return new DefaultData(field, null, null, new DataItem[] { item });
     }
 
-
     protected Data getDataStep() {
-        String value = String.valueOf(distancePanel.getStep());
-        String field = getStepField();
+        final String value = String.valueOf(this.distancePanel.getStep());
+        final String field = getStepField();
 
-        DataItem item = new DefaultDataItem(field, field, value);
-        return new DefaultData(
-            field, null, null, new DataItem[] { item });
-    }
-
-
-    @Override
-    public void onBlur(BlurEvent event) {
-        distancePanel.validateForm();
+        final DataItem item = new DefaultDataItem(field, field, value);
+        return new DefaultData(field, null, null, new DataItem[] { item });
     }
 
+    protected void initMinMaxValues(final DataList data) {
+        final Data f = getData(data.getAll(), getLowerField());
+        final Data t = getData(data.getAll(), getUpperField());
 
-    protected void initMinMaxValues(DataList data) {
-        Data f = getData(data.getAll(), getLowerField());
-        Data t = getData(data.getAll(), getUpperField());
-
-        DataItem[] fItems = f.getItems();
-        DataItem[] tItems = t.getItems();
+        final DataItem[] fItems = f.getItems();
+        final DataItem[] tItems = t.getItems();
 
         try {
-            min = Double.valueOf(fItems[0].getStringValue());
-            max = Double.valueOf(tItems[0].getStringValue());
+            this.min = Double.valueOf(fItems[0].getStringValue());
+            this.max = Double.valueOf(tItems[0].getStringValue());
         }
-        catch (NumberFormatException nfe) {
-            min = -Double.MAX_VALUE;
-            max =  Double.MAX_VALUE;
+        catch (final NumberFormatException nfe) {
+            this.min = -Double.MAX_VALUE;
+            this.max = Double.MAX_VALUE;
         }
     }
 
-
-    protected void initDefaultValues(DataList data) {
+    protected void initDefaultValues(final DataList data) {
         initDefaultFrom(data);
         initDefaultTo(data);
         initDefaultStep(data);
     }
 
-
-    protected void initDefaultFrom(DataList data) {
-        Data f = getData(data.getAll(), getLowerField());
+    protected void initDefaultFrom(final DataList data) {
+        final Data f = getData(data.getAll(), getLowerField());
 
         double from = getDefaultFrom();
 
         try {
             from = getDefaultValue(f);
         }
-        catch (NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             // do nothing
         }
 
-        distancePanel.setFrom(from);
+        this.distancePanel.setFrom(from);
     }
 
-
     protected double getDefaultFrom() {
-        return min;
+        return this.min;
     }
 
-
-    protected void initDefaultTo(DataList data) {
-        Data t = getData(data.getAll(), getUpperField());
+    protected void initDefaultTo(final DataList data) {
+        final Data t = getData(data.getAll(), getUpperField());
 
         double to = getDefaultTo();
 
         try {
             to = getDefaultValue(t);
         }
-        catch (NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             // do nothing
         }
 
-        distancePanel.setTo(to);
+        this.distancePanel.setTo(to);
     }
 
-
     protected double getDefaultTo() {
-        return max;
+        return this.max;
     }
 
-
-    protected void initDefaultStep(DataList data) {
-        Data s = getData(data.getAll(), getStepField());
+    protected void initDefaultStep(final DataList data) {
+        final Data s = getData(data.getAll(), getStepField());
 
         double step = getDefaultStep();
 
         try {
             step = getDefaultValue(s);
         }
-        catch (NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             // do nothing
         }
 
-        distancePanel.setStep(step);
+        this.distancePanel.setStep(step);
     }
 
-
     protected double getDefaultStep() {
         return DEFAULT_STEP_WIDTH;
     }
 
-
     /** Gets the double from default in data, null if none. */
-    protected double getDefaultValue(Data data)
-    throws NumberFormatException
-    {
-        DataItem def      = data.getDefault();
-        String   defValue = def != null ? def.getStringValue() : null;
+    protected double getDefaultValue(final Data data) throws NumberFormatException {
+        final DataItem def = data.getDefault();
+        final String defValue = def != null ? def.getStringValue() : null;
 
         return Double.valueOf(defValue);
     }
 
-
-    protected void initHelperPanel() {
-        distancesTable = new RangeTable();
-        locationsTable = new LocationsTable();
+    protected void initHelperPanel(final DataList data) {
 
-        Config config = Config.getInstance();
-        String url    = config.getServerUrl();
-        String river  = getRiverName();
+        final DistancePanelInputHelper helper = new DistancePanelInputHelper(this.MSG, this.helperContainer, this.getRiverName());
 
-        distancesTable.setAutoFetchData(true);
-        locationsTable.setAutoFetchData(true);
-        distancesTable.setDataSource(new DistanceInfoDataSource(
-            url, river, "distances"));
-        locationsTable.setDataSource(new DistanceInfoDataSource(
-            url, river, "locations"));
-
-        distancesTable.addRecordClickHandler(new RecordClickHandler() {
+        helper.getDistancesTable().addRecordClickHandler(new RecordClickHandler() {
             @Override
-            public void onRecordClick(RecordClickEvent e) {
-                Record r = e.getRecord();
-
-                String from = r.getAttribute("from");
-                String to   = r.getAttribute("to");
+            public void onRecordClick(final RecordClickEvent e) {
+                final Record r = e.getRecord();
 
-                try {
-                    distancePanel.setFrom(Double.valueOf(from));
-                    distancePanel.setTo(Double.valueOf(to));
-                }
-                catch (NumberFormatException nfe) {
-                    SC.warn(MSG.wrongFormat());
-                }
-            }
-        });
-
-        locationsTable.addRecordClickHandler(new RecordClickHandler() {
-            @Override
-            public void onRecordClick(RecordClickEvent e) {
-                Record  r = e.getRecord();
-                int field = e.getFieldNum();
+                final String from = r.getAttribute("from");
+                final String to = r.getAttribute("to");
 
                 try {
-                    String value = r.getAttribute("from");
-
-                    switch (field) {
-                    case 0:
-                        distancePanel.setFrom(Double.valueOf(value));
-                        break;
-                    case 1:
-                        distancePanel.setTo(Double.valueOf(value));
-                        break;
-                    }
-                }
-                catch (NumberFormatException nfe) {
-                    SC.warn(MSG.wrongFormat());
+                    DistancePanel.this.distancePanel.setFrom(Double.valueOf(from));
+                    DistancePanel.this.distancePanel.setTo(Double.valueOf(to));
                 }
-            }
-        });
-
-        tabs = new TabSet();
-        tabs.setWidth100();
-        tabs.setHeight100();
-
-        Tab locations = new Tab(MSG.locations());
-        Tab distances = new Tab(MSG.distance());
-
-        locations.setPane(locationsTable);
-        distances.setPane(distancesTable);
-
-        tabs.addTab(locations, 0);
-        tabs.addTab(distances, 1);
-
-        filterResultCount = new StaticTextItem(MSG.resultCount());
-        filterResultCount.setTitleAlign(Alignment.LEFT);
-        filterResultCount.setTitleStyle("color: #000");
-
-        filterDescription = new TableFilter();
-        filterDescription.setHeight("30px");
-        filterDescription.addFilterHandler(this);
-
-        filterRange = new RangeTableFilter();
-        filterRange.setHeight("30px");
-        filterRange.addFilterHandler(this);
-        filterRange.setVisible(false);
-
-        SelectItem filterCriteria = new SelectItem();
-        filterCriteria.setShowTitle(false);
-        filterCriteria.setWidth(100);
-        filterCriteria.addChangedHandler(new ChangedHandler() {
-            @Override
-            public void onChanged(ChangedEvent e) {
-                if(e.getValue().toString().equals("range")) {
-                    filterRange.setVisible(true);
-                    filterDescription.setVisible(false);
-                    filterDescription.clear();
-                }
-                else {
-                    filterRange.setVisible(false);
-                    filterRange.clear();
-                    filterDescription.setVisible(true);
+                catch (final NumberFormatException nfe) {
+                    SC.warn(DistancePanel.this.MSG.wrongFormat());
                 }
             }
         });
 
-        LinkedHashMap<String, String> filterMap =
-            new LinkedHashMap<String, String>();
-        filterMap.put("description", MSG.description());
-        filterMap.put("range", MSG.range());
-        filterCriteria.setValueMap(filterMap);
-        filterCriteria.setValue("description");
-
-        DynamicForm form = new DynamicForm();
-        form.setFields(filterCriteria);
-
-        DynamicForm form2 = new DynamicForm();
-        form2.setFields(filterResultCount);
+        helper.getLocationsTable().addRecordClickHandler(new RecordClickHandler() {
+            @Override
+            public void onRecordClick(final RecordClickEvent e) {
+                final Record r = e.getRecord();
+                final int field = e.getFieldNum();
 
-        HLayout filterLayout = new HLayout();
-        filterLayout.addMember(form);
-        filterLayout.addMember(filterDescription);
-        filterLayout.addMember(filterRange);
-        filterLayout.setHeight(30);
-        tabs.addTabSelectedHandler(new TabSelectedHandler() {
-            @Override
-            public void onTabSelected(TabSelectedEvent evt) {
-                filterDescription.clear();
-                filterRange.clear();
-                filterResultCount.setValue("");
+                try {
+                    final String value = r.getAttribute("from");
 
-                Canvas c = evt.getTabPane();
-                if(c instanceof ListGrid) {
-                    currentFiltered = (ListGrid)c;
+                    switch (field) {
+                    case 0:
+                        DistancePanel.this.distancePanel.setFrom(Double.valueOf(value));
+                        break;
+                    case 1:
+                        DistancePanel.this.distancePanel.setTo(Double.valueOf(value));
+                        break;
+                    }
+                }
+                catch (final NumberFormatException nfe) {
+                    SC.warn(DistancePanel.this.MSG.wrongFormat());
                 }
             }
         });
 
-        helperContainer.addMember(tabs);
-        helperContainer.addMember(filterLayout);
-        helperContainer.addMember(form2);
     }
 
-
-    @Override
-    public void onFilterCriteriaChanged(StringFilterEvent event) {
-        String search = event.getFilter();
-
-        if (search != null && search.length() > 0) {
-            Criteria c = new Criteria("description", search);
-            locationsTable.filterData(c);
-            distancesTable.filterData(c);
-            filterResultCount.setValue(currentFiltered.getRecords().length);
-        }
-        else {
-            locationsTable.clearCriteria();
-            distancesTable.clearCriteria();
-            filterResultCount.setValue("");
-        }
-    }
-
-
     @Override
-    public void onFilterCriteriaChanged(RangeFilterEvent event) {
-        Float from = event.getFrom() - 0.001f;
-        Float to = event.getTo() + 0.001f;
-
-        Criterion combinedFilter = null;
-        Criterion locationFilter = null;
-
-        if (from.equals(Float.NaN) && to.equals(Float.NaN)) {
-            locationsTable.clearCriteria();
-            distancesTable.clearCriteria();
-            filterResultCount.setValue("");
-            return;
-        }
-
-        if (from.equals(Float.NaN)) {
-            combinedFilter =
-                new Criterion("to", OperatorId.LESS_OR_EQUAL, to);
-
-            locationFilter =
-                new Criterion("from", OperatorId.LESS_OR_EQUAL, to);
-
-            locationsTable.filterData(locationFilter);
-            distancesTable.filterData(combinedFilter);
-            filterResultCount.setValue(currentFiltered.getRecords().length);
-            return;
-        }
-
-        if (to.equals(Float.NaN)) {
-            combinedFilter =
-                new Criterion("from", OperatorId.GREATER_OR_EQUAL, from);
-        }
-        else {
-            AdvancedCriteria c1 =
-                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
-                    new Criterion("from", OperatorId.GREATER_OR_EQUAL, from),
-                    new Criterion("from", OperatorId.LESS_OR_EQUAL, to)
-                });
-
-            AdvancedCriteria c2 =
-                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
-                    new Criterion("to", OperatorId.GREATER_OR_EQUAL, from),
-                    new Criterion("to", OperatorId.LESS_OR_EQUAL, to)
-                });
-
-            AdvancedCriteria c3 =
-                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
-                    new Criterion("from", OperatorId.LESS_OR_EQUAL, to),
-                    new Criterion("to", OperatorId.GREATER_OR_EQUAL, from)
-                });
-
-            combinedFilter =
-                new AdvancedCriteria(OperatorId.OR, new Criterion[] {
-                    c1, c2, c3
-                });
-        }
-        locationsTable.filterData(combinedFilter);
-        distancesTable.filterData(combinedFilter);
-        filterResultCount.setValue(currentFiltered.getRecords().length);
-
-    }
-
-
-    protected String getRiverName() {
-        ArtifactDescription adescr = artifact.getArtifactDescription();
-        return adescr.getRiver();
+    public void onBlur(final BlurEvent event) {
+        this.distancePanel.validateForm();
     }
 }
 // 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/DistancePanelInputHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,229 @@
+/* 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.client.client.ui;
+
+import java.util.LinkedHashMap;
+
+import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.event.FilterHandler;
+import org.dive4elements.river.client.client.event.RangeFilterEvent;
+import org.dive4elements.river.client.client.event.StringFilterEvent;
+import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource;
+import org.dive4elements.river.client.client.ui.range.LocationsTable;
+import org.dive4elements.river.client.client.ui.range.RangeTable;
+
+import com.smartgwt.client.data.AdvancedCriteria;
+import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.data.Criterion;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.types.OperatorId;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.StaticTextItem;
+import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.Tab;
+import com.smartgwt.client.widgets.tab.TabSet;
+import com.smartgwt.client.widgets.tab.events.TabSelectedEvent;
+import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
+
+/** Panel to allow input of distance for calculation range. */
+public class DistancePanelInputHelper implements FilterHandler {
+
+    private RangeTable distancesTable;
+    private LocationsTable locationsTable;
+    private TabSet tabs;
+    private StaticTextItem filterResultCount;
+    private TableFilter filterDescription;
+    private RangeTableFilter filterRange;
+    private ListGrid currentFiltered;
+    protected final VLayout helperContainer;
+    private final FLYSConstants MSG;
+    private final String river;
+
+    public DistancePanelInputHelper(final FLYSConstants MSG, final VLayout helperContainer, final String river) {
+        this.MSG = MSG;
+        this.helperContainer = helperContainer;
+        this.river = river;
+
+        initHelperPanel(); // copy from DistancePanel
+    }
+
+    protected void initHelperPanel() {
+        this.distancesTable = new RangeTable();
+        this.locationsTable = new LocationsTable();
+
+        final Config config = Config.getInstance();
+        final String url = config.getServerUrl();
+        // final String river = getRiverName();
+
+        this.distancesTable.setAutoFetchData(true);
+        this.locationsTable.setAutoFetchData(true);
+        this.distancesTable.setDataSource(new DistanceInfoDataSource(url, this.river, "distances"));
+        this.locationsTable.setDataSource(new DistanceInfoDataSource(url, this.river, "locations"));
+
+        // recordClickHandlers were here
+
+        this.tabs = new TabSet();
+        this.tabs.setWidth100();
+        this.tabs.setHeight100();
+
+        final Tab locations = new Tab(this.MSG.locations());
+        final Tab distances = new Tab(this.MSG.distance());
+
+        locations.setPane(this.locationsTable);
+        distances.setPane(this.distancesTable);
+
+        this.tabs.addTab(locations, 0);
+        this.tabs.addTab(distances, 1);
+
+        this.filterResultCount = new StaticTextItem(this.MSG.resultCount());
+        this.filterResultCount.setTitleAlign(Alignment.LEFT);
+        this.filterResultCount.setTitleStyle("color: #000");
+
+        this.filterDescription = new TableFilter();
+        this.filterDescription.setHeight("30px");
+        this.filterDescription.addFilterHandler(this);
+
+        this.filterRange = new RangeTableFilter();
+        this.filterRange.setHeight("30px");
+        this.filterRange.addFilterHandler(this);
+        this.filterRange.setVisible(false);
+
+        final SelectItem filterCriteria = new SelectItem();
+        filterCriteria.setShowTitle(false);
+        filterCriteria.setWidth(100);
+        filterCriteria.addChangedHandler(new ChangedHandler() {
+            @Override
+            public void onChanged(final ChangedEvent e) {
+                if (e.getValue().toString().equals("range")) {
+                    DistancePanelInputHelper.this.filterRange.setVisible(true);
+                    DistancePanelInputHelper.this.filterDescription.setVisible(false);
+                    DistancePanelInputHelper.this.filterDescription.clear();
+                } else {
+                    DistancePanelInputHelper.this.filterRange.setVisible(false);
+                    DistancePanelInputHelper.this.filterRange.clear();
+                    DistancePanelInputHelper.this.filterDescription.setVisible(true);
+                }
+            }
+        });
+
+        final LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
+        filterMap.put("description", this.MSG.description());
+        filterMap.put("range", this.MSG.range());
+        filterCriteria.setValueMap(filterMap);
+        filterCriteria.setValue("description");
+
+        final DynamicForm form = new DynamicForm();
+        form.setFields(filterCriteria);
+
+        final DynamicForm form2 = new DynamicForm();
+        form2.setFields(this.filterResultCount);
+
+        final HLayout filterLayout = new HLayout();
+        filterLayout.addMember(form);
+        filterLayout.addMember(this.filterDescription);
+        filterLayout.addMember(this.filterRange);
+        filterLayout.setHeight(30);
+        this.tabs.addTabSelectedHandler(new TabSelectedHandler() {
+            @Override
+            public void onTabSelected(final TabSelectedEvent evt) {
+                DistancePanelInputHelper.this.filterDescription.clear();
+                DistancePanelInputHelper.this.filterRange.clear();
+                DistancePanelInputHelper.this.filterResultCount.setValue("");
+
+                final Canvas c = evt.getTabPane();
+                if (c instanceof ListGrid) {
+                    DistancePanelInputHelper.this.currentFiltered = (ListGrid) c;
+                }
+            }
+        });
+
+        this.helperContainer.addMember(this.tabs);
+        this.helperContainer.addMember(filterLayout);
+        this.helperContainer.addMember(form2);
+    }
+
+    @Override
+    public void onFilterCriteriaChanged(final StringFilterEvent event) {
+        final String search = event.getFilter();
+
+        if (search != null && search.length() > 0) {
+            final Criteria c = new Criteria("description", search);
+            this.locationsTable.filterData(c);
+            this.distancesTable.filterData(c);
+            this.filterResultCount.setValue(this.currentFiltered.getRecords().length);
+        } else {
+            this.locationsTable.clearCriteria();
+            this.distancesTable.clearCriteria();
+            this.filterResultCount.setValue("");
+        }
+    }
+
+    @Override
+    public void onFilterCriteriaChanged(final RangeFilterEvent event) {
+        final Float from = event.getFrom() - 0.001f;
+        final Float to = event.getTo() + 0.001f;
+
+        Criterion combinedFilter = null;
+        Criterion locationFilter = null;
+
+        if (from.equals(Float.NaN) && to.equals(Float.NaN)) {
+            this.locationsTable.clearCriteria();
+            this.distancesTable.clearCriteria();
+            this.filterResultCount.setValue("");
+            return;
+        }
+
+        if (from.equals(Float.NaN)) {
+            combinedFilter = new Criterion("to", OperatorId.LESS_OR_EQUAL, to);
+
+            locationFilter = new Criterion("from", OperatorId.LESS_OR_EQUAL, to);
+
+            this.locationsTable.filterData(locationFilter);
+            this.distancesTable.filterData(combinedFilter);
+            this.filterResultCount.setValue(this.currentFiltered.getRecords().length);
+            return;
+        }
+
+        if (to.equals(Float.NaN)) {
+            combinedFilter = new Criterion("from", OperatorId.GREATER_OR_EQUAL, from);
+        } else {
+            final AdvancedCriteria c1 = new AdvancedCriteria(OperatorId.AND,
+                    new Criterion[] { new Criterion("from", OperatorId.GREATER_OR_EQUAL, from), new Criterion("from", OperatorId.LESS_OR_EQUAL, to) });
+
+            final AdvancedCriteria c2 = new AdvancedCriteria(OperatorId.AND,
+                    new Criterion[] { new Criterion("to", OperatorId.GREATER_OR_EQUAL, from), new Criterion("to", OperatorId.LESS_OR_EQUAL, to) });
+
+            final AdvancedCriteria c3 = new AdvancedCriteria(OperatorId.AND,
+                    new Criterion[] { new Criterion("from", OperatorId.LESS_OR_EQUAL, to), new Criterion("to", OperatorId.GREATER_OR_EQUAL, from) });
+
+            combinedFilter = new AdvancedCriteria(OperatorId.OR, new Criterion[] { c1, c2, c3 });
+        }
+        this.locationsTable.filterData(combinedFilter);
+        this.distancesTable.filterData(combinedFilter);
+        this.filterResultCount.setValue(this.currentFiltered.getRecords().length);
+
+    }
+
+    public ListGrid getDistancesTable() {
+        return this.distancesTable;
+    }
+
+    public ListGrid getLocationsTable() {
+        return this.locationsTable;
+    }
+
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ExportPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ExportPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,22 +8,25 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.MissingResourceException;
 
-import com.google.gwt.core.client.GWT;
-
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
-
+import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.FLYSConstants;
 import org.dive4elements.river.client.shared.model.Collection;
 import org.dive4elements.river.client.shared.model.ExportMode;
 import org.dive4elements.river.client.shared.model.Facet;
-import org.dive4elements.river.client.client.Config;
-import org.dive4elements.river.client.client.FLYSConstants;
 
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.TextAreaItem;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
 
 /**
  * A panel that displays an download icon for all available export modes of a
@@ -33,34 +36,82 @@
  */
 public class ExportPanel extends VLayout {
 
-    /** The message class that provides i18n strings.*/
+    private static final String LABEL_URL_SEPARATOR = ";";// always sync with server (InundationDurationState)
+    /** The message class that provides i18n strings. */
     protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
 
-    protected Collection       c;
+    protected Collection c;
     protected List<ExportMode> exports;
 
-    /** This layout will store a list of available export types.*/
+    /** This layout will store a list of available export types. */
     protected HLayout container;
 
-
-    public ExportPanel(Collection c, List<ExportMode> exports) {
+    public ExportPanel(final Collection c, final List<ExportMode> exports) {
         super();
 
-        this.c         = c;
-        this.exports   = exports;
+        this.c = c;
+        this.exports = exports;
         this.container = new HLayout();
 
-        Label title = new Label(MSG.dataexport());
+        final Label title = new Label(this.MSG.dataexport());
         title.setHeight(15);
         title.setStyleName("fontNormalSmallUnderlined");
 
         addMember(title);
         addMember(createExportItems());
-
+        addMember(createVlayoutExportItems());
         setHeight(45);
         setMembersMargin(5);
     }
 
+    private VLayout createVlayoutExportItems() {
+        final VLayout layout = new VLayout();
+        final DynamicForm form1 = new DynamicForm();
+        form1.setColWidths("10%");
+        form1.setWidth(400);
+        form1.setAlign(Alignment.LEFT);
+        final List<FormItem> items = new ArrayList<FormItem>();
+        for (final ExportMode mode : this.exports) {
+            final String name = mode.getName();
+            final List<Facet> facets = mode.getFacets();
+
+            for (int i = 0; i < facets.size(); i++) {
+                final Facet facet = facets.get(i);
+                final String facetName = facet.getName();
+
+                if (!facetName.equals("wms_url"))
+                    continue;
+                if ("wms_url".equals(facetName))
+                    items.add(createUrlLine(facet.getDescription(), i));
+            }
+        }
+        form1.setFields(items.toArray(new FormItem[items.size()]));
+        layout.addMember(form1);
+        return layout;
+    }
+
+    private FormItem createUrlLine(final String labelAndUrl, final int count) {
+
+        final String[] labelAndurlSplit = labelAndUrl.split(LABEL_URL_SEPARATOR);
+        if (labelAndurlSplit.length == 2) {
+
+            final TextAreaItem item = new TextAreaItem();
+            item.setTitle(labelAndurlSplit[0]);
+
+            item.setWrapTitle(true);
+            item.setTitleColSpan(3);
+            item.setColSpan(7);
+            item.setWidth(250);
+            item.setHeight(48);
+            item.setTitleAlign(Alignment.LEFT);
+
+            item.setValue(labelAndurlSplit[1]);
+            item.setCanEdit(false);
+
+            return item;
+        }
+        return null;
+    }
 
     /**
      * This method is used to create an item (created by createExportButton) for
@@ -69,84 +120,80 @@
      * @return a horizontal list of buttons.
      */
     protected HLayout createExportItems() {
-        HLayout layout = new HLayout();
+        final HLayout layout = new HLayout();
 
-        for (ExportMode mode: exports) {
-            String      name   = mode.getName();
-            List<Facet> facets = mode.getFacets();
+        for (final ExportMode mode : this.exports) {
+            final String name = mode.getName();
+            final List<Facet> facets = mode.getFacets();
 
-            for (Facet facet: facets) {
-                if (name.equals("fix_wq_curve_at_export")) {
+            for (final Facet facet : facets) {
+                final String facetName = facet.getName();
+
+                if (name.equals("fix_wq_curve_at_export"))
                     continue;
-                }
+
                 String filename = name;
-                if (name.equals("computed_dischargecurve_at_export")) {
+                if (name.equals("computed_dischargecurve_at_export"))
                     filename = "dischargecurve";
-                }
-                layout.addMember(createExportButton(
-                    name,
-                    facet.getName(),
-                    filename));
+
+                if ("wms_url".equals(facetName))
+                    continue;
+
+                layout.addMember(createExportButton(name, facetName, filename));
             }
         }
 
         return layout;
     }
 
-
     /**
      * This method is used to create a button (with click handler) for a
      * concrete export mode / type.
      *
-     * @param name The name of the export.
-     * @param facet The name of the export type (e.g. CSV, WST).
+     * @param name
+     *            The name of the export.
+     * @param facet
+     *            The name of the export type (e.g. CSV, WST).
      *
      * @return an image with click handler.
      */
-    protected Canvas createExportButton(
-        String name,
-        String facet,
-        String filename
-    ) {
-        String url  = getExportUrl(name, facet, filename);
+    protected Canvas createExportButton(final String name, final String facet, final String filename) {
+        String url = getExportUrl(name, facet, filename);
         String imgUrl = GWT.getHostPageBaseURL();
         if (facet.equals("pdf")) {
-            imgUrl += MSG.downloadPDF();
-        }
-        else if (facet.equals("at")) {
-            imgUrl += MSG.downloadAT();
-        }
-        else if (facet.equals("wst")) {
-            imgUrl += MSG.downloadWST();
+            imgUrl += this.MSG.downloadPDF();
+        } else if (facet.equals("at")) {
+            imgUrl += this.MSG.downloadAT();
+        } else if (facet.equals("wst")) {
+            imgUrl += this.MSG.downloadWST();
+        } else if (facet.equals("csv")) {
+            url += "&encoding=UTF-8";
+            imgUrl += this.MSG.downloadCSV();
+        } else {
+            imgUrl += this.MSG.imageSave();
         }
-        else  if (facet.equals("csv")) {
-            url += "&encoding=windows-1252";
-            imgUrl += MSG.downloadCSV();
-        }
-        else {
-            imgUrl += MSG.imageSave();
-        }
-        ImgLink link = new ImgLink(imgUrl, url, 30, 30);
+        final ImgLink link = new ImgLink(imgUrl, url, 30, 30);
         link.setTooltip(getTooltipText(name, facet));
 
         return link;
     }
 
-
     /**
      * Creates the URL used to trigger an export.
      *
-     * @param name The name of the export.
-     * @param facet The name of the export type (e.g. CSV, WST).
+     * @param name
+     *            The name of the export.
+     * @param facet
+     *            The name of the export type (e.g. CSV, WST).
      *
      * @return the export URL.
      */
-    protected String getExportUrl(String name, String facet, String filename) {
-        Config config = Config.getInstance();
+    protected String getExportUrl(final String name, final String facet, final String filename) {
+        final Config config = Config.getInstance();
 
         String url = GWT.getModuleBaseURL();
         url += "export";
-        url += "?uuid=" + c.identifier();
+        url += "?uuid=" + this.c.identifier();
         url += "&name=" + filename;
         url += "&mode=" + name;
         url += "&type=" + facet;
@@ -156,20 +203,21 @@
         return url;
     }
 
-
     /**
      * Creates a text used as tooltip for a specific export and type.
      *
-     * @param name The name of the export.
-     * @param facet The name of the export type (e.g. CSV, WST).
+     * @param name
+     *            The name of the export.
+     * @param facet
+     *            The name of the export type (e.g. CSV, WST).
      *
      * @return a tooltip text.
      */
-    protected String getTooltipText(String name, String facet) {
+    protected String getTooltipText(final String name, final String facet) {
         try {
-            return MSG.getString(name) + " | " + MSG.getString(facet);
+            return this.MSG.getString(name) + " | " + this.MSG.getString(facet);
         }
-        catch (MissingResourceException mre) {
+        catch (final MissingResourceException mre) {
             return name + " | " + facet;
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/FromToTableHelperPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,210 @@
+/** 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.MultiAttributeData;
+import org.dive4elements.river.client.shared.model.MultiDataItem;
+
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class FromToTableHelperPanel {
+
+    public interface IColumnClickHandler {
+        void columnClicked(String value);
+    }
+
+    private enum PinType {
+        none, from, to
+    }
+
+    private final ListGrid table;
+
+    private final DataList dataList;
+
+    private final FLYSConstants flys;
+
+    private final List<String> keyColEntries = new ArrayList<String>();
+
+    public FromToTableHelperPanel(final DataList dataList, final String definitionStr, final FLYSConstants flys, final IColumnClickHandler fromHandler,
+            final IColumnClickHandler toHandler) {
+        this.flys = flys;
+        this.dataList = dataList;
+        this.table = new ListGrid();
+        this.table.setShowHeaderContextMenu(false);
+        this.table.setWidth100();
+        this.table.setShowRecordComponents(true);
+        this.table.setShowRecordComponentsByCell(true);
+        this.table.setHeight100();
+        this.table.setEmptyMessage(flys.empty_table());
+        this.table.setCanReorderFields(false);
+
+        final MultiAttributeData mData = findDefinition(definitionStr);
+        final Map<String, Map<String, String>> meta = mData.getMeta();
+
+        final Map<String, String> tableInfo = meta.get("meta_tableinfo");
+        final String keyColumnName = tableInfo.get("keycol");
+
+        final SortedMap<Integer, ListGridField> fields = new TreeMap<Integer, ListGridField>();
+
+        for (final Entry<String, Map<String, String>> entry : meta.entrySet()) {
+
+            final String colName = entry.getKey();
+            if (colName.startsWith("meta_"))
+                continue;
+
+            final Map<String, String> values = entry.getValue();
+
+            final int order = Integer.parseInt(values.get("order"));
+
+            final ListGridField field = createField(colName, keyColumnName, values, fromHandler, toHandler);
+
+            fields.put(order, field);
+        }
+
+        if (mData == null || mData.opts == null) {
+            this.table.setEmptyMessage(flys.error_feed_no_data());
+            return;
+        }
+
+        for (final DataItem dataItem : mData.opts) {
+            final MultiDataItem item = (MultiDataItem) dataItem;
+
+            final Map<String, String> valueMap = item.getValue();
+
+            final Record newRecord = new Record();
+            for (final Entry<String, String> entry : valueMap.entrySet()) {
+                final String key = entry.getKey();
+                final String value = entry.getValue();
+                newRecord.setAttribute(key, value);
+
+                if (key.equals(keyColumnName))
+                    this.keyColEntries.add(value);
+            }
+
+            this.table.addData(newRecord);
+        }
+        this.table.setEmptyMessage("");
+        this.table.setFields(fields.values().toArray(new ListGridField[fields.size()]));
+    }
+
+    public Canvas getTable() {
+        return this.table;
+    }
+
+    private MultiAttributeData findDefinition(final String paranemterName) {
+
+        for (final Data data : this.dataList.getAll()) {
+
+            final String label = data.getLabel();
+            if (label.equals(paranemterName) && data instanceof MultiAttributeData)
+                return (MultiAttributeData) data;
+        }
+
+        return null;
+    }
+
+    private ListGridField createField(final String colName, final String keyColumnName, final Map<String, String> values, final IColumnClickHandler fromHandler,
+            final IColumnClickHandler toHandler) {
+
+        final String translation = getMeta(values, "translation", colName);
+
+        final ListGridField field = new ListGridField(colName, translation);
+
+        final String width = getMeta(values, "colwidth", "99");
+        field.setWidth(width);
+
+        final ListGridFieldType type = getMeta(values, "type", ListGridFieldType.TEXT, ListGridFieldType.class);
+        field.setType(type);
+
+        final Alignment alignment = getMeta(values, "alignment", Alignment.LEFT, Alignment.class);
+        field.setAlign(alignment);
+
+        final PinType pinType = getMeta(values, "pin", PinType.none, PinType.class);
+        switch (pinType) {
+        case from: {
+            makePin(keyColumnName, fromHandler, field, this.flys.markerGreen());
+        }
+            break;
+
+        case to: {
+            makePin(keyColumnName, toHandler, field, this.flys.markerRed());
+        }
+            break;
+        case none:
+        default:
+            break;
+        }
+
+        return field;
+    }
+
+    private void makePin(final String keyColumnName, final IColumnClickHandler handler, final ListGridField field, final String markerStr) {
+        final String baseUrl = GWT.getHostPageBaseURL();
+        field.setCellIcon(baseUrl + markerStr);
+        field.addRecordClickHandler(new RecordClickHandler() {
+            @Override
+            public void onRecordClick(final RecordClickEvent e) {
+                final Record r = e.getRecord();
+                handler.columnClicked(r.getAttribute(keyColumnName));
+            }
+        });
+    }
+
+    private String getMeta(final Map<String, String> values, final String key, final String defaultValue) {
+
+        final String value = values.get(key);
+        if (value == null || value.isEmpty())
+            return defaultValue;
+
+        return value;
+    }
+
+    private <TYPE extends Enum<TYPE>> TYPE getMeta(final Map<String, String> values, final String key, final TYPE defaultValue, final Class<TYPE> enumType) {
+
+        final String value = values.get(key);
+        if (value == null || value.isEmpty())
+            return defaultValue;
+
+        try {
+            return Enum.valueOf(enumType, value);
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+            return defaultValue;
+        }
+    }
+
+    public List<String> getKeycolEntries() {
+        return this.keyColEntries;
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/HWSDatacagePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/HWSDatacagePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,13 +8,8 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Label;
-
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.dive4elements.river.client.shared.model.Data;
 import org.dive4elements.river.client.shared.model.DataItem;
@@ -23,70 +18,48 @@
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 import org.dive4elements.river.client.shared.model.User;
 
-import java.util.ArrayList;
-import java.util.List;
-
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
 
-public class HWSDatacagePanel
-extends DatacagePanel
-{
-    public static final String OUT        = "floodmap_hws_panel";
-    public static final String PARAMETERS = "hws:true;load-system:true";
-
+public class HWSDatacagePanel extends DatacagePanel {
 
-    public HWSDatacagePanel() {
-        super();
-    }
+    private static final long serialVersionUID = 1L;
 
+    private static final String OUT = "floodmap_hws_panel";
 
-    public HWSDatacagePanel(User user) {
-        super(user);
+    private static final String PARAMETERS = "hws:true;load-system:true";
+
+    public HWSDatacagePanel(final User user) {
+        super(user, OUT, PARAMETERS, true);
     }
 
-
-    @Override
-    protected void createWidget() {
-        super.createWidget();
-        widget.setIsMutliSelectable(true);
-    }
-
-
-    @Override
-    public String getOuts() {
-        return OUT;
-    }
-
-
-    @Override
-    public String getParameters() {
-        return PARAMETERS;
-    }
-
-
     @Override
     public List<String> validate() {
-        List<String> errors = new ArrayList<String>();
+        final List<String> errors = new ArrayList<String>();
 
         return errors;
     }
 
     @Override
-    public Canvas createOld(DataList dataList) {
+    public Canvas createOld(final DataList dataList) {
         GWT.log("old datacage##########################################");
-        HLayout layout  = new HLayout();
-        VLayout vLayout = new VLayout();
+        final HLayout layout = new HLayout();
+        final VLayout vLayout = new VLayout();
         layout.setWidth("400px");
 
-        Label label = new Label(dataList.getLabel());
+        final Label label = new Label(dataList.getLabel());
         label.setWidth("200px");
 
-        int size = dataList.size();
+        final int size = dataList.size();
         for (int i = 0; i < size; i++) {
-            Data data        = dataList.get(i);
-            DataItem[] items = data.getItems();
+            final Data data = dataList.get(i);
+            final DataItem[] items = data.getItems();
 
-            for (DataItem item: items) {
-                HLayout hLayout = new HLayout();
+            for (final DataItem item : items) {
+                final HLayout hLayout = new HLayout();
 
                 hLayout.addMember(label);
                 hLayout.addMember(new Label(item.getLabel()));
@@ -96,7 +69,7 @@
             }
         }
 
-        Canvas back = getBackButton(dataList.getState());
+        final Canvas back = getBackButton(dataList.getState());
 
         layout.addMember(label);
         layout.addMember(vLayout);
@@ -105,19 +78,17 @@
         return layout;
     }
 
-
     @Override
     protected Data[] getData() {
-        String[] selection = this.widget.getSelectionTitles();
+        final String[] selection = getSelectionTitles();
         String result = "";
         boolean first = true;
         if (selection != null) {
-            for (String record: selection) {
+            for (final String record : selection) {
                 if (first) {
                     result += record;
                     first = false;
-                }
-                else {
+                } else {
                     result += ";" + record;
                 }
             }
@@ -125,13 +96,10 @@
         if (result.length() == 0) {
             result = MSG.notselected();
         }
-        Data[] data = new Data[1];
-        DataItem item = new DefaultDataItem(
-                "uesk.hws", "uesk.hws", result);
-        data[0] = new DefaultData(
-            "uesk.hws", null, null, new DataItem[] {item});
+        final Data[] data = new Data[1];
+        final DataItem item = new DefaultDataItem("uesk.hws", "uesk.hws", result);
+        data[0] = new DefaultData("uesk.hws", null, null, new DataItem[] { item });
 
         return data;
     }
-}
-// 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/ui/LocationDistancePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/LocationDistancePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,9 +8,28 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.event.FilterHandler;
+import org.dive4elements.river.client.client.event.RangeFilterEvent;
+import org.dive4elements.river.client.client.event.StringFilterEvent;
+import org.dive4elements.river.client.client.services.DistanceInfoService;
+import org.dive4elements.river.client.client.services.DistanceInfoServiceAsync;
+import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource;
+import org.dive4elements.river.client.shared.model.ArtifactDescription;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.DistanceInfoObject;
+
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.i18n.client.NumberFormat;
-
 import com.smartgwt.client.data.AdvancedCriteria;
 import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.data.Criterion;
@@ -44,88 +63,64 @@
 import com.smartgwt.client.widgets.tab.events.TabSelectedEvent;
 import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
 
-import org.dive4elements.river.client.client.Config;
-import org.dive4elements.river.client.client.FLYSConstants;
-import org.dive4elements.river.client.client.event.FilterHandler;
-import org.dive4elements.river.client.client.event.RangeFilterEvent;
-import org.dive4elements.river.client.client.event.StringFilterEvent;
-import org.dive4elements.river.client.client.services.DistanceInfoService;
-import org.dive4elements.river.client.client.services.DistanceInfoServiceAsync;
-import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource;
-import org.dive4elements.river.client.shared.model.ArtifactDescription;
-import org.dive4elements.river.client.shared.model.Data;
-import org.dive4elements.river.client.shared.model.DataItem;
-import org.dive4elements.river.client.shared.model.DataList;
-import org.dive4elements.river.client.shared.model.DefaultData;
-import org.dive4elements.river.client.shared.model.DefaultDataItem;
-import org.dive4elements.river.client.shared.model.DistanceInfoObject;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-
-
 /**
  * This UIProvider creates a widget to enter locations or a distance.
  *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class LocationDistancePanel
-extends      AbstractUIProvider
-implements   ChangeHandler, BlurHandler, FilterHandler
-{
+public class LocationDistancePanel extends AbstractUIProvider implements ChangeHandler, BlurHandler, FilterHandler {
     private static final long serialVersionUID = -10820092176039372L;
 
     /** The message class that provides i18n strings. */
     protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
 
     /** The DistanceInfoService used to retrieve locations about rivers. */
-    protected DistanceInfoServiceAsync distanceInfoService =
-        GWT.create(DistanceInfoService.class);
+    protected DistanceInfoServiceAsync distanceInfoService = GWT.create(DistanceInfoService.class);
 
     public static final String FIELD_MODE = "mode";
 
-    /** The constant name of the input field to enter the start of a distance.*/
+    /** The constant name of the input field to enter the start of a distance. */
     public static final String FIELD_FROM = "from";
 
-    /** The constant name of the input field to enter the end of a distance.*/
+    /** The constant name of the input field to enter the end of a distance. */
     public static final String FIELD_TO = "to";
 
-    /** The constant name of the input field to enter locations.*/
+    /** The constant name of the input field to enter locations. */
     public static final String FIELD_VALUE_LOCATION = "location";
 
-    /** The constant name of the input field to enter distance.*/
+    /** The constant name of the input field to enter distance. */
     public static final String FIELD_VALUE_DISTANCE = "distance";
 
-    /** The constant name of the input field to enter the step width of a
-     * distance.*/
+    /**
+     * The constant name of the input field to enter the step width of a
+     * distance.
+     */
     public static final String FIELD_WIDTH = "width";
 
     public static final int WIDTH = 250;
 
-
-    /** The radio group for input mode selection.*/
+    /** The radio group for input mode selection. */
     protected DynamicForm mode;
 
-    /** A container that will contain the location or the distance panel.*/
+    /** A container that will contain the location or the distance panel. */
     protected HLayout container;
 
-    /** The min value for a distance.*/
+    /** The min value for a distance. */
     protected double min;
 
-    /** The max value for a distance.*/
+    /** The max value for a distance. */
     protected double max;
 
-    /** The 'from' value entered in the distance mode.*/
+    /** The 'from' value entered in the distance mode. */
     protected double from;
 
-    /** The 'to' value entered in the distance mode.*/
+    /** The 'to' value entered in the distance mode. */
     protected double to;
 
-    /** The 'step' value entered in the distance mode.*/
+    /** The 'step' value entered in the distance mode. */
     protected double step;
 
-    /** The values entered in the location mode.*/
+    /** The values entered in the location mode. */
     protected double[] values;
 
     /** The input panel for locations. */
@@ -146,7 +141,7 @@
     /** The table data. */
     protected DistanceInfoObject[] tableData;
 
-    /** The table filter.*/
+    /** The table filter. */
     protected TableFilter filterDescription;
     protected RangeTableFilter filterRange;
 
@@ -159,34 +154,34 @@
      * Creates a new LocationDistancePanel instance.
      */
     public LocationDistancePanel() {
-        distanceTable  = new ListGrid();
-        distanceTable.setAutoFetchData(true);
+        this.distanceTable = new ListGrid();
+        this.distanceTable.setAutoFetchData(true);
 
-        locationsTable = new ListGrid();
-        locationsTable.setAutoFetchData(true);
+        this.locationsTable = new ListGrid();
+        this.locationsTable.setAutoFetchData(true);
 
-        distanceTable.setShowHeaderContextMenu(false);
-        locationsTable.setShowHeaderContextMenu(false);
+        this.distanceTable.setShowHeaderContextMenu(false);
+        this.locationsTable.setShowHeaderContextMenu(false);
     }
 
-
     /**
      * This method creates a widget that contains a label, a panel with
      * checkboxes to switch the input mode between location and distance input,
      * and a the mode specific panel.
      *
-     * @param data The data that might be inserted.
+     * @param data
+     *            The data that might be inserted.
      *
      * @return a panel.
      */
     @Override
-    public Canvas create(DataList data) {
-        VLayout layout = new VLayout();
+    public Canvas create(final DataList data) {
+        final VLayout layout = new VLayout();
         layout.setMembersMargin(10);
 
-        Label label   = new Label(MESSAGES.location_distance_state());
-        Canvas widget = createWidget(data);
-        Canvas submit = getNextButton();
+        final Label label = getLabel(data);// new Label(MESSAGES.location_distance_state());
+        final Canvas widget = createWidget(data);
+        final Canvas submit = getNextButton();
         createDistanceInputPanel();
 
         initDefaults(data);
@@ -201,6 +196,12 @@
         return layout;
     }
 
+    protected Label getLabel(final DataList data) {
+        final Data item = data.get(0);
+        return new Label(item.getDescription());//
+        // TODO: migrate distance_part_state to server
+        // item.getDescription()); // holt das Label vom Server (funktoniert schon sehr oft so!)
+    }
 
     /**
      * Setup a table for a DistanceInfoDataSource.
@@ -210,68 +211,67 @@
      * Depending on the value of isDistance the table will
      * have a to and a from column or a single location column.
      *
-     * @param table the ListGrid to set up.
-     * @param doublePins wether or not to have.
-     * @param isDistance wether or not to and from should be included.
+     * @param table
+     *            the ListGrid to set up.
+     * @param doublePins
+     *            wether or not to have.
+     * @param isDistance
+     *            wether or not to and from should be included.
      */
-    protected void setupDistanceInfoTable(ListGrid table,
-                                          boolean doublePins,
-                                          boolean isDistance) {
+    protected void setupDistanceInfoTable(final ListGrid table, final boolean doublePins, final boolean isDistance) {
 
-        String baseUrl = GWT.getHostPageBaseURL();
+        final String baseUrl = GWT.getHostPageBaseURL();
 
         table.setWidth100();
         table.setShowRecordComponents(true);
         table.setShowRecordComponentsByCell(true);
         table.setHeight100();
-        table.setEmptyMessage(MESSAGES.empty_filter());
+        table.setEmptyMessage(this.MESSAGES.empty_filter());
         table.setCanReorderFields(false);
 
-        CellFormatter cf = new CellFormatter() {
+        final CellFormatter cf = new CellFormatter() {
             @Override
-            public String format(
-                Object value,
-                ListGridRecord record,
-                int rowNum, int colNum) {
-                    if (value == null) return null;
-                    try {
-                        NumberFormat nf;
-                        double v = Double.parseDouble((String)value);
-                        nf = NumberFormat.getFormat("###0.00##");
-                        return nf.format(v);
-                    }
-                    catch (Exception e) {
-                        return value.toString();
-                    }
+            public String format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) {
+                if (value == null)
+                    return null;
+                try {
+                    NumberFormat nf;
+                    final double v = Double.parseDouble((String) value);
+                    nf = NumberFormat.getFormat("###0.00##");
+                    return nf.format(v);
+                }
+                catch (final Exception e) {
+                    return value.toString();
+                }
             }
         };
         ListGridField pin1 = null;
         ListGridField pin2 = null;
 
         if (doublePins) {
-            pin1 = new ListGridField ("fromIcon", MESSAGES.from());
-            pin1.setWidth (30);
+            pin1 = new ListGridField("fromIcon", this.MESSAGES.from());
+            pin1.setWidth(30);
         } else {
-            pin1 = new ListGridField ("fromIcon", MESSAGES.selection());
-            pin1.setWidth (60);
+            pin1 = new ListGridField("fromIcon", this.MESSAGES.selection());
+            pin1.setWidth(60);
         }
-        pin1.setType (ListGridFieldType.ICON);
-        pin1.setCellIcon(baseUrl + MESSAGES.markerGreen());
+        pin1.setType(ListGridFieldType.ICON);
+        pin1.setCellIcon(baseUrl + this.MESSAGES.markerGreen());
 
         if (doublePins) {
-            pin2 = new ListGridField ("toIcon", MESSAGES.to());
-            pin2.setType (ListGridFieldType.ICON);
-            pin2.setWidth (30);
-            pin2.setCellIcon(baseUrl + MESSAGES.markerRed());
+            pin2 = new ListGridField("toIcon", this.MESSAGES.to());
+            pin2.setType(ListGridFieldType.ICON);
+            pin2.setWidth(30);
+            pin2.setCellIcon(baseUrl + this.MESSAGES.markerRed());
         }
 
         if (isDistance) {
             /* We have from / to fields */
-            pin1.addRecordClickHandler (new RecordClickHandler () {
+            pin1.addRecordClickHandler(new RecordClickHandler() {
                 @Override
-                public void onRecordClick (RecordClickEvent e) {
-                    Record r = e.getRecord();
-                    if (!isLocationMode ()) {
+                public void onRecordClick(final RecordClickEvent e) {
+                    final Record r = e.getRecord();
+                    if (!isLocationMode()) {
                         /* distance panel and distance mode */
                         setFrom(r.getAttribute("from"));
                         setTo(r.getAttribute("to"));
@@ -283,15 +283,17 @@
                 }
             });
             if (doublePins) {
-                pin2.addRecordClickHandler (new RecordClickHandler () {
+                pin2.addRecordClickHandler(new RecordClickHandler() {
                     @Override
-                    public void onRecordClick (RecordClickEvent e) {
-                        Record r = e.getRecord();
-                        if (isLocationMode ()) {
+                    public void onRecordClick(final RecordClickEvent e) {
+                        final Record r = e.getRecord();
+                        if (isLocationMode()) {
                             appendLocation(r.getAttribute("to"));
                         } else {
-                            /* Distance and double pin behavior is only
-                             * defined for location mode. */
+                            /*
+                             * Distance and double pin behavior is only
+                             * defined for location mode.
+                             */
                             GWT.log("Unhandled input state.");
                         }
                     }
@@ -299,11 +301,11 @@
             }
         } else {
             /* We only have the from field */
-            pin1.addRecordClickHandler (new RecordClickHandler () {
+            pin1.addRecordClickHandler(new RecordClickHandler() {
                 @Override
-                public void onRecordClick (RecordClickEvent e) {
-                    Record r = e.getRecord();
-                    if (!isLocationMode ()) {
+                public void onRecordClick(final RecordClickEvent e) {
+                    final Record r = e.getRecord();
+                    if (!isLocationMode()) {
                         /* Location panel and distance mode */
                         setFrom(r.getAttribute("from"));
                     } else {
@@ -313,15 +315,17 @@
                 }
             });
             if (doublePins) {
-                pin2.addRecordClickHandler (new RecordClickHandler () {
+                pin2.addRecordClickHandler(new RecordClickHandler() {
                     @Override
-                    public void onRecordClick (RecordClickEvent e) {
-                        Record r = e.getRecord();
-                        if (!isLocationMode ()) {
+                    public void onRecordClick(final RecordClickEvent e) {
+                        final Record r = e.getRecord();
+                        if (!isLocationMode()) {
                             setTo(r.getAttribute("from"));
                         } else {
-                            /* Distance and double pin behavior is only
-                             * defined for location mode. */
+                            /*
+                             * Distance and double pin behavior is only
+                             * defined for location mode.
+                             */
                             GWT.log("Unhandled input state.");
                         }
                     }
@@ -329,8 +333,7 @@
             }
         }
 
-        ListGridField ddescr = new ListGridField("description",
-                MESSAGES.description());
+        final ListGridField ddescr = new ListGridField("description", this.MESSAGES.description());
         ddescr.setType(ListGridFieldType.TEXT);
         ddescr.setWidth("*");
 
@@ -338,32 +341,29 @@
         ListGridField to = null;
 
         if (isDistance) {
-            from = new ListGridField("from", MESSAGES.from());
-            to = new ListGridField("to", MESSAGES.to());
+            from = new ListGridField("from", this.MESSAGES.from());
+            to = new ListGridField("to", this.MESSAGES.to());
             to.setType(ListGridFieldType.FLOAT);
             to.setCellFormatter(cf);
 
             to.setWidth("12%");
             to.setAlign(Alignment.LEFT);
         } else {
-            from = new ListGridField("from", MESSAGES.locations());
+            from = new ListGridField("from", this.MESSAGES.locations());
         }
         from.setCellFormatter(cf);
         from.setWidth("12%");
 
-        ListGridField dside = new ListGridField("riverside",
-                MESSAGES.riverside());
+        final ListGridField dside = new ListGridField("riverside", this.MESSAGES.riverside());
         dside.setType(ListGridFieldType.TEXT);
         dside.setWidth("12%");
 
-        ListGridField bottom =
-            new ListGridField("bottom", MESSAGES.bottom_edge());
+        final ListGridField bottom = new ListGridField("bottom", this.MESSAGES.bottom_edge());
         bottom.setType(ListGridFieldType.TEXT);
         bottom.setWidth("10%");
         bottom.setCellFormatter(cf);
 
-        ListGridField top =
-            new ListGridField("top", MESSAGES.top_edge());
+        final ListGridField top = new ListGridField("top", this.MESSAGES.top_edge());
         top.setType(ListGridFieldType.TEXT);
         top.setWidth("10%");
         top.setCellFormatter(cf);
@@ -380,31 +380,30 @@
     }
 
     @Override
-    public Canvas createOld(DataList dataList) {
-        List<Data> items = dataList.getAll();
+    public Canvas createOld(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
 
-        Data       dMode  = getData(items, "ld_mode");
-        DataItem[] dItems = dMode.getItems();
+        final Data dMode = getData(items, "ld_mode");
+        final DataItem[] dItems = dMode.getItems();
 
         boolean rangeMode = true;
         if (dItems != null && dItems[0] != null) {
             rangeMode = FIELD_VALUE_DISTANCE.equals(dItems[0].getStringValue());
         }
 
-        HLayout layout = new HLayout();
+        final HLayout layout = new HLayout();
         layout.setWidth("400px");
 
-        Label   label  = new Label(dataList.getLabel());
+        final Label label = new Label(dataList.getLabel());
         label.setWidth("200px");
 
-        Canvas back = getBackButton(dataList.getState());
+        final Canvas back = getBackButton(dataList.getState());
 
         layout.addMember(label);
 
         if (rangeMode) {
             layout.addMember(getOldRangeSelection(dataList));
-        }
-        else {
+        } else {
             layout.addMember(getOldLocationSelection(dataList));
         }
 
@@ -413,124 +412,116 @@
         return layout;
     }
 
-
     /**
      * Creates a label for the selected range.
      *
-     * @param dataList The DataList containing all values for this state.
+     * @param dataList
+     *            The DataList containing all values for this state.
      *
      * @return A label displaying the selected values.
      */
-    protected Label getOldRangeSelection(DataList dataList) {
-        List<Data> items = dataList.getAll();
-
-        Data dFrom = getData(items, "ld_from");
-        Data dTo   = getData(items, "ld_to");
-        Data dStep = getData(items, "ld_step");
+    protected Label getOldRangeSelection(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
 
-        DataItem[] from = dFrom.getItems();
-        DataItem[] to   = dTo.getItems();
-        DataItem[] step = dStep.getItems();
+        final Data dFrom = getData(items, "ld_from");
+        final Data dTo = getData(items, "ld_to");
+        final Data dStep = getData(items, "ld_step");
 
-        StringBuilder sb = new StringBuilder();
+        final DataItem[] from = dFrom.getItems();
+        final DataItem[] to = dTo.getItems();
+        final DataItem[] step = dStep.getItems();
+
+        final StringBuilder sb = new StringBuilder();
         sb.append(from[0].getLabel());
-        sb.append(" " + MESSAGES.unitFrom() + " ");
+        sb.append(" " + this.MESSAGES.unitFrom() + " ");
         sb.append(to[0].getLabel());
-        sb.append(" " + MESSAGES.unitTo() + " ");
+        sb.append(" " + this.MESSAGES.unitTo() + " ");
         sb.append(step[0].getLabel());
-        sb.append(" " + MESSAGES.unitWidth());
+        sb.append(" " + this.MESSAGES.unitWidth());
 
-        Label selected = new Label(sb.toString());
+        final Label selected = new Label(sb.toString());
         selected.setWidth("130px");
 
         return selected;
     }
 
-
     /**
      * Creates a label for the selected locations.
      *
-     * @param dataList The DataList containing all values for this state.
+     * @param dataList
+     *            The DataList containing all values for this state.
      *
      * @return A label displaying the selected values.
      */
-    protected Label getOldLocationSelection(DataList dataList) {
-        List<Data> items = dataList.getAll();
-
-        Data       dLocations = getData(items, "ld_locations");
-        DataItem[] lItems     = dLocations.getItems();
+    protected Label getOldLocationSelection(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
 
-        String[] splitted = lItems[0].getStringValue().split(" ");
+        final Data dLocations = getData(items, "ld_locations");
+        final DataItem[] lItems = dLocations.getItems();
+
+        final String[] splitted = lItems[0].getStringValue().split(" ");
         String value = "";
-        for (int i = 0; i < splitted.length; i++) {
+        for (final String element : splitted) {
             try {
-                NumberFormat nf = NumberFormat.getDecimalFormat();
-                double dv = Double.parseDouble(splitted[i]);
+                final NumberFormat nf = NumberFormat.getDecimalFormat();
+                final double dv = Double.parseDouble(element);
                 value += nf.format(dv) + " ";
             }
-            catch(NumberFormatException nfe) {
-                value += splitted[i] + " ";
+            catch (final NumberFormatException nfe) {
+                value += element + " ";
             }
         }
 
-        Label selected = new Label(value);
+        final Label selected = new Label(value);
         selected.setWidth(130);
 
         return selected;
     }
 
-
     /**
      * This method reads the default values defined in the DataItems of the Data
      * objects in <i>list</i>.
      *
-     * @param list The DataList container that stores the Data objects.
+     * @param list
+     *            The DataList container that stores the Data objects.
      */
-    protected void initDefaults(DataList list) {
-        Data m = getData(list.getAll(), "ld_mode");
-        Data l = getData(list.getAll(), "ld_locations");
-        Data f = getData(list.getAll(), "ld_from");
-        Data t = getData(list.getAll(), "ld_to");
-        Data s = getData(list.getAll(), "ld_step");
-
-        DataItem[] fItems = f.getItems();
-        DataItem[] tItems = t.getItems();
-        DataItem[] sItems = s.getItems();
-
-        min  = Double.valueOf(fItems[0].getStringValue());
-        max  = Double.valueOf(tItems[0].getStringValue());
-        step = Double.valueOf(sItems[0].getStringValue());
+    protected void initDefaults(final DataList list) {
+        final Data m = getData(list.getAll(), "ld_mode");
+        final Data l = getData(list.getAll(), "ld_locations");
+        final Data f = getData(list.getAll(), "ld_from");
+        final Data t = getData(list.getAll(), "ld_to");
+        final Data s = getData(list.getAll(), "ld_step");
 
-        DataItem   mDef   = m.getDefault();
-        DataItem   lDef   = l.getDefault();
-        DataItem   fDef   = f.getDefault();
-        DataItem   tDef   = t.getDefault();
-        DataItem   sDef   = s.getDefault();
-
-        String mDefValue = mDef != null ? mDef.getStringValue() : null;
-        String theMode = mDefValue != null && mDefValue.length() > 0
-            ? mDef.getStringValue()
-            : FIELD_VALUE_DISTANCE;
-
-        mode.setValue(FIELD_MODE, theMode);
+        final DataItem[] fItems = f.getItems();
+        final DataItem[] tItems = t.getItems();
+        final DataItem[] sItems = s.getItems();
 
-        String fDefValue = fDef != null ? fDef.getStringValue() : null;
-        setFrom(fDefValue != null && fDefValue.length() > 0
-            ? Double.valueOf(fDef.getStringValue())
-            : min);
+        this.min = Double.valueOf(fItems[0].getStringValue());
+        this.max = Double.valueOf(tItems[0].getStringValue());
+        this.step = Double.valueOf(sItems[0].getStringValue());
 
-        String tDefValue = tDef != null ? tDef.getStringValue() : null;
-        setTo(tDefValue != null && tDefValue.length() > 0
-            ? Double.valueOf(tDef.getStringValue())
-            : max);
+        final DataItem mDef = m.getDefault();
+        final DataItem lDef = l.getDefault();
+        final DataItem fDef = f.getDefault();
+        final DataItem tDef = t.getDefault();
+        final DataItem sDef = s.getDefault();
 
-        String sDefValue = sDef != null ? sDef.getStringValue() : null;
-        setStep(sDefValue != null && sDefValue.length() > 0
-            ? Double.valueOf(sDef.getStringValue())
-            : step);
+        final String mDefValue = mDef != null ? mDef.getStringValue() : null;
+        final String theMode = mDefValue != null && mDefValue.length() > 0 ? mDef.getStringValue() : FIELD_VALUE_DISTANCE;
+
+        this.mode.setValue(FIELD_MODE, theMode);
+
+        final String fDefValue = fDef != null ? fDef.getStringValue() : null;
+        setFrom(fDefValue != null && fDefValue.length() > 0 ? Double.valueOf(fDef.getStringValue()) : this.min);
+
+        final String tDefValue = tDef != null ? tDef.getStringValue() : null;
+        setTo(tDefValue != null && tDefValue.length() > 0 ? Double.valueOf(tDef.getStringValue()) : this.max);
+
+        final String sDefValue = sDef != null ? sDef.getStringValue() : null;
+        setStep(sDefValue != null && sDefValue.length() > 0 ? Double.valueOf(sDef.getStringValue()) : this.step);
 
         if (lDef != null) {
-            String lDefValue = lDef != null ? lDef.getStringValue() : null;
+            final String lDefValue = lDef != null ? lDef.getStringValue() : null;
 
             if (lDefValue != null && lDefValue.length() > 0) {
                 setLocationValues(lDef.getStringValue());
@@ -539,309 +530,277 @@
 
         if (theMode.equals(FIELD_VALUE_DISTANCE)) {
             enableDistanceMode();
-            inputTables.selectTab(1);
+            this.inputTables.selectTab(1);
         } else {
             enableLocationMode();
         }
-        currentFiltered = (ListGrid)inputTables.getSelectedTab().getPane();
+        this.currentFiltered = (ListGrid) this.inputTables.getSelectedTab().getPane();
 
-        distancePanel.setValues(getFrom(), getTo(), getStep());
+        this.distancePanel.setValues(getFrom(), getTo(), getStep());
     }
 
-
-    protected Canvas createWidget(DataList data) {
-        VLayout layout       = new VLayout();
-        container            = new HLayout();
-        Canvas checkboxPanel = createRadioButtonPanel();
+    protected Canvas createWidget(final DataList data) {
+        final VLayout layout = new VLayout();
+        this.container = new HLayout();
+        final Canvas checkboxPanel = createRadioButtonPanel();
 
-        locationPanel = new DoubleArrayPanel(
-                MESSAGES.unitLocation(),
-                getLocationValues(),
-                this);
+        this.locationPanel = new DoubleArrayPanel(this.MESSAGES.unitLocation(), getLocationValues(), this);
 
-        distancePanel = new DoubleRangePanel(
-                MESSAGES.unitFrom(), MESSAGES.unitTo(), MESSAGES.unitWidth(),
-                0, 0, 0, /* initDefaults set the default values for this. */
-                400,
-                this);
+        this.distancePanel = new DoubleRangePanel(this.MESSAGES.unitFrom(), this.MESSAGES.unitTo(), this.MESSAGES.unitWidth(), 0, 0, 0, /*
+                                                                                                                                         * initDefaults set the
+                                                                                                                                         * default values for
+                                                                                                                                         * this.
+                                                                                                                                         */
+                400, this);
 
-        container.addMember(locationPanel);
-        container.addMember(distancePanel);
-        container.hideMember(locationPanel);
+        this.container.addMember(this.locationPanel);
+        this.container.addMember(this.distancePanel);
+        this.container.hideMember(this.locationPanel);
 
         layout.addMember(checkboxPanel);
-        layout.addMember(container);
-
-        container.setMembersMargin(30);
+        layout.addMember(this.container);
 
-        inputTables   = new TabSet();
-        inputTables.addTabSelectedHandler(new TabSelectedHandler() {
+        this.container.setMembersMargin(30);
+
+        this.inputTables = new TabSet();
+        this.inputTables.addTabSelectedHandler(new TabSelectedHandler() {
             @Override
-            public void onTabSelected(TabSelectedEvent evt) {
-                filterDescription.clear();
-                filterRange.clear();
-                filterResultCount.setValue("");
+            public void onTabSelected(final TabSelectedEvent evt) {
+                LocationDistancePanel.this.filterDescription.clear();
+                LocationDistancePanel.this.filterRange.clear();
+                LocationDistancePanel.this.filterResultCount.setValue("");
 
                 // The assumption is that location is tab 0 and distance tab 1
 
-                Canvas c = evt.getTabPane();
-                if(c instanceof ListGrid) {
-                    currentFiltered = (ListGrid)c;
+                final Canvas c = evt.getTabPane();
+                if (c instanceof ListGrid) {
+                    LocationDistancePanel.this.currentFiltered = (ListGrid) c;
                 }
             }
         });
 
-        Tab locations = new Tab(MESSAGES.locations());
-        Tab distances = new Tab(MESSAGES.distance());
-
-        inputTables.setWidth100();
-        inputTables.setHeight100();
-
-        locations.setPane(locationsTable);
-        distances.setPane(distanceTable);
-
-        inputTables.addTab(locations);
-        inputTables.addTab(distances);
-
-        filterResultCount = new StaticTextItem(MESSAGES.resultCount());
-        filterResultCount.setTitleAlign(Alignment.LEFT);
-        filterResultCount.setTitleStyle("color: #000");
-
-        filterDescription = new TableFilter();
-        filterDescription.setHeight("30px");
-        filterDescription.addFilterHandler(this);
+        final Tab locations = new Tab(this.MESSAGES.locations());
+        final Tab distances = new Tab(this.MESSAGES.distance());
 
-        filterRange = new RangeTableFilter();
-        filterRange.setHeight("30px");
-        filterRange.addFilterHandler(this);
-        filterRange.setVisible(false);
+        this.inputTables.setWidth100();
+        this.inputTables.setHeight100();
 
-        filterCriteria = new SelectItem();
-        filterCriteria.setShowTitle(false);
-        filterCriteria.setWidth(100);
-        filterCriteria.addChangedHandler(new ChangedHandler() {
+        locations.setPane(this.locationsTable);
+        distances.setPane(this.distanceTable);
+
+        this.inputTables.addTab(locations);
+        this.inputTables.addTab(distances);
+
+        this.filterResultCount = new StaticTextItem(this.MESSAGES.resultCount());
+        this.filterResultCount.setTitleAlign(Alignment.LEFT);
+        this.filterResultCount.setTitleStyle("color: #000");
+
+        this.filterDescription = new TableFilter();
+        this.filterDescription.setHeight("30px");
+        this.filterDescription.addFilterHandler(this);
+
+        this.filterRange = new RangeTableFilter();
+        this.filterRange.setHeight("30px");
+        this.filterRange.addFilterHandler(this);
+        this.filterRange.setVisible(false);
+
+        this.filterCriteria = new SelectItem();
+        this.filterCriteria.setShowTitle(false);
+        this.filterCriteria.setWidth(100);
+        this.filterCriteria.addChangedHandler(new ChangedHandler() {
             @Override
-            public void onChanged(ChangedEvent e) {
-                if(e.getValue().toString().equals("range")) {
-                    filterRange.setVisible(true);
-                    filterDescription.setVisible(false);
-                    filterDescription.clear();
-                    filterResultCount.setValue("");
-                }
-                else {
-                    filterRange.setVisible(false);
-                    filterRange.clear();
-                    filterDescription.setVisible(true);
-                    filterResultCount.setValue("");
+            public void onChanged(final ChangedEvent e) {
+                if (e.getValue().toString().equals("range")) {
+                    LocationDistancePanel.this.filterRange.setVisible(true);
+                    LocationDistancePanel.this.filterDescription.setVisible(false);
+                    LocationDistancePanel.this.filterDescription.clear();
+                    LocationDistancePanel.this.filterResultCount.setValue("");
+                } else {
+                    LocationDistancePanel.this.filterRange.setVisible(false);
+                    LocationDistancePanel.this.filterRange.clear();
+                    LocationDistancePanel.this.filterDescription.setVisible(true);
+                    LocationDistancePanel.this.filterResultCount.setValue("");
                 }
             }
         });
 
-        LinkedHashMap<String, String> filterMap =
-            new LinkedHashMap<String, String>();
-        filterMap.put("description", MESSAGES.description());
-        filterMap.put("range", MESSAGES.range());
-        filterCriteria.setValueMap(filterMap);
-        filterCriteria.setValue("description");
+        final LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
+        filterMap.put("description", this.MESSAGES.description());
+        filterMap.put("range", this.MESSAGES.range());
+        this.filterCriteria.setValueMap(filterMap);
+        this.filterCriteria.setValue("description");
 
-        DynamicForm form = new DynamicForm();
-        form.setFields(filterCriteria);
-        inputTables.setHeight("*");
-        DynamicForm form2 = new DynamicForm();
-        form2.setFields(filterResultCount);
+        final DynamicForm form = new DynamicForm();
+        form.setFields(this.filterCriteria);
+        this.inputTables.setHeight("*");
+        final DynamicForm form2 = new DynamicForm();
+        form2.setFields(this.filterResultCount);
 
-        VLayout helper = new VLayout();
-        HLayout filterLayout = new HLayout();
+        final VLayout helper = new VLayout();
+        final HLayout filterLayout = new HLayout();
 
         filterLayout.addMember(form);
-        filterLayout.addMember(filterDescription);
-        filterLayout.addMember(filterRange);
+        filterLayout.addMember(this.filterDescription);
+        filterLayout.addMember(this.filterRange);
         filterLayout.setHeight("30px");
-        helper.addMember(inputTables);
+        helper.addMember(this.inputTables);
         helper.addMember(filterLayout);
         helper.addMember(form2);
         helper.setHeight100();
         helper.setWidth100();
 
-        helperContainer.addMember(helper);
+        this.helperContainer.addMember(helper);
         filterLayout.setWidth("200");
 
         return layout;
     }
 
-
     @Override
-    public void onFilterCriteriaChanged(StringFilterEvent event) {
-        String search = event.getFilter();
+    public void onFilterCriteriaChanged(final StringFilterEvent event) {
+        final String search = event.getFilter();
 
         if (search != null && search.length() > 0) {
-            Criteria c = new Criteria("description", search);
+            final Criteria c = new Criteria("description", search);
 
-            locationsTable.filterData(c);
-            distanceTable.filterData(c);
-            filterResultCount.setValue(currentFiltered.getRecords().length);
-        }
-        else {
-            locationsTable.clearCriteria();
-            distanceTable.clearCriteria();
-            filterResultCount.setValue("");
+            this.locationsTable.filterData(c);
+            this.distanceTable.filterData(c);
+            this.filterResultCount.setValue(this.currentFiltered.getRecords().length);
+        } else {
+            this.locationsTable.clearCriteria();
+            this.distanceTable.clearCriteria();
+            this.filterResultCount.setValue("");
         }
     }
 
-
     @Override
-    public void onFilterCriteriaChanged(RangeFilterEvent event) {
-        Float from = event.getFrom() - 0.001f;
-        Float to = event.getTo() + 0.001f;
+    public void onFilterCriteriaChanged(final RangeFilterEvent event) {
+        final Float from = event.getFrom() - 0.001f;
+        final Float to = event.getTo() + 0.001f;
         GWT.log("filtering range: " + from + " to " + to);
 
-
         Criterion combinedFilter = null;
         Criterion locationFilter = null;
         if (from.equals(Float.NaN) && to.equals(Float.NaN)) {
-            locationsTable.clearCriteria();
-            distanceTable.clearCriteria();
-            filterResultCount.setValue("");
+            this.locationsTable.clearCriteria();
+            this.distanceTable.clearCriteria();
+            this.filterResultCount.setValue("");
             return;
-        }
-        else if (from.equals(Float.NaN)) {
+        } else if (from.equals(Float.NaN)) {
             combinedFilter = new Criterion("to", OperatorId.LESS_OR_EQUAL, to);
-            locationFilter =
-                new Criterion("from", OperatorId.LESS_OR_EQUAL, to);
-            locationsTable.filterData(locationFilter);
-            distanceTable.filterData(combinedFilter);
-            filterResultCount.setValue(currentFiltered.getRecords().length);
+            locationFilter = new Criterion("from", OperatorId.LESS_OR_EQUAL, to);
+            this.locationsTable.filterData(locationFilter);
+            this.distanceTable.filterData(combinedFilter);
+            this.filterResultCount.setValue(this.currentFiltered.getRecords().length);
             return;
-        }
-        else if (to.equals(Float.NaN)) {
-            combinedFilter =
-                new Criterion("from", OperatorId.GREATER_OR_EQUAL, from);
-             locationsTable.filterData(combinedFilter);
-            distanceTable.filterData(combinedFilter);
+        } else if (to.equals(Float.NaN)) {
+            combinedFilter = new Criterion("from", OperatorId.GREATER_OR_EQUAL, from);
+            this.locationsTable.filterData(combinedFilter);
+            this.distanceTable.filterData(combinedFilter);
+        } else {
+            final AdvancedCriteria c1 = new AdvancedCriteria(OperatorId.AND,
+                    new Criterion[] { new Criterion("from", OperatorId.GREATER_OR_EQUAL, from), new Criterion("from", OperatorId.LESS_OR_EQUAL, to) });
+
+            final AdvancedCriteria c2 = new AdvancedCriteria(OperatorId.AND,
+                    new Criterion[] { new Criterion("to", OperatorId.GREATER_OR_EQUAL, from), new Criterion("to", OperatorId.LESS_OR_EQUAL, to) });
+
+            final AdvancedCriteria c3 = new AdvancedCriteria(OperatorId.AND,
+                    new Criterion[] { new Criterion("from", OperatorId.LESS_OR_EQUAL, to), new Criterion("to", OperatorId.GREATER_OR_EQUAL, from) });
+
+            combinedFilter = new AdvancedCriteria(OperatorId.OR, new Criterion[] { c1, c2, c3 });
         }
-        else {
-            AdvancedCriteria c1 =
-                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
-                    new Criterion("from", OperatorId.GREATER_OR_EQUAL, from),
-                    new Criterion("from", OperatorId.LESS_OR_EQUAL, to)
-                });
-
-            AdvancedCriteria c2 =
-                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
-                    new Criterion("to", OperatorId.GREATER_OR_EQUAL, from),
-                    new Criterion("to", OperatorId.LESS_OR_EQUAL, to)
-                });
-
-            AdvancedCriteria c3 =
-                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
-                    new Criterion("from", OperatorId.LESS_OR_EQUAL, to),
-                    new Criterion("to", OperatorId.GREATER_OR_EQUAL, from)
-                });
-
-            combinedFilter =
-                new AdvancedCriteria(OperatorId.OR, new Criterion[] {
-                    c1, c2, c3
-                });
-        }
-        locationsTable.filterData(combinedFilter);
-        distanceTable.filterData(combinedFilter);
-        filterResultCount.setValue(currentFiltered.getRecords().length);
+        this.locationsTable.filterData(combinedFilter);
+        this.distanceTable.filterData(combinedFilter);
+        this.filterResultCount.setValue(this.currentFiltered.getRecords().length);
     }
 
-
     @Override
     public List<String> validate() {
         if (isLocationMode()) {
             return validateLocations();
-        }
-        else {
+        } else {
             return validateRange();
         }
     }
 
-
     protected List<String> validateLocations() {
-        List<String> errors = new ArrayList<String>();
-        NumberFormat nf     = NumberFormat.getDecimalFormat();
+        final List<String> errors = new ArrayList<String>();
+        final NumberFormat nf = NumberFormat.getDecimalFormat();
 
         try {
-            saveLocationValues(locationPanel);
+            saveLocationValues(this.locationPanel);
         }
-        catch (Exception e) {
-            errors.add(MESSAGES.wrongFormat());
+        catch (final Exception e) {
+            errors.add(this.MESSAGES.wrongFormat());
         }
 
-        double[] values = getLocationValues();
-        double[] good   = new double[values.length];
-        int      idx    = 0;
+        final double[] values = getLocationValues();
+        final double[] good = new double[values.length];
+        int idx = 0;
 
-        for (double value: values) {
-            if (value < min || value > max) {
-                String tmp = MESSAGES.error_validate_range();
+        for (final double value : values) {
+            if (value < this.min || value > this.max) {
+                String tmp = this.MESSAGES.error_validate_range();
                 tmp = tmp.replace("$1", nf.format(value));
-                tmp = tmp.replace("$2", nf.format(min));
-                tmp = tmp.replace("$3", nf.format(max));
+                tmp = tmp.replace("$2", nf.format(this.min));
+                tmp = tmp.replace("$3", nf.format(this.max));
                 errors.add(tmp);
-            }
-            else {
+            } else {
                 good[idx++] = value;
             }
         }
 
-        double[] justGood = new double[idx];
+        final double[] justGood = new double[idx];
         for (int i = 0; i < justGood.length; i++) {
             justGood[i] = good[i];
         }
 
         if (!errors.isEmpty()) {
-            locationPanel.setValues(justGood);
+            this.locationPanel.setValues(justGood);
         }
 
         return errors;
     }
 
-
     protected List<String> validateRange() {
-        List<String> errors = new ArrayList<String>();
-        NumberFormat nf     = NumberFormat.getDecimalFormat();
+        final List<String> errors = new ArrayList<String>();
+        final NumberFormat nf = NumberFormat.getDecimalFormat();
 
         try {
-            saveDistanceValues(distancePanel);
+            saveDistanceValues(this.distancePanel);
         }
-        catch (Exception e) {
-            errors.add(MESSAGES.wrongFormat());
+        catch (final Exception e) {
+            errors.add(this.MESSAGES.wrongFormat());
         }
 
         double from = getFrom();
-        double to   = getTo();
-        double step = getStep();
+        double to = getTo();
+        final double step = getStep();
 
-        if (from < min || from > max) {
-            String tmp = MESSAGES.error_validate_range();
+        if (from < this.min || from > this.max) {
+            String tmp = this.MESSAGES.error_validate_range();
             tmp = tmp.replace("$1", nf.format(from));
-            tmp = tmp.replace("$2", nf.format(min));
-            tmp = tmp.replace("$3", nf.format(max));
+            tmp = tmp.replace("$2", nf.format(this.min));
+            tmp = tmp.replace("$3", nf.format(this.max));
             errors.add(tmp);
-            from = min;
+            from = this.min;
         }
 
-        if (to < min || to > max) {
-            String tmp = MESSAGES.error_validate_range();
+        if (to < this.min || to > this.max) {
+            String tmp = this.MESSAGES.error_validate_range();
             tmp = tmp.replace("$1", nf.format(to));
-            tmp = tmp.replace("$2", nf.format(min));
-            tmp = tmp.replace("$3", nf.format(max));
+            tmp = tmp.replace("$2", nf.format(this.min));
+            tmp = tmp.replace("$3", nf.format(this.max));
             errors.add(tmp);
-            to = max;
+            to = this.max;
         }
 
         if (!errors.isEmpty()) {
-            distancePanel.setValues(from, to, step);
+            this.distancePanel.setValues(from, to, step);
         }
 
         return errors;
     }
 
-
     /**
      * This method returns the selected data.
      *
@@ -849,52 +808,46 @@
      */
     @Override
     public Data[] getData() {
-        List<Data> data = new ArrayList<Data>();
+        final List<Data> data = new ArrayList<Data>();
 
         // If we have entered a value and click right afterwards on the
         // 'next' button, the BlurEvent is not fired, and the values are not
         // saved. So, we gonna save those values explicitly.
         if (isLocationMode()) {
-            Canvas member = container.getMember(0);
+            final Canvas member = this.container.getMember(0);
             if (member instanceof DoubleArrayPanel) {
-                DoubleArrayPanel form = (DoubleArrayPanel) member;
+                final DoubleArrayPanel form = (DoubleArrayPanel) member;
                 saveLocationValues(form);
             }
 
-            Data dLocations = getDataLocations();
-            DataItem dFrom  = new DefaultDataItem("ld_from", "ld_from", "");
-            DataItem dTo    = new DefaultDataItem("ld_to", "ld_to", "");
-            DataItem dStep  = new DefaultDataItem("ld_step", "ld_step", "");
+            final Data dLocations = getDataLocations();
+            final DataItem dFrom = new DefaultDataItem("ld_from", "ld_from", "");
+            final DataItem dTo = new DefaultDataItem("ld_to", "ld_to", "");
+            final DataItem dStep = new DefaultDataItem("ld_step", "ld_step", "");
 
             data.add(dLocations);
-            data.add(new DefaultData(
-                "ld_from", null, null, new DataItem[] { dFrom } ));
-            data.add(new DefaultData(
-                "ld_to", null, null, new DataItem[] { dTo } ));
-            data.add(new DefaultData(
-                "ld_step", null, null, new DataItem[] { dStep } ));
-        }
-        else {
-            Canvas member = container.getMember(0);
+            data.add(new DefaultData("ld_from", null, null, new DataItem[] { dFrom }));
+            data.add(new DefaultData("ld_to", null, null, new DataItem[] { dTo }));
+            data.add(new DefaultData("ld_step", null, null, new DataItem[] { dStep }));
+        } else {
+            final Canvas member = this.container.getMember(0);
             if (member instanceof DoubleRangePanel) {
-                DoubleRangePanel form = (DoubleRangePanel) member;
+                final DoubleRangePanel form = (DoubleRangePanel) member;
                 saveDistanceValues(form);
             }
 
-            Data dFrom   = getDataFrom();
-            Data dTo     = getDataTo();
-            Data dStep   = getDataStep();
-            DataItem loc = new DefaultDataItem(
-                "ld_locations", "ld_locations","");
+            final Data dFrom = getDataFrom();
+            final Data dTo = getDataTo();
+            final Data dStep = getDataStep();
+            final DataItem loc = new DefaultDataItem("ld_locations", "ld_locations", "");
 
             data.add(dFrom);
             data.add(dTo);
             data.add(dStep);
-            data.add(new DefaultData(
-                "ld_locations", null, null, new DataItem[] { loc } ));
+            data.add(new DefaultData("ld_locations", null, null, new DataItem[] { loc }));
         }
 
-        Data dMode = getDataMode();
+        final Data dMode = getDataMode();
         if (dMode != null) {
             data.add(dMode);
         }
@@ -902,30 +855,28 @@
         return data.toArray(new Data[data.size()]);
     }
 
-
     /**
      * Returns the Data object for the 'mode' attribute.
      *
      * @return the Data object for the 'mode' attribute.
      */
     protected Data getDataMode() {
-        String   value = mode.getValueAsString(FIELD_MODE);
-        DataItem item  = new DefaultDataItem("ld_mode", "ld_mode", value);
+        final String value = this.mode.getValueAsString(FIELD_MODE);
+        final DataItem item = new DefaultDataItem("ld_mode", "ld_mode", value);
         return new DefaultData("ld_mode", null, null, new DataItem[] { item });
     }
 
-
     protected Data getDataLocations() {
-        double[] locations = getLocationValues();
-        boolean  first     = true;
+        final double[] locations = getLocationValues();
+        boolean first = true;
 
         if (locations == null) {
             return null;
         }
 
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
 
-        for (double l: locations) {
+        for (final double l : locations) {
             if (!first) {
                 sb.append(" ");
             }
@@ -935,210 +886,193 @@
             first = false;
         }
 
-        DataItem item = new DefaultDataItem(
-            "ld_locations",
-            "ld_locations",
-            sb.toString());
+        final DataItem item = new DefaultDataItem("ld_locations", "ld_locations", sb.toString());
 
-        return new DefaultData(
-            "ld_locations",
-            null,
-            null,
-            new DataItem[] { item });
+        return new DefaultData("ld_locations", null, null, new DataItem[] { item });
     }
 
-
     /**
      * Returns the Data object for the 'from' attribute.
      *
      * @return the Data object for the 'from' attribute.
      */
     protected Data getDataFrom() {
-        String value  = Double.valueOf(getFrom()).toString();
-        DataItem item = new DefaultDataItem("ld_from", "ld_from", value);
-        return new DefaultData(
-            "ld_from", null, null, new DataItem[] { item });
+        final String value = Double.valueOf(getFrom()).toString();
+        final DataItem item = new DefaultDataItem("ld_from", "ld_from", value);
+        return new DefaultData("ld_from", null, null, new DataItem[] { item });
     }
 
-
     /**
      * Returns the Data object for the 'to' attribute.
      *
      * @return the Data object for the 'to' attribute.
      */
     protected Data getDataTo() {
-        String value  = Double.valueOf(getTo()).toString();
-        DataItem item = new DefaultDataItem("ld_to", "ld_to", value);
-        return new DefaultData(
-            "ld_to", null, null, new DataItem[] { item });
+        final String value = Double.valueOf(getTo()).toString();
+        final DataItem item = new DefaultDataItem("ld_to", "ld_to", value);
+        return new DefaultData("ld_to", null, null, new DataItem[] { item });
     }
 
-
     /**
      * Returns the Data object for the 'step' attribute.
      *
      * @return the Data object for the 'step' attribute.
      */
     protected Data getDataStep() {
-        String value  = Double.valueOf(getStep()).toString();
-        DataItem item = new DefaultDataItem("ld_step","ld_step", value);
-        return new DefaultData(
-            "ld_step", null, null, new DataItem[] { item });
+        final String value = Double.valueOf(getStep()).toString();
+        final DataItem item = new DefaultDataItem("ld_step", "ld_step", value);
+        return new DefaultData("ld_step", null, null, new DataItem[] { item });
     }
 
-
     /**
      * Determines the current input mode.
      *
      * @return true, if 'location' is the current input mode, otherwise false.
      */
     public boolean isLocationMode() {
-        String inputMode = mode.getValueAsString(FIELD_MODE);
+        final String inputMode = this.mode.getValueAsString(FIELD_MODE);
 
         return inputMode.equals(FIELD_VALUE_LOCATION) ? true : false;
     }
 
-
     /**
      * Activates the location panel.
      */
     protected void enableLocationMode() {
-        mode.setValue(FIELD_MODE, FIELD_VALUE_LOCATION);
-        container.hideMember(distancePanel);
-        container.showMember(locationPanel);
-        setupDistanceInfoTable(locationsTable, false, false);
-        setupDistanceInfoTable(distanceTable, true, true);
-        inputTables.updateTab(0, locationsTable);
-        inputTables.updateTab(1, distanceTable);
+        this.mode.setValue(FIELD_MODE, FIELD_VALUE_LOCATION);
+        this.container.hideMember(this.distancePanel);
+        this.container.showMember(this.locationPanel);
+        setupDistanceInfoTable(this.locationsTable, false, false);
+        setupDistanceInfoTable(this.distanceTable, true, true);
+        this.inputTables.updateTab(0, this.locationsTable);
+        this.inputTables.updateTab(1, this.distanceTable);
     }
 
-
     /**
      * Activates the distance panel.
      */
     protected void enableDistanceMode() {
-        mode.setValue(FIELD_MODE, FIELD_VALUE_DISTANCE);
-        container.hideMember(locationPanel);
-        container.showMember(distancePanel);
-        setupDistanceInfoTable(locationsTable, true, false);
-        setupDistanceInfoTable(distanceTable, false, true);
-        inputTables.updateTab(0, locationsTable);
-        inputTables.updateTab(1, distanceTable);
+        this.mode.setValue(FIELD_MODE, FIELD_VALUE_DISTANCE);
+        this.container.hideMember(this.locationPanel);
+        this.container.showMember(this.distancePanel);
+        setupDistanceInfoTable(this.locationsTable, true, false);
+        setupDistanceInfoTable(this.distanceTable, false, true);
+        this.inputTables.updateTab(0, this.locationsTable);
+        this.inputTables.updateTab(1, this.distanceTable);
     }
 
-
     /**
      * This method switches the input mode between location and distance input.
      *
-     * @param event The click event fired by a RadioButtonGroupItem.
+     * @param event
+     *            The click event fired by a RadioButtonGroupItem.
      */
     @Override
-    public void onChange(ChangeEvent event) {
-        String value = (String) event.getValue();
+    public void onChange(final ChangeEvent event) {
+        final String value = (String) event.getValue();
 
         if (value == null) {
             return;
         }
         if (value.equals(FIELD_VALUE_LOCATION)) {
             enableLocationMode();
-            filterDescription.clear();
-            filterRange.clear();
-            filterResultCount.setValue("");
+            this.filterDescription.clear();
+            this.filterRange.clear();
+            this.filterResultCount.setValue("");
 
             // Bring this tab to front.
-            inputTables.selectTab(0);
-        }
-        else {
+            this.inputTables.selectTab(0);
+        } else {
             enableDistanceMode();
-            filterDescription.clear();
-            filterRange.clear();
-            filterResultCount.setValue("");
+            this.filterDescription.clear();
+            this.filterRange.clear();
+            this.filterResultCount.setValue("");
 
             // Bring the distanceTable tab to front.
-            inputTables.selectTab(1);
+            this.inputTables.selectTab(1);
         }
     }
 
-
     /**
      * This method is used to validate the inserted data in the form fields.
      *
-     * @param event The BlurEvent that gives information about the FormItem that
-     * has been modified and its value.
+     * @param event
+     *            The BlurEvent that gives information about the FormItem that
+     *            has been modified and its value.
      */
     @Override
-    public void onBlur(BlurEvent event) {
-        FormItem item = event.getItem();
-        String  field = item.getFieldName();
+    public void onBlur(final BlurEvent event) {
+        final FormItem item = event.getItem();
+        final String field = item.getFieldName();
 
         if (field == null) {
             return;
         }
 
         if (field.equals(DoubleArrayPanel.FIELD_NAME)) {
-            DoubleArrayPanel p = (DoubleArrayPanel) event.getForm();
+            final DoubleArrayPanel p = (DoubleArrayPanel) event.getForm();
 
             saveLocationValue(p, item);
-        }
-        else {
-            DoubleRangePanel p = (DoubleRangePanel) event.getForm();
+        } else {
+            final DoubleRangePanel p = (DoubleRangePanel) event.getForm();
 
             saveDistanceValue(p, item);
         }
     }
 
-
-
     /**
      * Validates and stores all values entered in the location mode.
      *
-     * @param p The DoubleArrayPanel.
+     * @param p
+     *            The DoubleArrayPanel.
      */
-    protected void saveLocationValues(DoubleArrayPanel p) {
-        FormItem[] formItems = p.getFields();
+    protected void saveLocationValues(final DoubleArrayPanel p) {
+        final FormItem[] formItems = p.getFields();
 
-        for (FormItem item: formItems) {
+        for (final FormItem item : formItems) {
             if (item.getFieldName().equals(DoubleArrayPanel.FIELD_NAME)) {
                 saveLocationValue(p, item);
             }
         }
     }
 
-
     /**
      * Validates and stores all values entered in the distance mode.
      *
-     * @param p The DoubleRangePanel.
+     * @param p
+     *            The DoubleRangePanel.
      */
-    protected void saveDistanceValues(DoubleRangePanel p) {
-        FormItem[] formItems = p.getFields();
+    protected void saveDistanceValues(final DoubleRangePanel p) {
+        final FormItem[] formItems = p.getFields();
 
-        for (FormItem item: formItems) {
+        for (final FormItem item : formItems) {
             saveDistanceValue(p, item);
         }
     }
 
-
     /**
      * Validates and stores a value entered in the location mode.
      *
-     * @param p The DoubleArrayPanel.
-     * @param item The item that needs to be validated.
+     * @param p
+     *            The DoubleArrayPanel.
+     * @param item
+     *            The item that needs to be validated.
      */
-    protected void saveLocationValue(DoubleArrayPanel p, FormItem item) {
+    protected void saveLocationValue(final DoubleArrayPanel p, final FormItem item) {
         if (p.validateForm(item)) {
             setLocationValues(p.getInputValues(item));
         }
     }
 
-
     /**
      * Validates and stores value entered in the distance mode.
      *
-     * @param p The DoubleRangePanel.
-     * @param item The item that needs to be validated.
+     * @param p
+     *            The DoubleRangePanel.
+     * @param item
+     *            The item that needs to be validated.
      */
-    protected void saveDistanceValue(DoubleRangePanel p, FormItem item) {
+    protected void saveDistanceValue(final DoubleRangePanel p, final FormItem item) {
         if (p.validateForm(item)) {
             setFrom(p.getFrom());
             setTo(p.getTo());
@@ -1146,7 +1080,6 @@
         }
     }
 
-
     /**
      * This method creates the panel that contains the checkboxes to switch
      * between the input mode 'location' and 'distance'.
@@ -1154,161 +1087,148 @@
      * @return the checkbox panel.
      */
     protected Canvas createRadioButtonPanel() {
-        mode = new DynamicForm();
+        this.mode = new DynamicForm();
 
-        RadioGroupItem radio = new RadioGroupItem(FIELD_MODE);
+        final RadioGroupItem radio = new RadioGroupItem(FIELD_MODE);
         radio.setShowTitle(false);
         radio.setVertical(false);
         radio.setWrap(false);
 
-        LinkedHashMap<String, String> values =
-            new LinkedHashMap<String, String>();
-        values.put(FIELD_VALUE_LOCATION, MESSAGES.location());
-        values.put(FIELD_VALUE_DISTANCE, MESSAGES.distance());
+        final LinkedHashMap<String, String> values = new LinkedHashMap<String, String>();
+        values.put(FIELD_VALUE_LOCATION, this.MESSAGES.location());
+        values.put(FIELD_VALUE_DISTANCE, this.MESSAGES.distance());
 
-        LinkedHashMap<String, String> initial =
-            new LinkedHashMap<String, String>();
+        final LinkedHashMap<String, String> initial = new LinkedHashMap<String, String>();
         initial.put(FIELD_MODE, FIELD_VALUE_DISTANCE);
 
         radio.setValueMap(values);
         radio.addChangeHandler(this);
 
-        mode.setFields(radio);
-        mode.setValues(initial);
+        this.mode.setFields(radio);
+        this.mode.setValues(initial);
 
-        return mode;
+        return this.mode;
     }
 
-
     protected void createDistanceInputPanel() {
-        Config config = Config.getInstance();
-        String url    = config.getServerUrl();
-        String river  = "";
+        final Config config = Config.getInstance();
+        final String url = config.getServerUrl();
+        String river = "";
 
-        ArtifactDescription adescr = artifact.getArtifactDescription();
-        DataList[] data = adescr.getOldData();
+        final ArtifactDescription adescr = this.artifact.getArtifactDescription();
+        final DataList[] data = adescr.getOldData();
 
         if (data != null && data.length > 0) {
-            for (int i = 0; i < data.length; i++) {
-                DataList dl = data[i];
+            for (final DataList dl : data) {
                 if (dl.getState().endsWith("river")) {
                     for (int j = 0; j < dl.size(); j++) {
-                        Data d = dl.get(j);
-                        DataItem[] di = d.getItems();
+                        final Data d = dl.get(j);
+                        final DataItem[] di = d.getItems();
                         if (di != null && di.length == 1) {
-                           river = d.getItems()[0].getStringValue();
+                            river = d.getItems()[0].getStringValue();
                         }
                     }
                 }
             }
         }
 
-        distanceTable.setDataSource(new DistanceInfoDataSource(
-            url, river, "distances"));
-        locationsTable.setDataSource(new DistanceInfoDataSource(
-            url, river, "locations"));
+        this.distanceTable.setDataSource(new DistanceInfoDataSource(url, river, "distances"));
+        this.locationsTable.setDataSource(new DistanceInfoDataSource(url, river, "locations"));
     }
 
     protected double getFrom() {
-        return from;
+        return this.from;
     }
 
-    protected void setTo(String to) {
-       try {
-            double toValue = Double.parseDouble(to);
+    protected void setTo(final String to) {
+        try {
+            final double toValue = Double.parseDouble(to);
             setTo(toValue);
         }
-        catch(NumberFormatException nfe) {
-            // Is there anything to do?
-        }
-    }
-
-    protected void setFrom(String from) {
-       try {
-            double fromValue = Double.parseDouble(from);
-            setFrom(fromValue);
-        }
-        catch(NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             // Is there anything to do?
         }
     }
 
-    protected void setFrom(double from) {
-        this.from = from;
-        /* The doubling should be removed and this.from abolished */
-        distancePanel.setFrom(from);
-    }
-
-
-    protected double getTo() {
-        return to;
+    protected void setFrom(final String from) {
+        try {
+            final double fromValue = Double.parseDouble(from);
+            setFrom(fromValue);
+        }
+        catch (final NumberFormatException nfe) {
+            // Is there anything to do?
+        }
     }
 
-
-    protected void setTo(double to) {
-        this.to = to;
-        /* The doubling should be removed and this.to abolished */
-        distancePanel.setTo(to);
+    protected void setFrom(final double from) {
+        this.from = from;
+        /* The doubling should be removed and this.from abolished */
+        this.distancePanel.setFrom(from);
     }
 
+    protected double getTo() {
+        return this.to;
+    }
+
+    protected void setTo(final double to) {
+        this.to = to;
+        /* The doubling should be removed and this.to abolished */
+        this.distancePanel.setTo(to);
+    }
 
     protected double getStep() {
-        return step;
+        return this.step;
     }
 
-
-    protected void setStep(double step) {
+    protected void setStep(final double step) {
         this.step = step;
     }
 
-
     protected double[] getLocationValues() {
-        return values;
+        return this.values;
     }
 
-    protected void appendLocation(String loc) {
+    protected void appendLocation(final String loc) {
         double[] selected;
         if (getLocationValues() != null) {
-            double[] val = getLocationValues();
+            final double[] val = getLocationValues();
             selected = new double[val.length + 1];
-            for(int i = 0; i < val.length; i++){
+            for (int i = 0; i < val.length; i++) {
                 selected[i] = val[i];
             }
             try {
                 selected[val.length] = Double.parseDouble(loc);
             }
-            catch(NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 // Is there anything to do here?
             }
-        }
-        else {
+        } else {
             selected = new double[1];
             selected[0] = Double.parseDouble(loc);
         }
         setLocationValues(selected);
     }
 
-    protected void setLocationValues(double[] values) {
+    protected void setLocationValues(final double[] values) {
         this.values = values;
-        locationPanel.setValues(values);
+        this.locationPanel.setValues(values);
     }
 
-
-    protected void setLocationValues(String values) {
-        String[] vs = values.split(" ");
+    protected void setLocationValues(final String values) {
+        final String[] vs = values.split(" ");
 
         if (vs == null) {
             return;
         }
 
-        double[] ds  = new double[vs.length];
-        int      idx = 0;
+        final double[] ds = new double[vs.length];
+        int idx = 0;
 
-        for (String s: vs) {
+        for (final String s : vs) {
             try {
                 ds[idx++] = Double.valueOf(s);
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 // do nothing
             }
         }
@@ -1316,11 +1236,10 @@
         setLocationValues(ds);
     }
 
-
-    protected void setDistanceValues (double from, double to) {
+    protected void setDistanceValues(final double from, final double to) {
         setFrom(from);
         setTo(to);
-        distancePanel.setValues(from, to, getStep());
+        this.distancePanel.setValues(from, to, getStep());
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/MapSelection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/MapSelection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -29,7 +29,7 @@
 
     private static final long serialVersionUID = 1261822454641198692L;
 
-    protected ModuleSelection moduleSelection;
+    private ModuleSelection moduleSelection;
 
     public MapSelection() {
     }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ModuleSelection.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ModuleSelection.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,19 +8,13 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import com.smartgwt.client.types.VerticalAlignment;
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
-import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
-import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYSConstants;
@@ -32,10 +26,21 @@
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 import org.dive4elements.river.client.shared.model.Module;
+import org.dive4elements.river.client.shared.model.ModuleGroup;
 
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.VerticalAlignment;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.LayoutSpacer;
+import com.smartgwt.client.widgets.layout.VLayout;
 
 /**
  * The ModuleSelection combines the river selection and the module selection in
@@ -50,32 +55,38 @@
     private static final long serialVersionUID = -5634831815175543328L;
 
     /** The message class that provides i18n strings.*/
-    protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
-
-    /** The module checkboxes.*/
-    protected static RadioGroupItem radio;
-
-    /** */
-    protected Module[] modules;
+    private FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
 
     /** The ModuleService used to retrieve the available modules of a user.*/
-    protected ModuleServiceAsync moduleService = GWT.create(
-        ModuleService.class);
-
-    private Map<String, List<String> > modulesRiverMap;
-    protected Map<String, HLayout> rivers;
+    private ModuleServiceAsync moduleService = GWT.create(ModuleService.class);
 
-    /**
-     * The default constructor.
-     */
+    private Map<String, List<String> > modulesRiverMap = new LinkedHashMap<String, List<String> >();
+
+    private Map<String, Module> modulesByName = new HashMap<String, Module>();
+
+    private Map<ModuleGroup, List<Module>> modulesByGroup = new LinkedHashMap<ModuleGroup, List<Module>>();
+
+    private Map<ModuleGroup, RadioGroupItem> groupToRadios = new LinkedHashMap<ModuleGroup, RadioGroupItem>();
+
+    private Map<ModuleGroup, Canvas> groupToCanvas = new LinkedHashMap<ModuleGroup, Canvas>();
+
+    private Map<String, HLayout> rivers = null;
+
+    private VLayout radioPanel;
+
+    /* TODO: seems that it needs to be static for the callback, is this really necessary?
+     * FIXME:  this is (most probable) the reason for the following bug:
+     * - open two different new projects
+     * - select in both windows two differenz modules (e.g. w-info in the first, m-info in the second)
+     * - now click on a river in each window
+     * ---> both windows will now show the calculations of the same module (i.e. either both m-info, or both w-info; not one m-info the the other w-info as it should).  
+     * */
+    private static Module selectedModule = null;
+
     public ModuleSelection() {
-        rivers = null;
-        modulesRiverMap = new LinkedHashMap<String, List<String> >();
-
         readModules();
     }
 
-
     /**
      * This method returns a widget that renders the checkboxes for each module
      * and the MapSelection that lets the user choose the river.
@@ -114,59 +125,54 @@
             @Override
             public void onSuccess(Module[] newmodules) {
                 GWT.log("Retrieved " + newmodules.length + " modules.");
-                modules = newmodules;
-                setModules();
+                setModules(newmodules);
+                updateRadioPanels();
             }
         });
     }
 
+    // TODO: bad. Too much knowledge spread over the application.
+    // TODO: instead, e.g. use a controller that knows both (ModuleSelection and LinkSelection) and let him do this kind of things 
     private void checkRivers(String selected) {
-        if (selected == null) {
-            selected = getSelectedModule();
-        }
-        if (rivers != null
-            && !rivers.isEmpty()
-            && modules != null
-            && selected != null
-        ) {
-            List<String> allowedRivers = modulesRiverMap.get(selected);
-            if ( allowedRivers == null ) {
-                GWT.log("No configured rivers for module: " + selected);
-            }
-            for (Map.Entry<String, HLayout> s: rivers.entrySet()) {
-                if ( allowedRivers == null ) {
-                    s.getValue().hide();
-                    continue;
-                }
-                if (!allowedRivers.contains(s.getKey())) {
-                    s.getValue().hide();
-                } else {
-                    s.getValue().show();
-                }
+        if (rivers == null || rivers.isEmpty() || /*modules == null || */ selected == null ) 
+            return;
+        
+        final List<String> allowedRivers = modulesRiverMap.get(selected);
+        if ( allowedRivers == null ) 
+            GWT.log("No configured rivers for module: " + selected);
+
+        for (final Map.Entry<String, HLayout> s: rivers.entrySet()) {
+            if (allowedRivers == null || !allowedRivers.contains(s.getKey())) {
+                s.getValue().hide();
+            } else {
+                s.getValue().show();
             }
         }
     }
-
-    private void setModules() {
-        LinkedHashMap<String, String> values =
-            new LinkedHashMap<String, String>();
+    
+    protected final void setModules(Module[] newmodules) {
+        modulesRiverMap.clear();
 
-        if (this.modules!= null) {
-            for(Module module : this.modules) {
-                values.put(module.getName(), module.getLocalizedName());
-                if (module.isSelected()) {
-                    GWT.log("Module " + module.getName() + " is selected.");
-                    if (radio != null) {
-                        radio.setDefaultValue(module.getName());
-                    }
-                }
-                modulesRiverMap.put(module.getName(), module.getRivers());
-            }
+        if( newmodules == null )
+            return;
+
+        for(final Module module : newmodules) {
+            final String name = module.getName();
+
+            /* remember rivers per module */
+            modulesRiverMap.put(name, module.getRivers());
+
+            /* hash by name */
+            modulesByName.put(name, module);
+
+            /* hash by group  */
+            final ModuleGroup group = module.getGroup();
+            if( !modulesByGroup.containsKey( group ) )
+                modulesByGroup.put(group, new LinkedList<Module>());
+
+            final List<Module> modulesGroup = modulesByGroup.get(group);
+            modulesGroup.add(module);
         }
-        if (radio != null) {
-            radio.setValueMap(values);
-        }
-        checkRivers(null);
     }
 
     /**
@@ -175,36 +181,128 @@
      * @return a widget with checkboxes.
      */
     protected Canvas createWidget() {
-        HLayout layout = new HLayout();
-
-        Label      label = new Label(MESSAGES.module_selection());
-        DynamicForm form = new DynamicForm();
+        
+        final HLayout layout = new HLayout();
+        
+        radioPanel = new VLayout();
 
-        radio = new RadioGroupItem("plugin");
-        radio.addChangeHandler(new ChangeHandler() {
-            @Override
-            public void onChange(ChangeEvent event) {
-                checkRivers((String)event.getValue());
-            }
-        });
-
+        final Label label = new Label(MESSAGES.module_selection());
         label.setWidth(50);
         label.setHeight(25);
 
-
-        radio.setShowTitle(false);
-        radio.setVertical(true);
+        layout.addMember(label);
+        layout.addMember(radioPanel);
 
-        setModules();
-
-        form.setFields(radio);
-
-        layout.addMember(label);
-        layout.addMember(form);
+        updateRadioPanels();
 
         return layout;
     }
 
+    protected final void updateRadioPanels() {
+        
+        /* first clear existing panels, if any exist */
+        final Collection<Canvas> oldforms = groupToCanvas.values();
+        for (Canvas oldCanvas : oldforms) {
+            radioPanel.removeMember(oldCanvas);
+            oldCanvas.destroy();
+        }
+
+        groupToCanvas.clear();
+        groupToRadios.clear();
+        selectedModule = null;
+        
+        if( radioPanel == null )
+            return;
+        
+        /* now create radio items per group */
+        int count = 0;
+        for (final Entry<ModuleGroup, List<Module>> groupEntry : modulesByGroup.entrySet()) {
+            
+            final  ModuleGroup group = groupEntry.getKey();
+            final List<Module> groupModule = groupEntry.getValue();
+            
+            
+            final RadioGroupItem moduleRadio = new RadioGroupItem("modulegroup" + count++);
+            moduleRadio.setShowTitle(false);
+            moduleRadio.setWrap(false);
+            
+            moduleRadio.addChangeHandler(new ChangeHandler() {
+                @Override
+                public void onChange(ChangeEvent event) {
+                    final String selectedModuleName = (String) event.getValue();
+                    handleModuleSelected(selectedModuleName);
+                }
+            });
+
+            Module selected = null;
+            final LinkedHashMap<String, String> values = new LinkedHashMap<String, String>();
+            for(final Module module : groupModule) {
+                values.put(module.getName(), module.getLocalizedName());
+                if (module.isSelected()) {
+                    GWT.log("Module " + module.getName() + " is selected.");
+                    selectedModule = module;
+                    selected = module;
+                }
+            }
+            moduleRadio.setValueMap(values);
+
+            final DynamicForm groupForm = new DynamicForm();
+            groupForm.setItems(moduleRadio);
+            groupForm.setColWidths(60,"*");
+
+            final Canvas groupPanel;
+            if( group.showGroupFrame() )
+            {
+                final HLayout layout = new HLayout();
+
+                final LayoutSpacer spacer = new LayoutSpacer();
+                // so text is on the same level as other items (with radio-icon), lets hope 25px is always right
+                spacer.setWidth(25);
+                layout.addMember(spacer);
+
+                final Label label = new Label(group.toString());
+                layout.addMember(label);
+
+                layout.addMember(groupForm);
+                
+                groupPanel = layout;
+            }
+            else
+                groupPanel = groupForm;
+            
+            this.groupToRadios.put( group, moduleRadio );
+            this.groupToCanvas.put( group, groupPanel );
+
+            /* selection must be done after value-map was set; and, only if the selection holds for this group */
+            if( selected != null )
+                moduleRadio.setValue(selected.getName());
+            
+            radioPanel.addMember(groupPanel);
+        }
+        
+        checkRivers(getSelectedModule());
+    }
+
+    protected void handleModuleSelected(final String selectedModuleName) {
+  
+        /* remember selected module for later */
+        selectedModule = modulesByName.get(selectedModuleName);
+        
+        /* because radios might in different radio-groups, we need to de-select them manually */
+        final ModuleGroup group = selectedModule.getGroup();
+        
+        for (final Entry<ModuleGroup, RadioGroupItem> entry : groupToRadios.entrySet()) {
+            final ModuleGroup radioGroup = entry.getKey();
+
+            if( !group.equals(radioGroup))
+            {
+                final RadioGroupItem groupRadio = entry.getValue();
+                groupRadio.setValue((String)null);
+            }
+        }
+        
+        checkRivers(selectedModuleName);
+    }
 
     /**
      * This method prepares the data of two widgets - the module selection and
@@ -217,13 +315,11 @@
     @Override
     protected Data[] getData() {
 
-        String module = radio.getValueAsString();
+        final Module module = selectedModule;
 
-        DataItem[] items = new DefaultDataItem[1];
-        items[0]         = new DefaultDataItem(module, module, module);
+        final DataItem[] items = new DefaultDataItem[] { new DefaultDataItem(module.getLocalizedName(), module.getLocalizedName(), module.getName()) };
 
-        Data       data  = new DefaultData("module", null, null, items);
-
+        final Data data  = new DefaultData("module", null, null, items);
         return new Data[] {data};
     }
 
@@ -236,10 +332,10 @@
     }-*/;
 
     private static String getSelectedModule() {
-        if (radio == null) {
+        if (selectedModule == null) {
             return null;
         }
-        return radio.getValueAsString();
+        return selectedModule.getName();
     }
 }
 // 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/NilDatacageTwinPanelInfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,55 @@
+/** 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;
+
+import org.dive4elements.river.client.client.ui.DatacageTwinPanel.IDatacageTwinPanelInfo;
+import org.dive4elements.river.client.shared.model.Recommendation;
+
+/**
+ * An info implementation that does NOT tweak any factories.
+ *
+ * @author Gernot Belger
+ */
+public final class NilDatacageTwinPanelInfo implements IDatacageTwinPanelInfo {
+
+    private final String outs;
+    private final String columnLabel;
+
+    public NilDatacageTwinPanelInfo(final String columnLabel, final String outs) {
+        this.columnLabel = columnLabel;
+        this.outs = outs;
+    }
+
+    @Override
+    public String getFactory(final String originalFactory) {
+        return originalFactory;
+    }
+
+
+    @Override
+    public String getDataStringFactory(final Recommendation recommendation) {
+        return recommendation.getFactory();
+    }
+
+    @Override
+    public void adjustRecommendation(final Recommendation recommendation) {
+        /* does nothing */
+    }
+
+    @Override
+    public String getOuts() {
+        return this.outs;
+    }
+
+    @Override
+    public String getColumnLabel() {
+        return this.columnLabel;
+    }
+}
\ 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/PanelHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,118 @@
+/** 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;
+
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.form.fields.IntegerItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
+import com.smartgwt.client.widgets.form.validator.IsIntegerValidator;
+import com.smartgwt.client.widgets.form.validator.Validator;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.SortNormalizer;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class PanelHelper {
+
+    public PanelHelper() {
+
+    }
+
+    public static final TextItem createItem(final String identifier, final String title, final String width, final Validator... validator) {
+        final TextItem item = new TextItem(identifier, title);
+        item.setWidth(width);
+        item.setWrapTitle(false);
+        item.setValidators(validator);
+        return item;
+    }
+
+    public static final IntegerItem createIntegerItem(final String identifier, final String title, final String width, final Validator... validator) {
+        final IntegerItem item = new IntegerItem(identifier, title);
+        item.setWidth(width);
+        item.setWrapTitle(false);
+        item.setValidators(validator);
+        return item;
+    }
+
+    public static VLayout getSpacer(final int height) {
+        final VLayout spacer = new VLayout();
+        spacer.setHeight(height);
+        return spacer;
+    }
+
+    public static TextItem createItem(final String title) {
+        final TextItem inputItem = new TextItem(title);
+
+        final boolean hideTitle = title == null || title.isEmpty();
+        inputItem.setShowTitle(!hideTitle);
+        // final CustomValidator validator = new CustomValidator() {
+        // @Override
+        // protected boolean condition(final Object value) {
+        // return validate().size() > 0 ? false : true;
+        // }
+        // };
+        inputItem.setValidators(new IsIntegerValidator()); // Validator hat keinen sichtbaren Effekt.
+        inputItem.setWidth(60);
+        return inputItem;
+
+    }
+
+    public static final ListGridField createRemoveField(final ListGrid table, final String icon) {
+        final ListGridField removeField = new ListGridField("_removeRecord", "Remove Record") {
+            {
+                setType(ListGridFieldType.ICON);
+                setIcon(icon);
+                setCanEdit(false);
+                setCanFilter(false);
+                setCanSort(false);
+                setCanGroupBy(false);
+                setCanFreeze(false);
+                setWidth(25);
+                setCanDragResize(false);
+                super.setCanToggle(false);
+            }
+        };
+        table.addRecordClickHandler(new RecordClickHandler() {
+            @Override
+            public void onRecordClick(final RecordClickEvent event) {
+                // Just handle remove-clicks
+                if (!event.getField().getName().equals(removeField.getName())) {
+                    return;
+                }
+                event.getViewer().removeData(event.getRecord());
+            }
+        });
+
+        return removeField;
+    }
+
+    public static final ListGridField createIntTableField(final String key, final String msg, final boolean canSort, final SortNormalizer normalizer,
+            final IntegerRangeValidator validators) {
+        final ListGridField intField = new ListGridField(key, msg);
+        intField.setType(ListGridFieldType.INTEGER);
+        intField.setValidators(validators);
+        intField.setWidth(90);
+        intField.setAlign(Alignment.RIGHT);
+        intField.setSortNormalizer(normalizer);
+        intField.setCanSort(canSort);
+        intField.setCanDragResize(false);
+
+        return intField;
+    }
+
+}
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,20 +8,11 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.types.VerticalAlignment;
-import com.smartgwt.client.types.VisibilityMode;
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.SectionStack;
-import com.smartgwt.client.widgets.layout.SectionStackSection;
-import com.smartgwt.client.widgets.layout.VLayout;
-import com.smartgwt.client.widgets.tab.Tab;
-import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYS;
@@ -51,6 +42,7 @@
 import org.dive4elements.river.client.client.ui.stationinfo.GaugePanel;
 import org.dive4elements.river.client.client.ui.stationinfo.InfoPanel;
 import org.dive4elements.river.client.client.ui.stationinfo.MeasurementStationPanel;
+import org.dive4elements.river.client.shared.model.AbstractFixBunduArtifact;
 import org.dive4elements.river.client.shared.model.Artifact;
 import org.dive4elements.river.client.shared.model.ArtifactDescription;
 import org.dive4elements.river.client.shared.model.Collection;
@@ -60,26 +52,29 @@
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 import org.dive4elements.river.client.shared.model.ExportMode;
-import org.dive4elements.river.client.shared.model.FixAnalysisArtifact;
 import org.dive4elements.river.client.shared.model.MINFOArtifact;
 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.UINFOArtifact;
 import org.dive4elements.river.client.shared.model.WINFOArtifact;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.Overflow;
+import com.smartgwt.client.types.VerticalAlignment;
+import com.smartgwt.client.types.VisibilityMode;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.SectionStack;
+import com.smartgwt.client.widgets.layout.SectionStackSection;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.Tab;
+import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
 
-
-public class ParameterList
-extends      Tab
-implements   StepBackHandler, StepForwardHandler, ParameterChangeHandler,
-             HasParameterChangeHandler, CollectionChangeHandler,
-             OutputModesChangeHandler, AdvanceHandler
-{
+public class ParameterList extends Tab implements StepBackHandler, StepForwardHandler, ParameterChangeHandler, HasParameterChangeHandler, CollectionChangeHandler, OutputModesChangeHandler, AdvanceHandler {
     private static final long serialVersionUID = 5204784727239299980L;
 
     public static final String STYLENAME_OLD_PARAMETERS = "oldParameters";
@@ -88,21 +83,15 @@
     protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
 
     /** The ArtifactService used to communicate with the Artifact server. */
-    protected ArtifactServiceAsync artifactService =
-        GWT.create(ArtifactService.class);
+    protected ArtifactServiceAsync artifactService = GWT.create(ArtifactService.class);
 
     /** The StepForwardService used to put data into an existing artifact. */
-    protected StepForwardServiceAsync forwardService =
-        GWT.create(StepForwardService.class);
+    protected StepForwardServiceAsync forwardService = GWT.create(StepForwardService.class);
 
     /** The StepForwardService used to put data into an existing artifact. */
-    protected AdvanceServiceAsync advanceService =
-        GWT.create(AdvanceService.class);
+    protected AdvanceServiceAsync advanceService = GWT.create(AdvanceService.class);
 
-
-    protected ReportServiceAsync reportService =
-        GWT.create(ReportService.class);
-
+    protected ReportServiceAsync reportService = GWT.create(ReportService.class);
 
     /** The list of ParameterizationChangeHandler. */
     protected List<ParameterChangeHandler> parameterHandlers;
@@ -115,7 +104,7 @@
 
     protected List<DataList> old;
     protected Map<String, Canvas> oldStorage;
-    protected DataList   current;
+    protected DataList current;
 
     protected UIProvider uiProvider;
 
@@ -127,51 +116,45 @@
     protected VLayout helperPanel;
     protected VLayout tablePanel;
     protected InfoPanel infoPanel;
-    protected Canvas  reportPanel;
+    protected Canvas reportPanel;
 
     private SectionStack stack;
 
-    public ParameterList(FLYS flys, CollectionView cView, String title) {
+    public ParameterList(final FLYS flys, final CollectionView cView, final String title) {
         super(title);
 
         this.cView = cView;
-        this.flys  = flys;
+        this.flys = flys;
 
-        parameterHandlers = new ArrayList<ParameterChangeHandler>();
-        old               = new ArrayList<DataList>();
-        oldStorage        = new TreeMap<String, Canvas>();
-        topLayout         = new VLayout();
-        oldItems          = new VLayout();
-        currentItems      = new VLayout();
-        exportModes       = new VLayout();
-        report            = new VLayout();
+        this.parameterHandlers = new ArrayList<ParameterChangeHandler>();
+        this.old = new ArrayList<DataList>();
+        this.oldStorage = new TreeMap<String, Canvas>();
+        this.topLayout = new VLayout();
+        this.oldItems = new VLayout();
+        this.currentItems = new VLayout();
+        this.exportModes = new VLayout();
+        this.report = new VLayout();
 
         addParameterChangeHandler(this);
 
         init();
     }
 
-
-    public ParameterList(
-        FLYS           flys,
-        CollectionView cView,
-        String         title,
-        Artifact       artifact)
-    {
+    public ParameterList(final FLYS flys, final CollectionView cView, final String title, final Artifact artifact) {
         super(title);
 
-        this.cView    = cView;
-        this.flys     = flys;
+        this.cView = cView;
+        this.flys = flys;
         this.artifact = artifact;
 
-        parameterHandlers = new ArrayList<ParameterChangeHandler>();
-        old               = new ArrayList<DataList>();
-        oldStorage        = new TreeMap<String, Canvas>();
-        topLayout         = new VLayout();
-        oldItems          = new VLayout();
-        currentItems      = new VLayout();
-        exportModes       = new VLayout();
-        report            = new VLayout();
+        this.parameterHandlers = new ArrayList<ParameterChangeHandler>();
+        this.old = new ArrayList<DataList>();
+        this.oldStorage = new TreeMap<String, Canvas>();
+        this.topLayout = new VLayout();
+        this.oldItems = new VLayout();
+        this.currentItems = new VLayout();
+        this.exportModes = new VLayout();
+        this.report = new VLayout();
 
         init();
 
@@ -180,156 +163,143 @@
         setArtifact(artifact, false);
     }
 
-
     protected void init() {
-        HLayout rootLayout = new HLayout();
+        final HLayout rootLayout = new HLayout();
         rootLayout.setMembersMargin(20);
 
-        VLayout left = new VLayout();
+        final VLayout left = new VLayout();
 
-        if (old == null || old.size() == 0) {
-            oldItems.setHeight(1);
+        if (this.old == null || this.old.size() == 0) {
+            this.oldItems.setHeight(1);
         }
 
-        oldItems.setMembersMargin(10);
-        oldItems.setStyleName(STYLENAME_OLD_PARAMETERS);
-        currentItems.setAlign(VerticalAlignment.TOP);
+        this.oldItems.setMembersMargin(10);
+        this.oldItems.setStyleName(STYLENAME_OLD_PARAMETERS);
+        this.currentItems.setAlign(VerticalAlignment.TOP);
 
         left.setMembersMargin(20);
         left.setWidth(300);
 
-        left.addMember(oldItems);
-        left.addMember(currentItems);
-        left.addMember(exportModes);
-        left.addMember(report);
+        left.addMember(this.oldItems);
+        left.addMember(this.currentItems);
+        left.addMember(this.exportModes);
+        left.addMember(this.report);
 
-        reportPanel = new Canvas();
-        reportPanel.setHeight("*");
-        report.addMember(reportPanel);
+        this.reportPanel = new Canvas();
+        this.reportPanel.setHeight("*");
+        this.report.addMember(this.reportPanel);
 
         rootLayout.addMember(left);
         rootLayout.addMember(createSectionStack());
 
-        topLayout.addMember(rootLayout);
-        if (artifact == null) {
-            Canvas moduleSelection = renderNew();
+        this.topLayout.addMember(rootLayout);
+        if (this.artifact == null) {
+            final Canvas moduleSelection = renderNew();
             moduleSelection.setLayoutAlign(VerticalAlignment.TOP);
-            currentItems.addMember(moduleSelection);
+            this.currentItems.addMember(moduleSelection);
         }
 
-        setPane(topLayout);
+        setPane(this.topLayout);
     }
 
-
     protected SectionStack createSectionStack() {
-        stack = new SectionStack();
-        stack.setHeight100();
-        stack.setCanResizeSections(true);
-        stack.setVisibilityMode(VisibilityMode.MULTIPLE);
-        stack.setOverflow(Overflow.SCROLL);
+        this.stack = new SectionStack();
+        this.stack.setHeight100();
+        this.stack.setCanResizeSections(true);
+        this.stack.setVisibilityMode(VisibilityMode.MULTIPLE);
+        this.stack.setOverflow(Overflow.SCROLL);
 
         // This canvas is used to render helper widgets.
         final SectionStackSection helperSection = new SectionStackSection();
         helperSection.setExpanded(false);
-        helperSection.setTitle(MSG.helperPanelTitle());
-        helperPanel = new VLayout() {
+        helperSection.setTitle(this.MSG.helperPanelTitle());
+        this.helperPanel = new VLayout() {
             @Override
-            public void addMember(Canvas component) {
+            public void addMember(final Canvas component) {
                 super.addMember(component);
-                stack.expandSection(helperSection.getID());
+                ParameterList.this.stack.expandSection(helperSection.getID());
             }
 
             @Override
-            public void removeMembers(Canvas[] components) {
+            public void removeMembers(final Canvas[] components) {
                 super.removeMembers(components);
                 helperSection.setExpanded(false);
             }
         };
-        helperPanel.setWidth100();
-        helperPanel.setHeight100();
-        helperSection.setItems(helperPanel);
+        this.helperPanel.setWidth100();
+        this.helperPanel.setHeight100();
+        helperSection.setItems(this.helperPanel);
 
         // This canvas is used to render calculation results.
         final SectionStackSection tableSection = new SectionStackSection();
         tableSection.setExpanded(false);
-        tableSection.setTitle(MSG.calcTableTitle());
-        tablePanel = new VLayout() {
+        tableSection.setTitle(this.MSG.calcTableTitle());
+        this.tablePanel = new VLayout() {
             @Override
-            public void addMember(Canvas component) {
+            public void addMember(final Canvas component) {
                 super.addMember(component);
                 tableSection.setExpanded(true);
-                if (stack.getSection(InfoPanel.SECTION_ID) != null) {
-                    stack.getSection(InfoPanel.SECTION_ID).setExpanded(false);
+                if (ParameterList.this.stack.getSection(InfoPanel.SECTION_ID) != null) {
+                    ParameterList.this.stack.getSection(InfoPanel.SECTION_ID).setExpanded(false);
                 }
             }
 
             @Override
-            public void removeMembers(Canvas[] components) {
+            public void removeMembers(final Canvas[] components) {
                 super.removeMembers(components);
                 tableSection.setExpanded(false);
             }
         };
-        tablePanel.setHeight100();
-        tablePanel.setWidth100();
-        tableSection.setItems(tablePanel);
+        this.tablePanel.setHeight100();
+        this.tablePanel.setWidth100();
+        tableSection.setItems(this.tablePanel);
 
-        stack.setSections(helperSection, tableSection);
+        this.stack.setSections(helperSection, tableSection);
 
-        return stack;
+        return this.stack;
     }
 
-
     /** Sets and forwards artifact. */
-    protected void setArtifact(Artifact artifact) {
+    protected void setArtifact(final Artifact artifact) {
         setArtifact(artifact, true);
     }
 
-
-    protected void setArtifact(Artifact artifact, boolean forward) {
-        Artifact tmp  = this.artifact;
+    protected void setArtifact(final Artifact artifact, final boolean forward) {
+        final Artifact tmp = this.artifact;
         this.artifact = artifact;
 
         if (forward) {
-            fireParameterChangeEvent(
-                tmp, this.artifact, ParameterChangeEvent.Type.FORWARD);
-        }
-        else {
-            fireParameterChangeEvent(
-                tmp, this.artifact, ParameterChangeEvent.Type.BACK);
+            fireParameterChangeEvent(tmp, this.artifact, ParameterChangeEvent.Type.FORWARD);
+        } else {
+            fireParameterChangeEvent(tmp, this.artifact, ParameterChangeEvent.Type.BACK);
         }
     }
 
-
     /**
      * This method registers a new ParameterChangeHandler.
      *
-     * @param handler The new ParameterChangeHandler.
+     * @param handler
+     *            The new ParameterChangeHandler.
      */
     @Override
-    public void addParameterChangeHandler(ParameterChangeHandler handler) {
+    public void addParameterChangeHandler(final ParameterChangeHandler handler) {
         if (handler != null) {
-            parameterHandlers.add(handler);
+            this.parameterHandlers.add(handler);
         }
     }
 
-
     /**
      * This method calls the <code>onParameterChange()</code> method of all
      * registered ParameterChangeHandler.
      */
-    protected void fireParameterChangeEvent(
-        Artifact old,
-        Artifact newArt,
-        ParameterChangeEvent.Type type)
-    {
-        ParameterChangeEvent e = new ParameterChangeEvent(old, newArt, type);
+    protected void fireParameterChangeEvent(final Artifact old, final Artifact newArt, final ParameterChangeEvent.Type type) {
+        final ParameterChangeEvent e = new ParameterChangeEvent(old, newArt, type);
 
-        for (ParameterChangeHandler handler: parameterHandlers) {
+        for (final ParameterChangeHandler handler : this.parameterHandlers) {
             handler.onParameterChange(e);
         }
     }
 
-
     /**
      * This method creates a Canvas displaying the plugins of FLYS combined with
      * a widget to select a river.
@@ -337,111 +307,99 @@
      * @return a Canvas that displays the supported plugins and rivers of FLYS.
      */
     protected Canvas renderNew() {
-        River[] rivers   = flys.getRivers();
-        DataItem[] items = new DataItem[rivers.length];
+        final River[] rivers = this.flys.getRivers();
+        final DataItem[] items = new DataItem[rivers.length];
 
         int i = 0;
-        for (River river: rivers) {
-            String name = river.getName();
-            String mUuid = river.getModelUuid();
-            items[i++]  = new DefaultDataItem(name, null, mUuid);
+        for (final River river : rivers) {
+            final String name = river.getName();
+            final String mUuid = river.getModelUuid();
+            items[i++] = new DefaultDataItem(name, null, mUuid);
         }
 
-        Data data = new DefaultData(
-            "river",
-            MSG.river_selection(),
-            null,
-            items);
+        final Data data = new DefaultData("river", this.MSG.river_selection(), null, items);
 
-        LinkSelection widget           = new LinkSelection();
-        HasStepForwardHandlers handler = widget;
+        final LinkSelection widget = new LinkSelection();
+        final HasStepForwardHandlers handler = widget;
 
-        widget.setContainer(helperPanel);
+        widget.setContainer(this.helperPanel);
 
         handler.addStepForwardHandler(new StepForwardHandler() {
             private static final long serialVersionUID = -6210719844707004860L;
 
             @Override
-            public void onStepForward(StepForwardEvent event) {
+            public void onStepForward(final StepForwardEvent event) {
                 lockUI();
-                Data[] data = event.getData();
+                final Data[] data = event.getData();
 
-                DataItem[] moduleItems = data[0].getItems();
-                DataItem[] riversItems = data[1].getItems();
+                final DataItem[] moduleItems = data[0].getItems();
+                final DataItem[] riversItems = data[1].getItems();
 
-                String module = moduleItems[0].getStringValue();
-                String river  = riversItems[0].getStringValue();
+                final String module = moduleItems[0].getStringValue();
+                final String river = riversItems[0].getStringValue();
 
                 if (module == null || river == null) {
-                    GWT.log("ParameterList.renderNew(): module == null "
-                        + "|| river == null");
+                    GWT.log("ParameterList.renderNew(): module == null " + "|| river == null");
                     unlockUI();
                     return;
                 }
-
-                String newTitle = MSG.getString(module);
+                final String newTitle = moduleItems[0].getLabel();
                 setTitle(newTitle);
 
-                Config config       = Config.getInstance();
+                final Config config = Config.getInstance();
                 final String locale = config.getLocale();
 
                 final Data[] feedData = new Data[] { data[1] };
 
-                artifactService.create(
-                    locale, module.toLowerCase(), null,
-                    new AsyncCallback<Artifact>() {
-                        @Override
-                        public void onFailure(Throwable caught) {
-                            unlockUI();
-                            GWT.log("Could not create the new artifact.");
-                            SC.warn(FLYS.getExceptionString(MSG, caught));
-                        }
-
-                        @Override
-                        public void onSuccess(Artifact artifact) {
-                            GWT.log("Successfully created a new artifact.");
+                ParameterList.this.artifactService.create(locale, module.toLowerCase(), null, new AsyncCallback<Artifact>() {
+                    @Override
+                    public void onFailure(final Throwable caught) {
+                        unlockUI();
+                        GWT.log("Could not create the new artifact.");
+                        SC.warn(FLYS.getExceptionString(ParameterList.this.MSG, caught));
+                    }
 
-                            forwardService.go(locale, artifact, feedData,
-                            new AsyncCallback<Artifact>() {
-                                @Override
-                                public void onFailure(Throwable caught) {
-                                    unlockUI();
-                                    GWT.log("Could not feed the artifact.");
-                                    SC.warn(caught.getMessage());
-                                }
+                    @Override
+                    public void onSuccess(final Artifact artifact) {
+                        GWT.log("Successfully created a new artifact.");
 
-                                @Override
-                                public void onSuccess(Artifact artifact) {
-                                    GWT.log("Successfully feed the artifact.");
-                                    old.clear();
-                                    cView.addArtifactToCollection(artifact);
-                                    setArtifact(artifact);
-                                    unlockUI();
-                                }
-                            });
-                        }
+                        ParameterList.this.forwardService.go(locale, artifact, feedData, new AsyncCallback<Artifact>() {
+                            @Override
+                            public void onFailure(final Throwable caught) {
+                                unlockUI();
+                                GWT.log("Could not feed the artifact.");
+                                SC.warn(caught.getMessage());
+                            }
+
+                            @Override
+                            public void onSuccess(final Artifact artifact) {
+                                GWT.log("Successfully feed the artifact.");
+                                ParameterList.this.old.clear();
+                                ParameterList.this.cView.addArtifactToCollection(artifact);
+                                setArtifact(artifact);
+                                unlockUI();
+                            }
+                        });
+                    }
                 });
             }
         });
 
-        DataList list = new DataList();
+        final DataList list = new DataList();
         list.add(data);
 
         return widget.create(list);
     }
 
-
     protected void clearOldData() {
-        old.clear();
+        this.old.clear();
     }
 
-
-    public void addOldData(DataList old) {
+    public void addOldData(final DataList old) {
         addOldData(old, true);
     }
 
-
-    public void addOldData(DataList old, boolean redraw) {
+    public void addOldData(final DataList old, final boolean redraw) {
         if (old != null) {
             this.old.add(old);
         }
@@ -449,15 +407,13 @@
         refreshOld(redraw);
     }
 
-
-    public void addOldDatas(DataList[] old) {
+    public void addOldDatas(final DataList[] old) {
         addOldDatas(old, true);
     }
 
-
-    public void addOldDatas(DataList[] old, boolean redraw) {
+    public void addOldDatas(final DataList[] old, final boolean redraw) {
         if (old != null && old.length > 0) {
-            for (DataList o: old) {
+            for (final DataList o : old) {
                 if (o == null) {
                     continue;
                 }
@@ -478,15 +434,14 @@
         addOldData(null, true);
     }
 
-
-    public boolean exists(DataList data) {
+    public boolean exists(final DataList data) {
         if (data == null) {
             return false;
         }
 
-        String stateName = data.getState();
+        final String stateName = data.getState();
 
-        for (DataList o: old) {
+        for (final DataList o : this.old) {
             if (stateName.equals(o.getState())) {
                 return true;
             }
@@ -495,34 +450,29 @@
         return false;
     }
 
-
-    public void setCurrentData(DataList current, UIProvider uiProvider) {
-        this.current    = current;
+    public void setCurrentData(final DataList current, final UIProvider uiProvider) {
+        this.current = current;
         this.uiProvider = uiProvider;
 
         refreshCurrent();
     }
 
-
-    public void refreshOld(boolean redrawAll) {
+    public void refreshOld(final boolean redrawAll) {
         if (redrawAll) {
             refreshAllOld();
-        }
-        else {
-            DataList dataList = old.get(old.size()-1);
-            String   state    = dataList.getState();
+        } else {
+            final DataList dataList = this.old.get(this.old.size() - 1);
+            final String state = dataList.getState();
 
-            if (oldStorage.get(state) == null) {
-                String     provider   = dataList.getUIProvider();
-                UIProvider uiprovider = UIProviderFactory.getProvider(
-                    provider,
-                    flys.getCurrentUser());
+            if (this.oldStorage.get(state) == null) {
+                final String provider = dataList.getUIProvider();
+                final UIProvider uiprovider = UIProviderFactory.getProvider(provider, this.flys.getCurrentUser());
                 ((HasStepBackHandlers) uiprovider).addStepBackHandler(this);
 
-                Canvas c = uiprovider.createOld(dataList);
+                final Canvas c = uiprovider.createOld(dataList);
                 if (c != null) {
-                    oldStorage.put(dataList.getState(), c);
-                    oldItems.addMember(c);
+                    this.oldStorage.put(dataList.getState(), c);
+                    this.oldItems.addMember(c);
                 }
             }
         }
@@ -530,276 +480,255 @@
         updateOldHeight();
     }
 
-
     protected void refreshAllOld() {
-        List<String> not = new ArrayList<String>();
+        final List<String> not = new ArrayList<String>();
 
-        for (DataList data: old) {
-            String state = data.getState();
+        for (final DataList data : this.old) {
+            final String state = data.getState();
 
-            Canvas c = oldStorage.get(state);
+            final Canvas c = this.oldStorage.get(state);
 
             if (c != null) {
                 not.add(state);
             }
         }
 
-        Map<String, Canvas> newOld = new TreeMap<String, Canvas>();
+        final Map<String, Canvas> newOld = new TreeMap<String, Canvas>();
 
-        Set<Map.Entry<String, Canvas>> entries = oldStorage.entrySet();
-        for (Map.Entry<String, Canvas> entry: entries) {
-            String state = entry.getKey();
-            Canvas value = entry.getValue();
+        final Set<Map.Entry<String, Canvas>> entries = this.oldStorage.entrySet();
+        for (final Map.Entry<String, Canvas> entry : entries) {
+            final String state = entry.getKey();
+            final Canvas value = entry.getValue();
 
             if (not.indexOf(state) < 0) {
-                oldItems.removeMember(value);
-            }
-            else {
+                this.oldItems.removeMember(value);
+            } else {
                 newOld.put(state, value);
             }
         }
 
-        oldStorage = newOld;
+        this.oldStorage = newOld;
     }
 
-
     protected void updateOldHeight() {
-        int minHeight = oldItems.getMinHeight();
+        final int minHeight = this.oldItems.getMinHeight();
         if (minHeight <= 20) {
-            oldItems.setHeight(20);
-        }
-        else {
-            oldItems.setHeight(minHeight);
+            this.oldItems.setHeight(20);
+        } else {
+            this.oldItems.setHeight(minHeight);
         }
     }
 
-
     /**
      * Refreshes the part displaying the data of the current state.
      * The UI is created using the UIProvider stored in the Data object.
      */
     public void refreshCurrent() {
-        currentItems.removeMembers(currentItems.getMembers());
+        this.currentItems.removeMembers(this.currentItems.getMembers());
 
-        if (current != null && uiProvider != null) {
-            Canvas c = uiProvider.create(current);
-            Canvas h = uiProvider.createHelpLink(current, null, this.flys);
+        if (this.current != null && this.uiProvider != null) {
+            final Canvas c = this.uiProvider.create(this.current);
+            final Canvas h = this.uiProvider.createHelpLink(this.current, null, this.flys);
 
-            HLayout wrapper = new HLayout();
+            final HLayout wrapper = new HLayout();
             wrapper.addMember(h);
             wrapper.addMember(c);
 
-            currentItems.addMember(wrapper);
-        }
-        else if (uiProvider != null) {
-            Canvas c = uiProvider.create(null);
+            this.currentItems.addMember(wrapper);
+        } else if (this.uiProvider != null) {
+            final Canvas c = this.uiProvider.create(null);
             c.setLayoutAlign(VerticalAlignment.TOP);
 
-            currentItems.addMember(c);
-        }
-        else {
-            currentItems.setHeight(1);
+            this.currentItems.addMember(c);
+        } else {
+            this.currentItems.setHeight(1);
         }
 
-        Canvas[] members = currentItems.getMembers();
+        final Canvas[] members = this.currentItems.getMembers();
         if (members == null || members.length == 0) {
-            currentItems.setHeight(1);
-        }
-        else {
+            this.currentItems.setHeight(1);
+        } else {
             int height = 0;
 
-            for (Canvas member: members) {
+            for (final Canvas member : members) {
                 height += member.getHeight();
             }
 
-            currentItems.setHeight(height);
+            this.currentItems.setHeight(height);
         }
     }
 
-
     /**
      * This method is called if the user clicks on the 'next' button to advance
      * to the next state.
      *
-     * @param event The StepForwardEvent.
+     * @param event
+     *            The StepForwardEvent.
      */
     @Override
-    public void onStepForward(StepForwardEvent event) {
+    public void onStepForward(final StepForwardEvent event) {
         GWT.log("CollectionView - onStepForward()");
         lockUI();
 
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-        forwardService.go(locale, artifact, event.getData(),
-            new AsyncCallback<Artifact>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    unlockUI();
-                    GWT.log("Could not feed the artifact.");
-                    SC.warn(FLYS.getExceptionString(MSG, caught));
-                }
+        this.forwardService.go(locale, this.artifact, event.getData(), new AsyncCallback<Artifact>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                unlockUI();
+                GWT.log("Could not feed the artifact.");
+                SC.warn(FLYS.getExceptionString(ParameterList.this.MSG, caught));
+            }
 
-                @Override
-                public void onSuccess(Artifact artifact) {
-                    GWT.log("Successfully feed the artifact.");
-                    old.clear();
+            @Override
+            public void onSuccess(final Artifact artifact) {
+                GWT.log("Successfully feed the artifact.");
+                ParameterList.this.old.clear();
 
-                    setArtifact(artifact, true);
-                    unlockUI();
-                }
+                setArtifact(artifact, true);
+                unlockUI();
+            }
         });
     }
 
-
     /**
      * This method is used to remove all old items from this list after the user
      * has clicked the step back button.
      *
-     * @param e The StepBackEvent that holds the identifier of the target state.
+     * @param e
+     *            The StepBackEvent that holds the identifier of the target state.
      */
     @Override
-    public void onStepBack(StepBackEvent e) {
+    public void onStepBack(final StepBackEvent e) {
         lockUI();
-        final String target    = e.getTarget();
-
-        Config config          = Config.getInstance();
-        final String locale    = config.getLocale();
+        final String target = e.getTarget();
 
-        advanceService.advance(locale, artifact, target,
-            new AsyncCallback<Artifact>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    unlockUI();
-                    GWT.log("Could not go back to '" + target + "'");
-                    SC.warn(FLYS.getExceptionString(MSG, caught));
-                }
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-                @Override
-                public void onSuccess(Artifact artifact) {
-                    GWT.log("Successfully step back to '" + target + "'");
-
-                    old.clear();
+        this.advanceService.advance(locale, this.artifact, target, new AsyncCallback<Artifact>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                unlockUI();
+                GWT.log("Could not go back to '" + target + "'");
+                SC.warn(FLYS.getExceptionString(ParameterList.this.MSG, caught));
+            }
 
-                    setArtifact(artifact, false);
-                    unlockUI();
-                }
+            @Override
+            public void onSuccess(final Artifact artifact) {
+                GWT.log("Successfully step back to '" + target + "'");
+
+                ParameterList.this.old.clear();
+
+                setArtifact(artifact, false);
+                unlockUI();
             }
-        );
+        });
     }
 
-
     @Override
     public void onAdvance(final String target) {
-        Config config          = Config.getInstance();
-        final String locale    = config.getLocale();
-
-        advanceService.advance(locale, artifact, target,
-            new AsyncCallback<Artifact>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Could not go to '" + target + "'");
-                    SC.warn(FLYS.getExceptionString(MSG, caught));
-                }
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-                @Override
-                public void onSuccess(Artifact artifact) {
-                    GWT.log("Successfully advanced to '" + target + "'");
-
-                    old.clear();
+        this.advanceService.advance(locale, this.artifact, target, new AsyncCallback<Artifact>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Could not go to '" + target + "'");
+                SC.warn(FLYS.getExceptionString(ParameterList.this.MSG, caught));
+            }
 
-                    setArtifact(artifact, true);
-                }
+            @Override
+            public void onSuccess(final Artifact artifact) {
+                GWT.log("Successfully advanced to '" + target + "'");
+
+                ParameterList.this.old.clear();
+
+                setArtifact(artifact, true);
             }
-        );
+        });
     }
 
-
     /**
      * Implements the onCollectionChange() method to do update the GUI after the
      * parameterization has changed.
      *
-     * @param event The ParameterChangeEvent.
+     * @param event
+     *            The ParameterChangeEvent.
      */
     @Override
-    public void onParameterChange(ParameterChangeEvent event) {
+    public void onParameterChange(final ParameterChangeEvent event) {
         GWT.log("ParameterList.onParameterChange");
 
-        Canvas[] c = helperPanel.getMembers();
+        final Canvas[] c = this.helperPanel.getMembers();
         if (c != null && c.length > 0) {
-            helperPanel.removeMembers(c);
+            this.helperPanel.removeMembers(c);
         }
 
-        Artifact art             = event.getNewValue();
-        ArtifactDescription desc = art.getArtifactDescription();
+        final Artifact art = event.getNewValue();
+        final ArtifactDescription desc = art.getArtifactDescription();
 
-        DataList currentData = desc.getCurrentData();
+        final DataList currentData = desc.getCurrentData();
         if (currentData != null) {
             // the user has to enter some attributes
-            String uiProvider   = currentData.getUIProvider();
-            UIProvider provider = UIProviderFactory.getProvider(
-                uiProvider,
-                flys.getCurrentUser());
+            final String uiProvider = currentData.getUIProvider();
+            final UIProvider provider = UIProviderFactory.getProvider(uiProvider, this.flys.getCurrentUser());
 
-            provider.setContainer(helperPanel);
+            provider.setContainer(this.helperPanel);
             provider.setArtifact(art);
-            provider.setCollection(cView.getCollection());
+            provider.setCollection(this.cView.getCollection());
             provider.setParameterList(this);
 
             ((HasStepForwardHandlers) provider).addStepForwardHandler(this);
             ((HasStepBackHandlers) provider).addStepBackHandler(this);
 
             setCurrentData(currentData, provider);
-        }
-        else {
-            String[] reachable = desc.getReachableStates();
+        } else {
+            final String[] reachable = desc.getReachableStates();
             if (reachable != null && reachable.length > 0) {
                 // We have reached a final state with the option to step to
                 // further to a next state. But in the current state, no user
                 // data is required.
-                UIProvider ui = UIProviderFactory.getProvider("continue", null);
+                final UIProvider ui = UIProviderFactory.getProvider("continue", null);
                 ui.setArtifact(art);
-                ui.setCollection(cView.getCollection());
+                ui.setCollection(this.cView.getCollection());
                 ui.setParameterList(this);
 
                 ((ContinuePanel) ui).addAdvanceHandler(this);
 
                 setCurrentData(null, ui);
-            }
-            else {
+            } else {
                 // we have reached a final state with no more user input
                 setCurrentData(null, null);
             }
         }
-        if (art instanceof WINFOArtifact
-                || art instanceof FixAnalysisArtifact) {
+
+        // 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 SINFOArtifact || art instanceof UINFOArtifact || art instanceof AbstractFixBunduArtifact) {
             createGaugePanel();
             renderInfo(desc.getRiver(), desc.getOldData());
-        }
-        else if (art instanceof MINFOArtifact) {
+        } else if (art instanceof MINFOArtifact) {
             createMeasurementStationPanel();
             renderInfo(desc.getRiver(), desc.getOldData());
-        }
-        else {
+        } else {
             removeInfoPanel();
         }
 
-        addOldDatas(
-            desc.getOldData(),
-            event.getType() == ParameterChangeEvent.Type.BACK);
+        addOldDatas(desc.getOldData(), event.getType() == ParameterChangeEvent.Type.BACK);
     }
 
-
     @Override
-    public void onCollectionChange(CollectionChangeEvent event) {
-        Collection                 c = event.getNewValue();
-        Map<String, OutputMode> outs = c.getOutputModes();
-        Set<String>             keys = outs.keySet();
+    public void onCollectionChange(final CollectionChangeEvent event) {
+        final Collection c = event.getNewValue();
+        final Map<String, OutputMode> outs = c.getOutputModes();
+        final Set<String> keys = outs.keySet();
 
-        OutputMode[] outputs = new OutputMode[outs.size()];
+        final OutputMode[] outputs = new OutputMode[outs.size()];
 
         int idx = 0;
-        for (String outname: keys) {
+        for (final String outname : keys) {
             outputs[idx++] = outs.get(outname);
         }
 
@@ -807,46 +736,43 @@
         updateReportModes(c, getReportModes(outputs));
     }
 
-
     @Override
-    public void onOutputModesChange(OutputModesChangeEvent event) {
+    public void onOutputModesChange(final OutputModesChangeEvent event) {
 
-        Collection c = cView.getCollection();
+        final Collection c = this.cView.getCollection();
 
         if (c != null) {
-            OutputMode [] outs = event.getOutputModes();
+            final OutputMode[] outs = event.getOutputModes();
             updateExportModes(c, getExportModes(outs));
             updateReportModes(c, getReportModes(outs));
         }
     }
 
+    protected List<ReportMode> getReportModes(final OutputMode[] outs) {
 
-    protected List<ReportMode> getReportModes(OutputMode [] outs) {
-
-        List<ReportMode> reports = new ArrayList<ReportMode>();
+        final List<ReportMode> reports = new ArrayList<ReportMode>();
 
         if (outs == null || outs.length == 0) {
             return reports;
         }
 
-        for (OutputMode out: outs) {
+        for (final OutputMode out : outs) {
             if (out instanceof ReportMode) {
-                reports.add((ReportMode)out);
+                reports.add((ReportMode) out);
             }
         }
 
         return reports;
     }
 
-
-    protected List<ExportMode> getExportModes(OutputMode[] outs) {
-        List<ExportMode> exports = new ArrayList<ExportMode>();
+    protected List<ExportMode> getExportModes(final OutputMode[] outs) {
+        final List<ExportMode> exports = new ArrayList<ExportMode>();
 
         if (outs == null || outs.length == 0) {
             return exports;
         }
 
-        for (OutputMode out: outs) {
+        for (final OutputMode out : outs) {
             if (out instanceof ExportMode) {
                 exports.add((ExportMode) out);
             }
@@ -855,129 +781,119 @@
         return exports;
     }
 
-
-    protected void updateExportModes(Collection c, List<ExportMode> exports) {
-        int num = exports != null ? exports.size() : 0;
+    protected void updateExportModes(final Collection c, final List<ExportMode> exports) {
+        final int num = exports != null ? exports.size() : 0;
         GWT.log("Update export modes: " + num);
 
-        exportModes.removeMembers(exportModes.getMembers());
+        this.exportModes.removeMembers(this.exportModes.getMembers());
 
         if (exports.size() > 0) {
-            exportModes.addMember(new ExportPanel(c, exports));
-        }
-        else {
-            exportModes.setHeight(1);
+            this.exportModes.addMember(new ExportPanel(c, exports));
+        } else {
+            this.exportModes.setHeight(1);
         }
     }
 
-    protected void updateReportModes(Collection c, List<ReportMode> reports) {
-        int num = reports != null ? reports.size() : 0;
+    protected void updateReportModes(final Collection c, final List<ReportMode> reports) {
+        final int num = reports != null ? reports.size() : 0;
         GWT.log("Update report modes: " + num);
 
         if (num == 0) {
-            reportPanel.setContents("");
+            this.reportPanel.setContents("");
             return;
         }
 
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-        String cid = c.identifier();
+        final String cid = c.identifier();
 
-        for (ReportMode report: reports) {
+        for (final ReportMode report : reports) {
             GWT.log("report '" + report.toString() + "'");
 
-            reportService.report(cid, locale, report.getName(),
-                new AsyncCallback<String>() {
-                    @Override
-                    public void onFailure(Throwable caught) {
-                        SC.warn(FLYS.getExceptionString(MSG, caught));
-                    }
+            this.reportService.report(cid, locale, report.getName(), new AsyncCallback<String>() {
+                @Override
+                public void onFailure(final Throwable caught) {
+                    SC.warn(FLYS.getExceptionString(ParameterList.this.MSG, caught));
+                }
 
-                    @Override
-                    public void onSuccess(String msg) {
-                        setReportMessage(msg);
-                    }
-                });
+                @Override
+                public void onSuccess(final String msg) {
+                    setReportMessage(msg);
+                }
+            });
         }
     }
 
-
     /** Sets content of reportPanel. */
     protected void setReportMessage(String msg) {
         GWT.log("returned from service: " + msg);
         if (msg == null) {
             msg = "";
         }
-        reportPanel.setContents(msg);
+        this.reportPanel.setContents(msg);
     }
 
-
     /**
      * Adds a table to the parameterlist to show calculated data.
      *
-     * @param table The table data panel.
+     * @param table
+     *            The table data panel.
      */
-    public void setTable(TableDataPanel table) {
+    public void setTable(final TableDataPanel table) {
         removeTable();
 
-        Canvas c = table.create();
+        final Canvas c = table.create();
         c.setHeight100();
         c.setWidth100();
 
-        tablePanel.addMember(c);
+        this.tablePanel.addMember(c);
     }
 
-
     public boolean hasTable() {
-        Canvas[] members = tablePanel.getMembers();
+        final Canvas[] members = this.tablePanel.getMembers();
 
         return members != null && members.length > 0;
     }
 
-
     /**
      * Removes the table from the parameter list.
      */
     public void removeTable() {
-        Canvas[] members = tablePanel.getMembers();
+        final Canvas[] members = this.tablePanel.getMembers();
 
         if (members != null && members.length > 0) {
-            tablePanel.removeMembers(members);
+            this.tablePanel.removeMembers(members);
         }
     }
 
-
-    public void registerCollectionViewTabHandler(TabSelectedHandler tsh) {
+    public void registerCollectionViewTabHandler(final TabSelectedHandler tsh) {
         this.cView.registerTabHandler(tsh);
     }
 
-
     protected void lockUI() {
-        cView.lockUI();
+        this.cView.lockUI();
     }
 
-
     protected void unlockUI() {
-        cView.unlockUI();
+        this.cView.unlockUI();
     }
 
-
     private void createGaugePanel() {
         GWT.log("ParameterList - createGaugePanel");
-        if (infoPanel == null) {
-            infoPanel = new GaugePanel(flys);
-            infoPanel.setWidth100();
-            infoPanel.setHeight100();
+        if (this.infoPanel == null) {
+            this.infoPanel = new GaugePanel(this.flys);
+            this.infoPanel.setWidth100();
+            this.infoPanel.setHeight100();
         }
     }
 
     private void createMeasurementStationPanel() {
         GWT.log("ParameterList - createMeasurementStationPanel");
-        if (infoPanel == null) {
-            infoPanel = new MeasurementStationPanel(flys);
-            infoPanel.setWidth100();
-            infoPanel.setHeight100();
+        if (this.infoPanel == null) {
+            this.infoPanel = new MeasurementStationPanel(this.flys);
+            this.infoPanel.setWidth100();
+            this.infoPanel.setHeight100();
         }
     }
 
@@ -985,14 +901,14 @@
         GWT.log("ParameterList - showInfoPanel");
 
         /* Don't add InfoPanel twice */
-        SectionStackSection info = stack.getSection(InfoPanel.SECTION_ID);
+        SectionStackSection info = this.stack.getSection(InfoPanel.SECTION_ID);
         if (info == null) {
             info = new SectionStackSection();
-            info.setTitle(infoPanel.getSectionTitle());
+            info.setTitle(this.infoPanel.getSectionTitle());
             info.setID(InfoPanel.SECTION_ID);
             info.setName(InfoPanel.SECTION_ID);
-            info.setItems(infoPanel);
-            stack.addSection(info, 0);
+            info.setItems(this.infoPanel);
+            this.stack.addSection(info, 0);
         }
 
         info.setExpanded(true);
@@ -1001,29 +917,27 @@
     private void hideInfoPanel() {
         GWT.log("ParameterList - hideInfoPanel");
 
-        if (infoPanel != null) {
-            infoPanel.hide();
+        if (this.infoPanel != null) {
+            this.infoPanel.hide();
         }
     }
 
     private void removeInfoPanel() {
         GWT.log("ParameterList - removeInfoPanel");
-        SectionStackSection exists = stack.getSection(InfoPanel.SECTION_ID);
+        final SectionStackSection exists = this.stack.getSection(InfoPanel.SECTION_ID);
         if (exists != null) {
-            stack.removeSection(InfoPanel.SECTION_ID);
+            this.stack.removeSection(InfoPanel.SECTION_ID);
         }
     }
 
-
-    private void renderInfo(String river, DataList[] data) {
+    private void renderInfo(final String river, final DataList[] data) {
         GWT.log("ParameterList - renderInfo");
 
         if (river != null) {
             showInfoPanel();
-            infoPanel.setRiver(river);
-            infoPanel.setData(data);
-        }
-        else {
+            this.infoPanel.setRiver(river);
+            this.infoPanel.setData(data);
+        } else {
             GWT.log("ParameterList - renderInfo no river");
             hideInfoPanel();
         }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/RadioPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/RadioPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,14 +8,8 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
 import org.dive4elements.river.client.shared.model.Data;
 import org.dive4elements.river.client.shared.model.DataItem;
@@ -23,7 +17,13 @@
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 
-import java.util.LinkedHashMap;
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
 
 public class RadioPanel extends AbstractUIProvider {
 
@@ -31,19 +31,20 @@
 
     protected String dataName;
     protected DynamicForm form;
+    private final Map<String, String> valueLabelMap = new LinkedHashMap<String, String>();
 
     @Override
-    public Canvas createOld(DataList dataList) {
-        Data       data  = dataList.get(0);
-        DataItem[] items = data.getItems();
-
-        HLayout layout = new HLayout();
-        Label   label  = new Label(dataList.getLabel());
-        Label   value  = new Label(items[0].getLabel());
-
+    public Canvas createOld(final DataList dataList) {
+        final Data data = dataList.get(0);
+        final DataItem[] items = data.getItems();
+        // hat Einfluss auf Layout in der Übersicht (oben) nach Setzen des Wertes für den State
+        final HLayout layout = new HLayout();
+        final Label label = new Label(dataList.getLabel());
+        final Label value = new Label(items[0].getLabel());
+        layout.setWidth(400);
+        label.setWidth(200); // nicht ändern; scheint wohl ne Konstante zu sein!
+        value.setWidth(180); // änderbar
         layout.setHeight(35);
-        layout.setWidth(400);
-        label.setWidth(200);
 
         layout.addMember(label);
         layout.addMember(value);
@@ -53,52 +54,60 @@
     }
 
     @Override
-    public Canvas create(DataList dataList) {
-        Data       data  = dataList.get(0);
-        DataItem[] items = data.getItems();
+    public Canvas create(final DataList dataList) {
+        final Data data = dataList.get(0);
+        final DataItem[] items = data.getItems();
 
         this.dataName = data.getLabel();
 
-        VLayout layout = new VLayout();
-        Label   label  = new Label(data.getDescription());
-        RadioGroupItem rgi = new RadioGroupItem("selection");
+        final VLayout layout = new VLayout();
+        final Label label = new Label(data.getDescription());
+        label.setWrap(false);
+        final RadioGroupItem rgi = new RadioGroupItem("selection");
+        rgi.setWrapTitle(false);
+        rgi.setWrap(false);
         rgi.setShowTitle(false);
         GWT.log("items: " + items.length);
-        LinkedHashMap<String, String> elems =
-            new LinkedHashMap<String, String>();
-        for (int i = 0; i < items.length; i++) {
-            GWT.log(items[i].getStringValue() + "; " + items[i].getLabel());
-            elems.put(items[i].getStringValue(), items[i].getLabel());
+        final LinkedHashMap<String, String> elems = new LinkedHashMap<String, String>();
+        for (final DataItem item : items) {
+            GWT.log(item.getStringValue() + "; " + item.getLabel());
+            elems.put(item.getStringValue(), item.getLabel());
+            this.valueLabelMap.put(item.getStringValue(), item.getLabel());
         }
         rgi.setValueMap(elems);
         rgi.setDefaultValue(items[0].getStringValue());
 
-        form = new DynamicForm();
-        form.setFields(rgi);
+        this.form = new DynamicForm();
+        this.form.setFields(rgi);
         layout.setMembersMargin(10);
         layout.setHeight(35);
         label.setHeight(35);
+        layout.setWidth(300);
+        label.setWidth(300);
 
         layout.addMember(label);
-        layout.addMember(form);
+        layout.addMember(this.form);
         layout.addMember(getNextButton());
         layout.setMembersMargin(10);
 
-        //initDefaultValues(dataList);
+        // initDefaultValues(dataList);
 
         return layout;
     }
 
     @Override
     protected Data[] getData() {
-        String value = form.getValueAsString("selection");
-        DataItem item = new DefaultDataItem(
-            this.dataName, this.dataName, value);
-        return new Data[] { new DefaultData(
-            this.dataName, null, null, new DataItem[]{item})};
+        final String value = this.form.getValueAsString("selection");
+
+        final DataItem item = new DefaultDataItem("label_irrelevant", "description_irrelevant", value);
+        // Alles hoffnungslos:
+        // final DataItem useHeader = new DefaultDataItem("label_irrelevant", "description_irrelevant",
+        // this.valueLabelMap.get(value));
+
+        return new Data[] { new DefaultData(this.dataName, "label_no_effect", "description_no_effect", new DataItem[] { item // , useHeader
+                })
+                // ,new DefaultData("value", "label", "description", new DataItem[] { useHeader }) DOES NOT WORK
+        };
     }
 
-    protected String getTitle(DataItem item) {
-        return item.getLabel();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/RecommandationUtils.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,58 @@
+/** 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;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.dive4elements.river.client.client.ui.AbstractPairRecommendationPanel.IRecommendationInfo;
+import org.dive4elements.river.client.shared.model.Recommendation;
+import org.dive4elements.river.client.shared.model.Recommendation.Facet;
+import org.dive4elements.river.client.shared.model.Recommendation.Filter;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class RecommandationUtils {
+    /**
+     * Creates part of the String that encodes minuend or subtrahend.
+     * 
+     * @param recommendation
+     *            Recommendation to wrap in string.
+     * @param info
+     *            Provides the factory to encode.
+     */
+    public static final String createDataString(final String artifactUuid, final Recommendation recommendation, final IRecommendationInfo info) {
+        final String factory = info.getDataStringFactory(recommendation);
+
+        final Filter filter = recommendation.getFilter();
+        Facet f = null;
+
+        if (filter != null) {
+            final Map<String, List<Facet>> outs = filter.getOuts();
+            final Set<Map.Entry<String, List<Facet>>> entries = outs.entrySet();
+
+            for (final Map.Entry<String, List<Facet>> entry : entries) {
+                final List<Facet> fs = entry.getValue();
+
+                f = fs.get(0);
+                if (f != null) {
+                    break;
+                }
+            }
+
+            return "[" + artifactUuid + ";" + f.getName() + ";" + f.getIndex() + ";" + recommendation.getDisplayName() + "]";
+        }
+
+        return "[" + artifactUuid + ";" + factory + ";0;" + recommendation.getDisplayName() + "]";
+    }
+}
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/StyleEditorWindow.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/StyleEditorWindow.java	Fri Jul 13 11:56:22 2018 +0200
@@ -294,6 +294,7 @@
 
         // Done via array to keep the order.
         String[] sets = {"showlines",
+                         "showborder",
                          "showpoints",
                          "linetype",
                          "linesize",
@@ -372,6 +373,7 @@
      * @return The dynamic form for the attribute property.
      */
     protected DynamicForm createPropertyUI(
+        // FIXME: display name (which comes from the server side) is not used but i10n happens on client side,, 
         String dname,
         String name,
         String type,
@@ -535,6 +537,9 @@
             f.setValueMap(valueMap);
             f.setValue(value);
         }
+        else if (type.equals("areapattern")) {
+            f = createAreaPetternUi(name, value);
+        }
         else if (type.equals("font")) {
             f = new SelectItem(name, MSG.getString(name));
             LinkedHashMap<String, String> valueMap =
@@ -587,6 +592,38 @@
     }
 
 
+    private FormItem createAreaPetternUi(String name, String value) {
+        final FormItem f = new SelectItem(name, MSG.getString(name));
+        
+        f.setImageURLPrefix(GWT.getHostPageBaseURL() + "images/areapattern-");
+        f.setImageURLSuffix(".png");
+        f.setValueIconHeight(20);
+        f.setValueIconWidth(80);
+
+        final LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
+        final Map<String, String> valueIcons = new LinkedHashMap<String, String>();
+
+        // FIXME: ugly, using knowledge of available patterns at this point, creating redundancy with AreaFillPattern enum.
+        // But the whole code does it like that, so this is 'flys style'
+        final String[] patterns = new String[] {"patternFill", //
+                                                "patternPoints", //
+                                                "paternCross", //
+                                                "patternDagonalLeft", //
+                                                "patternDiagonalRight"};
+
+        for (int i = 0; i < patterns.length; i++) {
+            final String pattern = patterns[i];
+
+            valueMap.put(pattern, "");
+            valueIcons.put(pattern, pattern);
+        }
+
+        f.setValueIcons(valueIcons);
+        f.setValueMap(valueMap);
+        f.setValue(value);
+        return f;
+    }
+
     protected FormItem createLineSizeUI(FormItem f) {
         LinkedHashMap<String, String> valueIcons =
             new LinkedHashMap<String, String>();
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/TableDataPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/TableDataPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,17 +8,9 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.NumberFormat;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import com.smartgwt.client.types.ListGridFieldType;
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.grid.ListGrid;
-import com.smartgwt.client.widgets.grid.ListGridField;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-import com.smartgwt.client.widgets.layout.VLayout;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYSConstants;
@@ -26,20 +18,29 @@
 import org.dive4elements.river.client.client.services.CSVExportServiceAsync;
 import org.dive4elements.river.client.shared.model.DataList;
 
-import java.util.List;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.Tab;
+import com.smartgwt.client.widgets.tab.TabSet;
 
 /**
  * This UIProvider creates a widget that displays calculated data in a table.
  *
  * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public class TableDataPanel
-{
+public class TableDataPanel {
     /** The message class that provides i18n strings. */
     protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
 
-    protected CSVExportServiceAsync exportService =
-        GWT.create(CSVExportService.class);
+    protected CSVExportServiceAsync exportService = GWT.create(CSVExportService.class);
 
     /** A container that will contain the location or the distance panel. */
     protected VLayout container;
@@ -53,115 +54,140 @@
     /** The table. */
     protected ListGrid dataTable;
 
+    private final TabSet tabSet;
 
     /**
      * Creates a new TableDataPanel instance.
      */
     public TableDataPanel() {
-        container = new VLayout();
-        dataTable = new ListGrid();
-        name      = "";
+        this.container = new VLayout();
+        this.dataTable = new ListGrid();
+        this.tabSet = new TabSet();
+        this.name = "";
     }
 
-
     /**
      * This method creates a widget that contains a table.
      *
      * @return a panel.
      */
     public Canvas create() {
-        Config config    = Config.getInstance();
-        String locale    = config.getLocale ();
-        dataTable.setEmptyMessage(MESSAGES.empty_table());
-        dataTable.setShowHeaderContextMenu(false);
-        dataTable.setCanDragSelectText(true);
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
+        this.dataTable.setEmptyMessage(this.MESSAGES.empty_table());
+        this.dataTable.setShowHeaderContextMenu(false);
+        this.dataTable.setCanDragSelectText(true);
 
-        exportService.getCSV(locale, uuid, name,
-            new AsyncCallback<List<String[]>>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Could not receive csv.");
-                    SC.warn(caught.getMessage());
-                }
+        this.exportService.getCSV(locale, this.uuid, this.name, new AsyncCallback<List<String[]>>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Could not receive csv.");
+                SC.warn(caught.getMessage());
+            }
 
-                @Override
-                public void onSuccess(List<String[]> l) {
-                    GWT.log("Recieved csv with " + l.size() + " lines.");
-                    setData(l);
-                }
+            @Override
+            public void onSuccess(final List<String[]> l) {
+                GWT.log("Recieved csv with " + l.size() + " lines.");
+                setData(l);
             }
-        );
+        });
+        this.container.addMember(this.dataTable);
 
-        container.addMember(dataTable);
-
-        return container;
+        return this.container;
     }
 
-
-    public void setName(String name) {
-      this.name = name;
+    public void setName(final String name) {
+        this.name = name;
     }
 
-    public void setUuid(String uuid) {
-      this.uuid = uuid;
+    public void setUuid(final String uuid) {
+        this.uuid = uuid;
     }
 
-
-    public Canvas createOld(DataList dataList) {
+    public Canvas createOld(final DataList dataList) {
         return null;
     }
 
-
-    protected Canvas createWidget(DataList data) {
+    protected Canvas createWidget(final DataList data) {
         return null;
     }
 
-
     /**
      * This method sets the data to a dynamic table.
      *
-     * @param list List of String[] containing the data.
+     * @param list
+     *            List of String[] containing the data.
      */
-    public void setData(List<String[]> list) {
+
+    public void setData(final List<String[]> list) {
         if (list == null || list.size() < 2) {
-            dataTable.setEmptyMessage(MESSAGES.error_no_calc_result());
-            dataTable.redraw();
+            this.dataTable.setEmptyMessage(this.MESSAGES.error_no_calc_result());
+            this.dataTable.redraw();
             return;
         }
 
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
         NumberFormat nf;
         if (locale.equals("de")) {
             nf = NumberFormat.getFormat("#,##");
-        }
-        else {
+        } else {
             nf = NumberFormat.getFormat("#.##");
         }
-
-        String[] header      = list.get(0);
-        String[] displayField = new String[header.length];
+        final Map<String, List<String[]>> tabData = getTabData(list);
+        if (tabData.size() == 1) {
+            createTable(this.dataTable, tabData.get(tabData.keySet().iterator().next()), nf, 0);
 
-        ListGridField[] fields = new ListGridField[header.length];
+        } else if (tabData.size() > 1) {
 
-        for(int i = 0; i < header.length; i++) {
-            ListGridField f = new ListGridField(String.valueOf(i));
+            final int index = 0;
+            for (final String key : tabData.keySet()) {
+                final List<String[]> items = tabData.get(key);
+
+                final ListGrid table = new ListGrid();
+
+                createTable(table, items, nf, index);
+                final Tab tab = new Tab();
+                tab.setTitle(key);
+                tab.setPane(table);
+                this.tabSet.addTab(tab);
+            }
+            this.tabSet.selectTab(0);
+            this.container.removeChild(this.dataTable);
+            this.container.addChild(this.tabSet);
+            this.tabSet.setWidth100();
+            this.tabSet.setHeight100();
+        }
+    }
+
+    private void createTable(final ListGrid dataTableTab, final List<String[]> list, final NumberFormat nf, final int tabNumber) {
+
+        final String[] header = list.get(0);
+        final String[] displayField = new String[header.length];
+
+        final ListGridField[] fields = new ListGridField[header.length];
+
+        for (int i = 0; i < header.length; i++) {
+            final ListGridField f = new ListGridField(String.valueOf(i));
             fields[i] = f;
             f.setTitle(header[i]);
 
             try {
-                /* Try to determine the type with the first
-                 * non empty element. */
+                /*
+                 * Try to determine the type with the first
+                 * non empty element. -> WARUM??! OK, nur Formatierung/Sortierung
+                 */
                 for (int j = 1; j < list.size(); j++) {
                     if (!list.get(j)[i].isEmpty()) {
                         nf.parse(list.get(j)[i]);
                         f.setType(ListGridFieldType.FLOAT);
+
                         break;
                     }
                 }
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 f.setType(ListGridFieldType.TEXT);
             }
 
@@ -169,35 +195,85 @@
             // float values, we will store the value once formatted 'as is'
             // to be displayed and once as e.g. float to allow functions like
             // sorting on it.
-            displayField[i] = i + "_displayField";
+            displayField[i] = "$" + i + "_displayField";
             f.setDisplayField(displayField[i]);
             f.setValueField(String.valueOf(i));
             f.setSortByDisplayField(false);
         }
-
-        dataTable.setFields(fields);
+        dataTableTab.setFields(fields);
 
-        for(int i = 1; i < list.size(); i++) {
-            String[] sItem = list.get(i);
-            ListGridRecord r = new ListGridRecord();
-            for(int j = 0; j < sItem.length; j++) {
+        for (int i = 1; i < list.size(); i++) { // index bei 1, da erster Eintrag Header ist
+
+            final String[] sItem = list.get(i);
+            final Record r = new Record();
+            for (int j = 0; j < sItem.length; j++) {
                 // See above, display 'as is' from server, but keep value
                 // in machine-usable way (float), to allow numeric sorting.
                 r.setAttribute(displayField[j], sItem[j]);
+                // r.setAttribute(String.valueOf(j), sItem[j]);
                 if (fields[j].getType() == ListGridFieldType.TEXT) {
                     r.setAttribute(String.valueOf(j), sItem[j]);
-                }
-                else {
+                } else {
                     try {
-                        r.setAttribute(String.valueOf(j), nf.parse(sItem[j]));
+                        final Float valueFloatSortable = (float) nf.parse(sItem[j]);
+                        r.setAttribute(String.valueOf(j), valueFloatSortable);
                     }
-                    catch (NumberFormatException nfe) {
+                    catch (final NumberFormatException nfe) {
                         r.setAttribute(String.valueOf(j), sItem[j]);
                     }
                 }
+
             }
-            dataTable.addData(r);
+
+            dataTableTab.addData(r);
         }
     }
+
+    private Map<String, List<String[]>> getTabData(final List<String[]> raw) {
+        // Condition: tableTitle must be first
+        final Map<String, List<String[]>> tabs = new TreeMap<String, List<String[]>>(); // auto-sort
+
+        if (raw.get(0)[0].startsWith(this.MESSAGES.export_csv_title())) {
+            // Bedingung für Tabs
+            int lastIndex = 0;
+            String lastTableTitle = "";
+
+            for (int i = 0; i < raw.size(); i++) {
+
+                final String[] row = raw.get(i);
+                if (row[0].startsWith(this.MESSAGES.export_csv_title())) {
+
+                    if (i > 0) {
+                        tabs.put(makeKeyTitle(lastTableTitle, tabs.size()), raw.subList((lastIndex + 1), (i))); // toIndex exclusive (without
+                                                                                                                // tabTitle-Line of the next tab, which is
+                                                                                                                // stored in the current row (raw.get(i));
+                                                                                                                // fromIndex
+                                                                                                                // inclusive ->
+                                                                                                                // without tabTitle from the past tab ->
+                                                                                                                // lastindex+1
+                    }
+                    lastTableTitle = row[0].replace(this.MESSAGES.export_csv_title(), "");
+                    lastIndex = i;
+                }
+
+                if (i == (raw.size() - 1)) {
+                    tabs.put(makeKeyTitle(lastTableTitle, tabs.size()), raw.subList((lastIndex + 1), i + 1));
+                    // last result-tab:
+                    // toIndex exclusive -> last i + 1
+                    // fromIndex inclusive: lastInde +1 -> no title-line included
+                }
+
+            }
+        } else {
+            // plainOld Table, no TABS
+            tabs.put("", raw);
+        }
+
+        return tabs;
+    }
+
+    private String makeKeyTitle(final String title, final int index) {
+        return new StringBuilder().append("(").append((index + 1)).append(") ").append(title).toString();
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,6 +8,8 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.ui.AbstractSingleItemPanel.Type;
 import org.dive4elements.river.client.client.ui.fixation.FixEventSelect;
 import org.dive4elements.river.client.client.ui.fixation.FixFunctionSelect;
 import org.dive4elements.river.client.client.ui.fixation.FixGaugeSelectPanel;
@@ -22,9 +24,21 @@
 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.CollisionLoadEpochPanel;
+import org.dive4elements.river.client.client.ui.sinfo.CollisionLoadYearPanel;
+import org.dive4elements.river.client.client.ui.sinfo.FlowDepthMinMaxTwinPanel;
+import org.dive4elements.river.client.client.ui.sinfo.FlowDepthTwinPanel;
 import org.dive4elements.river.client.client.ui.sq.SQPeriodPanel;
+import org.dive4elements.river.client.client.ui.uinfo.LoadSedimentHeightPanel;
+import org.dive4elements.river.client.client.ui.uinfo.LoadSingleYearPanel;
+import org.dive4elements.river.client.client.ui.uinfo.LoadSingleYearPseudoEpochPanel;
+import org.dive4elements.river.client.client.ui.uinfo.SupraRegionalTablePanel;
+import org.dive4elements.river.client.client.ui.uinfo.VegetationzonesTableEditPanel;
+import org.dive4elements.river.client.client.ui.uinfo.VegetationzonesTablePanel;
 import org.dive4elements.river.client.shared.model.User;
 
+import com.google.gwt.core.client.GWT;
+
 /**
  * Depending on the provider the state declared, return a UIProvider.
  *
@@ -32,173 +46,164 @@
  * artifacts state.
  */
 public class UIProviderFactory {
+    private static FLYSConstants MSG;
 
     private UIProviderFactory() {
     }
 
-    /** @param uiProvider uiprovider demanded for by state. */
-    public static UIProvider getProvider(String uiProvider, User user) {
+    /**
+     * @param uiProvider
+     *            uiprovider demanded for by state.
+     */
+    public static UIProvider getProvider(final String uiProvider, final User user) {
         if (uiProvider == null || uiProvider.equals("")) {
             return new SelectProvider();
-        }
-        else if (uiProvider.equals("select_with_map")) {
+        } else if (uiProvider.equals("select_with_map")) {
             return new MapSelection();
-        }
-        else if (uiProvider.equals("location_distance_panel")) {
+        } else if (uiProvider.equals("location_distance_panel")) {
             return new LocationDistancePanel();
-        }
-        else if (uiProvider.equals("location_panel")) {
+        } else if (uiProvider.equals("location_panel")) {
             return new SingleLocationPanel();
-        }
-        else if (uiProvider.equals("multi_location_panel")) {
+        } else if (uiProvider.equals("multi_location_panel")) {
             return new MultipleLocationPanel();
-        }
-        else if (uiProvider.equals("distance_panel")) {
+        } else if (uiProvider.equals("distance_panel")) {
             return new DistancePanel();
-        }
-        else if (uiProvider.equals("distance_only_panel")) {
+        } else if (uiProvider.equals("distance_only_panel")) {
             return new DistanceOnlyPanel();
-        }
-        else if (uiProvider.equals("waterlevel_ground_panel")) {
+        } else if (uiProvider.equals("distance_only_part_panel")) {
+            return new DistanceOnlyPartPanel();
+        } else if (uiProvider.equals("distance_only_part_historical_panel")) {
+            return new DistanceOnlyPartHistoricalPanel();
+        } else if (uiProvider.equals("waterlevel_ground_panel")) {
             return new WaterlevelGroundPanel();
-        }
-        else if (uiProvider.equals("wq_panel")) {
+        } else if (uiProvider.equals("wq_panel")) {
             return new WQInputPanel();
-        }
-        else if (uiProvider.equals("wq_panel_adapted")) {
+        } else if (uiProvider.equals("wq_panel_adapted")) {
             return new WQAdaptedInputPanel();
-        }
-        else if (uiProvider.equals("wq_panel_adapted_fixing")) {
+        } else if (uiProvider.equals("wq_panel_adapted_fixing")) {
             return new WQAdaptedFixingInputPanel();
-        }
-        else if (uiProvider.equals("q_segmented_panel")) {
+        } else if (uiProvider.equals("q_segmented_panel")) {
             return new QSegmentedInputPanel();
-        }
-        else if (uiProvider.equals("river_panel")) {
+        } else if (uiProvider.equals("river_panel")) {
             return new LinkSelection();
-        }
-        else if (uiProvider.equals("continue")) {
+        } else if (uiProvider.equals("continue")) {
             return new ContinuePanel();
-        }
-        else if (uiProvider.equals("wsp_datacage_panel")) {
+        } else if (uiProvider.equals("uinfo.vegetationzones.table.edit")) {
+            return new VegetationzonesTableEditPanel();
+        } else if (uiProvider.equals("uinfo.vegetationzones.table")) {
+            return new VegetationzonesTablePanel();
+        } else if (uiProvider.equals("wsp_datacage_panel")) {
             return new WspDatacagePanel(user);
-        }
-        else if (uiProvider.equals("dgm_datacage_panel")) {
+        } 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("auto_integer")) {
+        } else if (uiProvider.equals("waterlevel_twin_panel")) {
+            return new WaterlevelTwinPanel(user);
+        } else if (uiProvider.equals("auto_integer")) {
             return new AutoIntegerPanel();
-        }
-        else if (uiProvider.equals("boolean_panel")) {
+        } else if (uiProvider.equals("boolean_panel")) {
             return new BooleanPanel();
-        }
-        else if (uiProvider.equals("noinput")) {
+        } else if (uiProvider.equals("noinput")) {
             return new NoInputPanel();
-        }
-        else if (uiProvider.equals("map_digitize")) {
+        } else if (uiProvider.equals("map_digitize")) {
             return new DigitizePanel();
-        }
-        else if (uiProvider.equals("timerange")) {
+        } else if (uiProvider.equals("timerange")) {
             return new IntegerRangePanel();
-        }
-        else if (uiProvider.equals("wq_simple_array")) {
+        } else if (uiProvider.equals("wq_simple_array")) {
             return new WQSimpleArrayPanel();
-        }
-        else if (uiProvider.equals("gaugetimerange")) {
+        } else if (uiProvider.equals("gaugetimerange")) {
             return new GaugeTimeRangePanel();
-        }
-        else if (uiProvider.equals("fix.location_panel")) {
+        } else if (uiProvider.equals("fix.location_panel")) {
             return new FixLocationPanel();
-        }
-        else if (uiProvider.equals("fix.period_panel")) {
+        } else if (uiProvider.equals("fix.period_panel")) {
             return new FixPeriodPanel();
-        }
-        else if (uiProvider.equals("fix.period_ref_panel")) {
+        } else if (uiProvider.equals("fix.period_ref_panel")) {
             return new FixPeriodPanel("ref_start", "ref_end");
+        } else if (uiProvider.equals("fix.period_ana_panel")) {
+            return new FixMultiPeriodPanel();
+        } else if (uiProvider.equals("fix.qselect_panel")) {
+            return new FixQSelectPanel();
+        } else if (uiProvider.equals("fix.gaugeselect_panel")) {
+            return new FixGaugeSelectPanel();
+        } else if (uiProvider.equals("fix.event_panel")) {
+            return new FixEventSelect();
+        } else if (uiProvider.equals("fix.preprocessing_panel")) {
+            return new BooleanPanel();
+        } else if (uiProvider.equals("fix.functionselect")) {
+            return new FixFunctionSelect();
+        } else if (uiProvider.equals("period_select")) {
+            return new PeriodPanel();
+        } else if (uiProvider.equals("periods_select")) {
+            return new MultiPeriodPanel();
+        } else if (uiProvider.equals("sq.period.select")) {
+            return new SQPeriodPanel();
+        } else if (uiProvider.equals("outliers_input")) {
+            return new DoubleInputPanel();
+        } else if (uiProvider.equals("percent_input")) {
+            return new DoubleInputPanel("percent");
+        } else if (uiProvider.equals("parameter-matrix")) {
+            return new ParameterMatrixPanel();
+        } else if (uiProvider.equals("minfo.bed.year_epoch")) {// legacy
+            return new RadioPanel();
+        } else if (uiProvider.equals("radio_panel")) {
+            return new RadioPanel();
+        } else if (uiProvider.equals("bedquality_periods_select")) {
+            return new BedMultiPeriodPanel();
+        } else if (uiProvider.equals("bedheights_twin_panel")) {
+            return new BedHeightsDatacagePanel(user);
+        } else if (uiProvider.equals("minfo.bed.char_diameter")) {
+            return new CheckboxPanel();
+        } else if (uiProvider.equals("minfo.sedimentload_unit_select")) {
+            return new RadioPanel();
+        } else if (uiProvider.equals("static_data")) {
+            return new StaticDataPanel();
+        } else if (uiProvider.equals("minfo.sedimentload_distance_select")) {
+            return new SedLoadDistancePanel();
+        } else if (uiProvider.equals("minfo.sedimentload_year_select")) {
+            return new SedLoadPeriodPanel();
+        } else if (uiProvider.equals("minfo.sedimentload_epoch_select")) {
+            return new SedLoadEpochPanel();
+        } else if (uiProvider.equals("sinfo.collision.load_year_select")) {
+            return new CollisionLoadYearPanel();
+        } else if (uiProvider.equals("sinfo.collision.load_epoch_select")) {
+            return new CollisionLoadEpochPanel();
+        } else if (uiProvider.equals("common.state.load_single_year_select")) {
+            return new LoadSingleYearPanel();
+        } else if (uiProvider.equals("common.state.load_single_year_select.show_hint")) {
+            return new LoadSingleYearPanel(true);
+        } else if (uiProvider.equals("uinfo.salix.load_single_year_pseudo_epoch_select")) {
+            return new LoadSingleYearPseudoEpochPanel();
+        } else if (uiProvider.equals("minfo.sedimentload_sqti_select")) {
+            return new SedLoadSQTiPanel();
+        } else if (uiProvider.equals("uinfo.sedimentheight_select")) {
+            return new LoadSedimentHeightPanel(Type.single);
+        } else if (uiProvider.equals("uinfo.sedimentheight_select.limit5")) {
+            return new LoadSedimentHeightPanel(Type.limit5);
+        } else if (uiProvider.equals("hws_datacage_panel")) {
+            return new HWSDatacagePanel(user);
+        } else if (uiProvider.equals("user_rgd_panel")) {
+            return new UserRGDProvider();
+        } else if (uiProvider.equals("static_sqrelation")) {
+            return new StaticDataPanel();
+        } else if (uiProvider.equals("uinfo.salix.supraregional.table")) {
+            return new SupraRegionalTablePanel();
         }
-        else if (uiProvider.equals("fix.period_ana_panel")) {
-            return new FixMultiPeriodPanel();
-        }
-        else if (uiProvider.equals("fix.qselect_panel")) {
-            return new FixQSelectPanel();
-        }
-        else if (uiProvider.equals("fix.gaugeselect_panel")) {
-            return new FixGaugeSelectPanel();
-        }
-        else if (uiProvider.equals("fix.event_panel")) {
-            return new FixEventSelect();
-        }
-        else if (uiProvider.equals("fix.preprocessing_panel")) {
-            return new BooleanPanel();
-        }
-        else if (uiProvider.equals("fix.functionselect")) {
-            return new FixFunctionSelect();
-        }
-        else if (uiProvider.equals("period_select")) {
-            return new PeriodPanel();
-        }
-        else if (uiProvider.equals("periods_select")) {
-            return new MultiPeriodPanel();
-        }
-        else if (uiProvider.equals("sq.period.select")) {
-            return new SQPeriodPanel();
-        }
-        else if (uiProvider.equals("outliers_input")) {
-            return new DoubleInputPanel();
-        }
-        else if (uiProvider.equals("percent_input")) {
-            return new DoubleInputPanel("percent");
-        }
-        else if (uiProvider.equals("parameter-matrix")) {
-            return new ParameterMatrixPanel();
-        }
-        else if (uiProvider.equals("minfo.bed.year_epoch")) {
-            return new RadioPanel();
+
+        if ("sinfo_flowdepth_twin_panel".equals(uiProvider))
+            return new FlowDepthTwinPanel(user, 1, getMSG().sinfo_flow_depth_development_twin_panel_max_count_msg());
+
+        if ("sinfo_flowdepthminmax_twin_panel".equals(uiProvider))
+            return new FlowDepthMinMaxTwinPanel(user);
+
+        // GWT.log("Picked default provider.");
+        return new SelectProvider();
+    }
+
+    private static FLYSConstants getMSG() {
+        if (MSG == null) {
+            MSG = GWT.create(FLYSConstants.class);
         }
-        else if (uiProvider.equals("bedquality_periods_select")) {
-            return new BedMultiPeriodPanel();
-        }
-        else if (uiProvider.equals("bedheights_twin_panel")) {
-            return new BedHeightsDatacagePanel(user);
-        }
-        else if (uiProvider.equals("minfo.bed.char_diameter")) {
-            return new CheckboxPanel();
-        }
-        else if (uiProvider.equals("minfo.sedimentload_unit_select")) {
-            return new RadioPanel();
-        }
-        else if (uiProvider.equals("static_data")) {
-            return new StaticDataPanel();
-        }
-        else if (uiProvider.equals("minfo.sedimentload_distance_select")) {
-            return new SedLoadDistancePanel();
-        }
-        else if (uiProvider.equals("minfo.sedimentload_year_select")) {
-            return new SedLoadPeriodPanel();
-        }
-        else if (uiProvider.equals("minfo.sedimentload_epoch_select")) {
-            return new SedLoadEpochPanel();
-        }
-        else if (uiProvider.equals("minfo.sedimentload_sqti_select")) {
-            return new SedLoadSQTiPanel();
-        }
-        else if (uiProvider.equals("hws_datacage_panel")) {
-            return new HWSDatacagePanel(user);
-        }
-        else if (uiProvider.equals("user_rgd_panel")) {
-            return new UserRGDProvider();
-        }
-        else if (uiProvider.equals("static_sqrelation")) {
-            return new StaticDataPanel();
-        }
-        else {
-            //GWT.log("Picked default provider.");
-            return new SelectProvider();
-        }
+        return MSG;
     }
+
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
-
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WaterlevelGroundPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WaterlevelGroundPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,6 +8,10 @@
 
 package org.dive4elements.river.client.client.ui;
 
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.widgets.Label;
 import com.smartgwt.client.widgets.form.validator.FloatRangeValidator;
 
 public class WaterlevelGroundPanel extends DistancePanel {
@@ -16,118 +20,108 @@
 
     public static final String FIELD_LOWER = "diff_from";
     public static final String FIELD_UPPER = "diff_to";
-    public static final String FIELD_STEP  = "diff_diff";
-
+    public static final String FIELD_STEP = "diff_diff";
 
     public WaterlevelGroundPanel() {
         super("left");
 
-        FloatRangeValidator frv = new FloatRangeValidator();
+        final FloatRangeValidator frv = new FloatRangeValidator();
         frv.setMin(0f);
         frv.setMax(Float.MAX_VALUE);
         frv.setValidateOnChange(true);
-        distancePanel.getToItem().setValidators(frv);
+        this.distancePanel.getToItem().setValidators(frv);
     }
 
-
     @Override
     protected String getLowerField() {
         return FIELD_LOWER;
     }
 
-
     @Override
     protected String getUpperField() {
         return FIELD_UPPER;
     }
 
-
     @Override
     protected String getStepField() {
         return FIELD_STEP;
     }
 
-
     @Override
-    protected String getLabel() {
-        return MSG.waterlevel_ground_state();
+    protected Label getLabel(final DataList data) {
+        final Data item = data.get(0);
+        return new Label(item.getDescription());//
+
+        // item.getDescription()); // holt das Label vom Server (funktoniert schon sehr oft so!)
     }
 
+    // @Override
+    // protected String getLabel() {
+    // return MSG.waterlevel_ground_state();
+    // }
 
     @Override
     protected String labelFrom() {
         return getLabelFrom() + " [" + getUnitFrom() + "]";
     }
 
-
     @Override
     protected String getLabelFrom() {
-        return MSG.wgLabelFrom();
+        return this.MSG.wgLabelFrom();
     }
 
-
     @Override
     protected String getUnitFrom() {
-        return MSG.wgUnitFrom();
+        return this.MSG.wgUnitFrom();
     }
 
-
     @Override
     protected String labelTo() {
         return getLabelTo() + " [" + getUnitTo() + "]";
     }
 
-
     @Override
     protected String getLabelTo() {
-        return MSG.wgLabelTo();
+        return this.MSG.wgLabelTo();
     }
 
-
     @Override
     protected String getUnitTo() {
-        return MSG.wgUnitTo();
+        return this.MSG.wgUnitTo();
     }
 
-
     @Override
     protected String labelStep() {
         return getLabelStep() + " [" + getUnitStep() + "]";
     }
 
-
     @Override
     protected String getLabelStep() {
-        return MSG.wgLabelStep();
+        return this.MSG.wgLabelStep();
     }
 
-
     @Override
     protected String getUnitStep() {
-        return MSG.wgUnitStep();
+        return this.MSG.wgUnitStep();
     }
 
-
     @Override
     protected double getDefaultFrom() {
         return 0;
     }
 
-
     @Override
     protected double getDefaultTo() {
         return 2;
     }
 
-
     @Override
     protected double getDefaultStep() {
         return 0.5;
     }
 
-
     @Override
-    protected void initHelperPanel() {
+    protected void initHelperPanel(final DataList data) {
         // We don't need a helper panel here. But we have to override this
         // method to avoid the table creation in the parent class.
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WaterlevelRecommendationInfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,80 @@
+/** 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;
+
+import org.dive4elements.river.client.client.ui.DatacageTwinPanel.IDatacageTwinPanelInfo;
+import org.dive4elements.river.client.shared.model.Recommendation;
+
+import com.google.gwt.core.client.GWT;
+
+/**
+ * Factored out code from the old WaterlevelTwinPanel; contains some evil hacks about the involved artifact factories. See original comments below...
+ *
+ * @author Gernot Belger
+ */
+public final class WaterlevelRecommendationInfo implements IDatacageTwinPanelInfo {
+
+    private final String outs;
+
+    /**
+     * @param tweakFactory See evil hack below
+     */
+    public WaterlevelRecommendationInfo(final String outs) {
+        this.outs = outs;
+    }
+
+    @Override
+    public String getFactory(final String originalFactory) {
+        // FIXME: why are the factory here and the one used in createDataString different?
+        // Probably also because of the 'throw all this code away comment'
+        return "waterlevel";
+    }
+
+    @Override
+    public String getDataStringFactory(final Recommendation recommendation) {
+        return "staticwkms";
+    }
+
+    @Override
+    public void adjustRecommendation(final Recommendation recommendation) {
+
+        // XXX: THIS IS AN EVIL HACK TO MAKE W-DIFFERENCES WORK AGAIN!
+        // TODO: Throw all this code away and do it with server side recommendations!
+        recommendation.setTargetOut("w_differences");
+
+        if (recommendation.getIDs() != null) {
+            GWT.log("Setting staticwkms factory for rec with ID "
+                    + recommendation.getIDs());
+            recommendation.setFactory("staticwkms");
+        }
+        /*
+        // So far, we do not need to rewrite the factory anymore,
+        // except for staticwkms; probably other cases will pop up later.
+        else if (recommendation.getFactory().equals("winfo")) {
+            GWT.log("Setting waterlevel factory for a winfo rec.");
+            recommendation.setFactory("waterlevel");
+        }
+         */
+        else {
+            GWT.log("Leave rec. id " + recommendation.getIDs() + ", factory "
+                    + recommendation.getFactory() + " untouched.");
+        }
+    }
+
+    @Override
+    public String getOuts() {
+        return this.outs;
+    }
+
+    @Override
+    public String getColumnLabel() {
+        return null;
+    }
+}
\ 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/WaterlevelTwinPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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.client.client.ui;
+
+import org.dive4elements.river.client.shared.model.User;
+
+/**
+ * A DatacageTwinPanel implementation for W-INFO Differences: choose two waterlevels
+ *
+ * @author Gernot Belger
+ */
+public class WaterlevelTwinPanel extends DatacageTwinPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public WaterlevelTwinPanel(final User user) {
+        super(user, new WaterlevelTwinPanelValidator(), DatacagePairWidget.NIL_CONTROLER, new WaterlevelRecommendationInfo("winfo_diff_twin_panel"),
+                new WaterlevelRecommendationInfo("winfo_diff_twin_panel"), 9999, "");
+    }
+}
\ 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/WaterlevelTwinPanelValidator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,48 @@
+/** 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;
+
+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
+ */
+public final class WaterlevelTwinPanelValidator 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.error_no_waterlevel_pair_selected());
+        }
+        // Check whether minuend and subtrahend are equal.
+        for (ListGridRecord record: differencesList.getRecords()) {
+            RecommendationPairRecord r = (RecommendationPairRecord) record;
+            if (r.getFirst().equals(r.getSecond())) {
+            	// FIXME: this is still waterlevel specific!
+            	// TODO: delegate validation to specific implementations
+                errors.add(msgProvider.error_same_waterlevels_in_pair());
+            }
+        }
+
+        return errors;
+	}
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WspDatacagePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WspDatacagePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,15 +8,12 @@
 
 package org.dive4elements.river.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.events.ClickEvent;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYS;
-import org.dive4elements.river.client.client.FLYSConstants;
 import org.dive4elements.river.client.client.event.StepForwardEvent;
 import org.dive4elements.river.client.client.services.LoadArtifactService;
 import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
@@ -32,67 +29,40 @@
 import org.dive4elements.river.client.shared.model.ToLoad;
 import org.dive4elements.river.client.shared.model.User;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.events.ClickEvent;
 
 public class WspDatacagePanel extends DatacagePanel {
 
     private static final long serialVersionUID = 2494432743877141135L;
 
-    public static final String WATERLEVEL_OUTS = "waterlevels_panel";
-
-    public static final FLYSConstants MSG = GWT.create(FLYSConstants.class);
-
-
-    protected LoadArtifactServiceAsync loadService =
-        GWT.create(LoadArtifactService.class);
-
-    protected Recommendation recommendation;
-    protected Artifact       artifact;
-
-
-    public WspDatacagePanel() {
-        super();
-    }
-
+    private static final String WATERLEVEL_OUTS = "waterlevels_panel";
 
-    public WspDatacagePanel(User user) {
-        super(user);
-    }
-
+    private final LoadArtifactServiceAsync loadService = GWT.create(LoadArtifactService.class);
 
-    @Override
-    public String getOuts() {
-        return WATERLEVEL_OUTS;
+    public WspDatacagePanel(final User user) {
+        super(user, WATERLEVEL_OUTS, null, false);
     }
 
-
-    @Override
-    protected void createWidget() {
-        super.createWidget();
-        widget.setIsMutliSelectable(false);
-    }
-
-
     /**
      * We need to override this method (defined in AbstractUIProvider) because
      * we have to create a new Artifact specified by the Datacage selection via
      * Async request.
      *
-     * @param e The ClickEvent.
+     * @param e
+     *            The ClickEvent.
      */
     @Override
-    public void onClick(ClickEvent e) {
-        List<String> errors = validate();
+    public void onClick(final ClickEvent e) {
+        final List<String> errors = validate();
         if (errors == null || errors.isEmpty()) {
             // 1) Fetch selected recommendation.
-            Config config           = Config.getInstance();
-            final  String locale    = config.getLocale();
-            final  Collection c     = this.collection;
-            final  Recommendation r = getSelectedRecommendation();
-
+            final Config config = Config.getInstance();
+            final String locale = config.getLocale();
+            final Collection c = this.collection;
+            final Recommendation r = getSelectedRecommendation();
 
             if (r == null) {
                 SC.warn(MSG.warning_no_wsp_selected());
@@ -101,38 +71,31 @@
 
             // TODO: This could eventually be handled server-side.
             // 2) Create, load Artifact and fire event.
-            loadService.load(
-                c, r, r.getFactory(), locale,
-                new AsyncCallback<Artifact>() {
-                    @Override
-                    public void onFailure(Throwable caught) {
-                        GWT.log("WspDatacagePanel", caught);
-                        SC.warn(FLYS.getExceptionString(MSG, caught));
-                    }
+            this.loadService.load(c, r, r.getFactory(), locale, new AsyncCallback<Artifact>() {
+                @Override
+                public void onFailure(final Throwable caught) {
+                    GWT.log("WspDatacagePanel", caught);
+                    SC.warn(FLYS.getExceptionString(MSG, caught));
+                }
 
-                    @Override
-                    public void onSuccess(Artifact newArtifact) {
-                        GWT.log("Created new artifact.");
-                        fireStepForwardEvent(new StepForwardEvent(
-                            getData(r, newArtifact)));
-                    }
+                @Override
+                public void onSuccess(final Artifact newArtifact) {
+                    GWT.log("Created new artifact.");
+                    fireStepForwardEvent(new StepForwardEvent(getData(r, newArtifact)));
                 }
-            );
-        }
-        else {
+            });
+        } else {
             showErrors(errors);
         }
     }
 
-
     protected Recommendation getSelectedRecommendation() {
-        ToLoad toLoad = widget.getSelection();
-        List<Recommendation> recoms = toLoad.toRecommendations();
+        final ToLoad toLoad = getSelection();
+        final List<Recommendation> recoms = toLoad.toRecommendations();
 
         return recoms.size() > 0 ? recoms.get(0) : null;
     }
 
-
     /**
      * Nothing is done in this method. It returns null, because we serve the
      * Data another way!
@@ -145,35 +108,32 @@
         return null;
     }
 
-
     /** Returns a Data Array with one default item. */
-    protected Data[] getData(Recommendation r, Artifact newArtifact) {
-        String uuid = newArtifact.getUuid();
+    protected final Data[] getData(final Recommendation r, final Artifact newArtifact) {
+        final String uuid = newArtifact.getUuid();
         r.setMasterArtifact(uuid);
 
-        String value = createDataString(uuid, r);
+        final String value = createDataString(uuid, r);
 
-        DataItem item = new DefaultDataItem(dataName, dataName, value);
-        return new Data[] { new DefaultData(
-            dataName, null, null, new DataItem[] { item }) };
+        final String dataName = getMyDataName();
+
+        final DataItem item = new DefaultDataItem(dataName, dataName, value);
+        return new Data[] { new DefaultData(dataName, null, null, new DataItem[] { item }) };
     }
 
-
-    protected String createDataString(
-        String artifact,
-        Recommendation recommendation
-    ) {
-        Facet f = null;
+    private String createDataString(final String artifactId, final Recommendation recommendation) {
 
         // The filter will only be available or previous calculation artifacts.
-        Filter filter = recommendation.getFilter();
+        final Filter filter = recommendation.getFilter();
 
         if (filter != null) {
-            Map<String, List<Facet>>               outs = filter.getOuts();
-            Set<Map.Entry<String, List<Facet>>> entries = outs.entrySet();
+            Facet f = null;
 
-            for (Map.Entry<String, List<Facet>> entry: entries) {
-                List<Facet> fs = entry.getValue();
+            final Map<String, List<Facet>> outs = filter.getOuts();
+            final Set<Map.Entry<String, List<Facet>>> entries = outs.entrySet();
+
+            for (final Map.Entry<String, List<Facet>> entry : entries) {
+                final List<Facet> fs = entry.getValue();
 
                 f = fs.get(0);
                 if (f != null) {
@@ -181,13 +141,9 @@
                 }
             }
 
-            return "[" + artifact + ";" + f.getName() + ";"
-                + f.getIndex() + "]";
+            return "[" + artifactId + ";" + f.getName() + ";" + f.getIndex() + "]";
         }
-        else {
-            return "[" + artifact + ";"
-                + recommendation.getFactory() + ";" + 0 + "]";
-        }
+
+        return "[" + artifactId + ";" + recommendation.getFactory() + ";" + 0 + "]";
     }
-}
-// 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/ui/chart/ManualPointsEditor.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ManualPointsEditor.java	Fri Jul 13 11:56:22 2018 +0200
@@ -200,6 +200,9 @@
                         (StringProperty)pg.getPropertyByName("label");
                     xAxis = name.getValue();
                 }
+                // FIXME: this always selects the first axis not named 'X' regardless of on what axis the manual points sit.
+                // Actually we do not have the information about the manual points axis
+                // One solution might be to add that axis as extra info into the chart settings: but would be a very special case
                 else if (yAxis.equals("Y")) {
                     StringProperty name =
                         (StringProperty)pg.getPropertyByName("label");
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,203 +8,183 @@
 
 package org.dive4elements.river.client.client.ui.chart;
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.Map;
-import java.util.HashMap;
+
+import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.shared.model.AbstractFixBunduArtifact;
+import org.dive4elements.river.client.shared.model.Artifact;
+import org.dive4elements.river.client.shared.model.Collection;
+import org.dive4elements.river.client.shared.model.FixFilter;
+import org.dive4elements.river.client.shared.model.OutputMode;
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.i18n.client.NumberFormat;
-
 import com.smartgwt.client.types.Alignment;
-
 import com.smartgwt.client.widgets.Button;
 import com.smartgwt.client.widgets.Canvas;
-
 import com.smartgwt.client.widgets.events.ClickEvent;
 import com.smartgwt.client.widgets.events.ClickHandler;
-
 import com.smartgwt.client.widgets.form.DynamicForm;
-
 import com.smartgwt.client.widgets.form.fields.TextItem;
-
 import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
 import com.smartgwt.client.widgets.form.fields.events.KeyPressHandler;
-
 import com.smartgwt.client.widgets.layout.HLayout;
 import com.smartgwt.client.widgets.layout.VLayout;
-
 import com.smartgwt.client.widgets.tab.events.TabSelectedEvent;
 import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
 
-import org.dive4elements.river.client.client.Config;
-
-import org.dive4elements.river.client.client.ui.CollectionView;
-
-import org.dive4elements.river.client.shared.model.Artifact;
-import org.dive4elements.river.client.shared.model.Collection;
-import org.dive4elements.river.client.shared.model.FixAnalysisArtifact;
-import org.dive4elements.river.client.shared.model.FixFilter;
-import org.dive4elements.river.client.shared.model.OutputMode;
-
-import java.util.Date;
-
-
 /**
  * Tab representing and showing one Chart-output with a "navi" thing.
  *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class NaviChartOutputTab
-extends      ChartOutputTab
-implements   TabSelectedHandler
-{
+public class NaviChartOutputTab extends ChartOutputTab implements TabSelectedHandler {
     protected TextItem currentkm;
 
-    public NaviChartOutputTab(
-        String         title,
-        Collection     collection,
-        OutputMode     mode,
-        CollectionView collectionView
-    ){
+    public NaviChartOutputTab(final String title, final Collection collection, final OutputMode mode, final CollectionView collectionView) {
         super(title, collection, mode, collectionView);
-        right.removeChild(chart);
-        right.addChild(createNaviChart());
+        this.right.removeChild(this.chart);
+        this.right.addChild(createNaviChart());
         collectionView.registerTabHandler(this);
     }
 
-
     protected Canvas createNaviChart() {
-        final Artifact art = collectionView.getArtifact();
-        VLayout root = new VLayout();
+        final Artifact art = this.collectionView.getArtifact();
+        final VLayout root = new VLayout();
         root.setWidth100();
         root.setHeight100();
 
-        HLayout layout = new HLayout();
+        final HLayout layout = new HLayout();
         layout.setAlign(Alignment.CENTER);
 
-        DynamicForm form = new DynamicForm();
-        Button lower = new Button("<<");
+        final DynamicForm form = new DynamicForm();
+        final Button lower = new Button("<<");
         lower.setWidth(30);
-        Button upper = new Button(">>");
+        final Button upper = new Button(">>");
         upper.setWidth(30);
-        currentkm = new TextItem();
-        currentkm.setWidth(60);
-        currentkm.setShowTitle(false);
+        this.currentkm = new TextItem();
+        this.currentkm.setWidth(60);
+        this.currentkm.setShowTitle(false);
 
-        form.setFields(currentkm);
+        form.setFields(this.currentkm);
         form.setWidth(60);
 
         double fromKm;
         double toKm;
 
-        if (art instanceof FixAnalysisArtifact) {
-            FixAnalysisArtifact fix = (FixAnalysisArtifact) art;
-            FixFilter fixFilter = fix.getFilter();
-            String s = fix.getArtifactDescription().getDataValueAsString(
-                "ld_step");
+        if (art instanceof AbstractFixBunduArtifact) {
+            final AbstractFixBunduArtifact fix = (AbstractFixBunduArtifact) art;
+            final FixFilter fixFilter = fix.getFilter();
+            final String s = fix.getArtifactDescription().getDataValueAsString("ld_step");
             try {
-                double ds = Double.parseDouble(s);
-                collectionView.setSteps(ds);
-            }
-            catch(NumberFormatException nfe) {
-                collectionView.setSteps(100d);
+                final double ds = Double.parseDouble(s);
+                this.collectionView.setSteps(ds);
             }
-            fromKm = fixFilter.getFromKm();
-            toKm   = fixFilter.getToKm();
-        }
-        else {
+            catch (final NumberFormatException nfe) {
+                this.collectionView.setSteps(100d);
+            }
+            fromKm = fixFilter.getLowerKm();
+            toKm = fixFilter.getUpperKm();
+        } else {
             // Probably WINFOArtifact kind of artifact.
-            String ld_step =
-                    art.getArtifactDescription().getDataValueAsString(
-                        "ld_step");
+            final String ld_step = art.getArtifactDescription().getDataValueAsString("ld_step");
             try {
-                collectionView.setSteps(Double.valueOf(ld_step));
+                this.collectionView.setSteps(Double.valueOf(ld_step));
             }
-            catch (Exception e) {
+            catch (final Exception e) {
                 GWT.log("No ld_steps data or not parsable.");
                 return root;
             }
 
-            double[] kmRange = art.getArtifactDescription().getKMRange();
+            final double[] kmRange = art.getArtifactDescription().getKMRange();
             if (kmRange == null || kmRange.length == 2) {
                 fromKm = kmRange[0];
-                toKm   = kmRange[1];
-            }
-            else {
+                toKm = kmRange[1];
+            } else {
                 GWT.log("No KM range in description found.");
                 return root;
             }
         }
 
-        collectionView.setMinKm(fromKm);
-        collectionView.setMaxKm(toKm);
+        this.collectionView.setMinKm(fromKm);
+        this.collectionView.setMaxKm(toKm);
 
         final NumberFormat nf = NumberFormat.getDecimalFormat();
 
         // Always jump to the from km when initialized.
         try {
-            double d = Double.valueOf(fromKm);
-            currentkm.setValue(nf.format(d));
-        } catch (NumberFormatException e) {
-            currentkm.setValue(fromKm);
+            final double d = Double.valueOf(fromKm);
+            this.currentkm.setValue(nf.format(d));
         }
-        collectionView.setCurrentKm(fromKm);
+        catch (final NumberFormatException e) {
+            this.currentkm.setValue(fromKm);
+        }
+        this.collectionView.setCurrentKm(fromKm);
 
         lower.addClickHandler(new ClickHandler() {
-            public void onClick(ClickEvent ce) {
-                tbarPanel.deselectControls();
+            @Override
+            public void onClick(final ClickEvent ce) {
+                NaviChartOutputTab.this.tbarPanel.deselectControls();
                 updateChartDown();
                 try {
-                    double d = Double.valueOf(collectionView.getCurrentKm());
-                    currentkm.setValue(nf.format(d));
-                    tbarPanel.onZoom(null);
-                } catch (NumberFormatException e) {
-                    currentkm.setValue(collectionView.getCurrentKm());
+                    final double d = Double.valueOf(NaviChartOutputTab.this.collectionView.getCurrentKm());
+                    NaviChartOutputTab.this.currentkm.setValue(nf.format(d));
+                    NaviChartOutputTab.this.tbarPanel.onZoom(null);
+                }
+                catch (final NumberFormatException e) {
+                    NaviChartOutputTab.this.currentkm.setValue(NaviChartOutputTab.this.collectionView.getCurrentKm());
                 }
             }
         });
 
         upper.addClickHandler(new ClickHandler() {
-            public void onClick(ClickEvent ce) {
-                tbarPanel.deselectControls();
+            @Override
+            public void onClick(final ClickEvent ce) {
+                NaviChartOutputTab.this.tbarPanel.deselectControls();
                 updateChartUp();
                 try {
-                    double d = Double.valueOf(collectionView.getCurrentKm());
-                    currentkm.setValue(nf.format(d));
-                    tbarPanel.onZoom(null);
-                } catch (NumberFormatException e) {
-                    currentkm.setValue(collectionView.getCurrentKm());
+                    final double d = Double.valueOf(NaviChartOutputTab.this.collectionView.getCurrentKm());
+                    NaviChartOutputTab.this.currentkm.setValue(nf.format(d));
+                    NaviChartOutputTab.this.tbarPanel.onZoom(null);
+                }
+                catch (final NumberFormatException e) {
+                    NaviChartOutputTab.this.currentkm.setValue(NaviChartOutputTab.this.collectionView.getCurrentKm());
                 }
             }
         });
 
-        currentkm.addKeyPressHandler(new KeyPressHandler() {
-            public void onKeyPress(KeyPressEvent kpe) {
+        this.currentkm.addKeyPressHandler(new KeyPressHandler() {
+            @Override
+            public void onKeyPress(final KeyPressEvent kpe) {
                 if (!kpe.getKeyName().equals("Enter")) {
                     return;
                 }
-                if(kpe.getItem().getValue() != null) {
-                    tbarPanel.deselectControls();
+                if (kpe.getItem().getValue() != null) {
+                    NaviChartOutputTab.this.tbarPanel.deselectControls();
                     try {
-                        String s = kpe.getItem().getValue().toString();
+                        final String s = kpe.getItem().getValue().toString();
                         double d;
                         try {
                             d = nf.parse(s);
-                            currentkm.setValue(nf.format(d));
-                        } catch (NumberFormatException e) {
+                            NaviChartOutputTab.this.currentkm.setValue(nf.format(d));
+                        }
+                        catch (final NumberFormatException e) {
                             d = -1d;
                         }
-                        if (d <= collectionView.getMaxKm() &&
-                            d >= collectionView.getMinKm()) {
-                            collectionView.setCurrentKm(d);
-                            tbarPanel.updateLinks();
-                            tbarPanel.onZoom(null);
-                            if (right != null) {
+                        if (d <= NaviChartOutputTab.this.collectionView.getMaxKm() && d >= NaviChartOutputTab.this.collectionView.getMinKm()) {
+                            NaviChartOutputTab.this.collectionView.setCurrentKm(d);
+                            NaviChartOutputTab.this.tbarPanel.updateLinks();
+                            NaviChartOutputTab.this.tbarPanel.onZoom(null);
+                            if (NaviChartOutputTab.this.right != null) {
                                 updateChartPanel();
                                 updateChartInfo();
                             }
                         }
                     }
-                    catch(NumberFormatException nfe) {
+                    catch (final NumberFormatException nfe) {
                         // Do nothing.
                     }
                 }
@@ -214,24 +194,23 @@
         layout.addMember(form);
         layout.addMember(upper);
 
-        root.addMember(chart);
+        root.addMember(this.chart);
         root.addMember(layout);
         return root;
     }
 
-
     /**
      * Callback when km-up-button is clicked.
      * Increases collectionViews KM and refreshes view.
      */
     protected void updateChartUp() {
-        double currentKm = collectionView.getCurrentKm();
-        if (currentKm < collectionView.getMaxKm()) {
+        final double currentKm = this.collectionView.getCurrentKm();
+        if (currentKm < this.collectionView.getMaxKm()) {
             // Why this math?
             double newVal = currentKm * 100;
-            newVal += (collectionView.getSteps() / 10);
-            collectionView.setCurrentKm((double)Math.round(newVal) / 100);
-            tbarPanel.updateLinks();
+            newVal += (this.collectionView.getSteps() / 10);
+            this.collectionView.setCurrentKm((double) Math.round(newVal) / 100);
+            this.tbarPanel.updateLinks();
             updateChartPanel();
             updateChartInfo();
         }
@@ -242,53 +221,57 @@
      * Decreases collectionViews KM and refreshes view.
      */
     protected void updateChartDown() {
-        double currentKm = collectionView.getCurrentKm();
-        if (currentKm > collectionView.getMinKm()) {
+        final double currentKm = this.collectionView.getCurrentKm();
+        if (currentKm > this.collectionView.getMinKm()) {
             // Why this math?
             double newVal = currentKm * 100;
-            newVal -= (collectionView.getSteps() / 10);
-            collectionView.setCurrentKm((double)Math.round(newVal) / 100);
-            tbarPanel.updateLinks();
+            newVal -= (this.collectionView.getSteps() / 10);
+            this.collectionView.setCurrentKm((double) Math.round(newVal) / 100);
+            this.tbarPanel.updateLinks();
             updateChartPanel();
             updateChartInfo();
         }
 
     }
 
-   /**
+    /**
      * Returns the existing chart panel.
      *
      * @return the existing chart panel.
      */
     @Override
     public Canvas getChartPanel() {
-        return chart;
+        return this.chart;
     }
 
     /**
      * Builds the URL that points to the chart image.
      *
-     * @param width The width of the requested chart.
-     * @param height The height of the requested chart.
-     * @param xr Optional x range (used for zooming).
-     * @param yr Optional y range (used for zooming).
+     * @param width
+     *            The width of the requested chart.
+     * @param height
+     *            The height of the requested chart.
+     * @param xr
+     *            Optional x range (used for zooming).
+     * @param yr
+     *            Optional y range (used for zooming).
      *
      * @return the URL to the chart image.
      */
     @Override
-    protected String getImgUrl(int width, int height) {
-        Config config = Config.getInstance();
+    protected String getImgUrl(final int width, final int height) {
+        final Config config = Config.getInstance();
 
         String imgUrl = GWT.getModuleBaseURL();
         imgUrl += "chart";
-        imgUrl += "?uuid=" + collection.identifier();
-        imgUrl += "&type=" + mode.getName();
+        imgUrl += "?uuid=" + this.collection.identifier();
+        imgUrl += "&type=" + this.mode.getName();
         imgUrl += "&locale=" + config.getLocale();
         imgUrl += "&timestamp=" + new Date().getTime();
         imgUrl += "&width=" + Integer.toString(width);
         imgUrl += "&height=" + Integer.toString(height - 40);
 
-        Number[] zoom = getZoomValues();
+        final Number[] zoom = getZoomValues();
 
         if (zoom != null) {
             if (zoom[0].intValue() != 0 || zoom[1].intValue() != 1) {
@@ -306,30 +289,27 @@
             }
         }
 
-        if (collectionView.getArtifact() instanceof FixAnalysisArtifact) {
-            if (collectionView.getCurrentKm() == -1) {
-                FixAnalysisArtifact fix =
-                    (FixAnalysisArtifact) collectionView.getArtifact();
-                collectionView.setCurrentKm(fix.getFilter().getFromKm());
+        if (this.collectionView.getArtifact() instanceof AbstractFixBunduArtifact) {
+            if (this.collectionView.getCurrentKm() == -1) {
+                final AbstractFixBunduArtifact fix = (AbstractFixBunduArtifact) this.collectionView.getArtifact();
+                this.collectionView.setCurrentKm(fix.getFilter().getLowerKm());
             }
+        } else if (this.collectionView.getCurrentKm() == -1) {
+            this.collectionView.setCurrentKm(this.collectionView.getArtifact().getArtifactDescription().getKMRange()[0]);
         }
-        else if (collectionView.getCurrentKm() == -1) {
-            collectionView.setCurrentKm(
-                collectionView.getArtifact().getArtifactDescription()
-                .getKMRange()[0]);
-        }
-        if (collectionView.getCurrentKm() != -1) {
-            imgUrl += "&currentKm=" + collectionView.getCurrentKm();
+        if (this.collectionView.getCurrentKm() != -1) {
+            imgUrl += "&currentKm=" + this.collectionView.getCurrentKm();
         }
 
         return imgUrl;
     }
 
-    public void onTabSelected(TabSelectedEvent tse) {
+    @Override
+    public void onTabSelected(final TabSelectedEvent tse) {
         if (this.equals(tse.getTab())) {
             updateChartPanel();
             updateChartInfo();
-            currentkm.setValue(collectionView.getCurrentKm());
+            this.currentkm.setValue(this.collectionView.getCurrentKm());
         }
     }
 
@@ -338,18 +318,20 @@
         Map<String, String> attr = new HashMap<String, String>();
 
         attr = super.getChartAttributes();
-        attr.put("km", String.valueOf(collectionView.getCurrentKm()));
+        attr.put("km", String.valueOf(this.collectionView.getCurrentKm()));
 
         return attr;
     }
 
-    /** In contrast to supers implementation, include the currently selected
-     * km in the url. */
+    /**
+     * In contrast to supers implementation, include the currently selected
+     * km in the url.
+     */
     @Override
-    public String getExportUrl(int width, int height, String format) {
+    public String getExportUrl(final int width, final int height, final String format) {
         String url = super.getExportUrl(width, height, format);
-        if (collectionView.getCurrentKm() != -1) {
-            url += "&currentKm=" + collectionView.getCurrentKm();
+        if (this.collectionView.getCurrentKm() != -1) {
+            url += "&currentKm=" + this.collectionView.getCurrentKm();
         }
         return url;
     }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixLocationPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixLocationPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,45 +8,39 @@
 
 package org.dive4elements.river.client.client.ui.fixation;
 
-import java.util.List;
 import java.util.ArrayList;
-
-import com.google.gwt.core.client.GWT;
-
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Label;
-
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
-
-import com.smartgwt.client.widgets.form.fields.FormItem;
-import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
-import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import java.util.List;
 
 import org.dive4elements.river.client.client.FLYSConstants;
 import org.dive4elements.river.client.client.ui.DoubleRangePanel;
-
 import org.dive4elements.river.client.shared.model.Data;
 import org.dive4elements.river.client.shared.model.DataItem;
 import org.dive4elements.river.client.shared.model.DataList;
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
+
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
 /**
  * This UIProvider creates a panel for location or distance input.
  *
  * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public class FixLocationPanel
-extends      FixationPanel
-implements   BlurHandler
-{
+public class FixLocationPanel extends FixationPanel implements BlurHandler {
     /** The message class that provides i18n strings. */
     protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
 
-    /** The constant name of the input field to enter locations.*/
+    /** The constant name of the input field to enter locations. */
     public static final String FIELD_VALUE_LOCATION = "location";
 
-    /** The constant name of the input field to enter distance.*/
+    /** The constant name of the input field to enter distance. */
     public static final String FIELD_VALUE_DISTANCE = "distance";
 
     DoubleRangePanel inputPanel;
@@ -56,61 +50,54 @@
     double step;
 
     public FixLocationPanel() {
-        htmlOverview = "";
+        this.htmlOverview = "";
     }
 
-    public Canvas createWidget(DataList data) {
+    @Override
+    public Canvas createWidget(final DataList data) {
         instances.put(this.artifact.getUuid(), this);
 
-        VLayout layout = new VLayout();
+        final VLayout layout = new VLayout();
 
-        Canvas title = new Label(MESSAGES.distance());
+        final Canvas title = new Label(this.MESSAGES.distance());
         title.setHeight("25px");
 
-        inputPanel = new DoubleRangePanel(
-                MESSAGES.unitFrom(),
-                MESSAGES.unitTo(),
-                MESSAGES.unitWidth(),
-                0d,
-                0d,
-                0d,
-                240,
-                this);
+        this.inputPanel = new DoubleRangePanel(this.MESSAGES.unitFrom(), this.MESSAGES.unitTo(), this.MESSAGES.unitWidth(), 0d, 0d, 0d, 240, this);
 
         layout.addMember(title);
-        layout.addMember(inputPanel);
+        layout.addMember(this.inputPanel);
         return layout;
     }
 
     @Override
-    public Canvas createOld(DataList dataList) {
-        List<Data> items = dataList.getAll();
+    public Canvas createOld(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
 
-        Data       f      = getData(items, "ld_from");
-        Data       t      = getData(items, "ld_to");
-        Data       s      = getData(items, "ld_step");
-        DataItem[] fItems = f.getItems();
-        DataItem[] tItems = t.getItems();
-        DataItem[] sItems = s.getItems();
+        final Data f = getData(items, "ld_from");
+        final Data t = getData(items, "ld_to");
+        final Data s = getData(items, "ld_step");
+        final DataItem[] fItems = f.getItems();
+        final DataItem[] tItems = t.getItems();
+        final DataItem[] sItems = s.getItems();
 
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         sb.append(fItems[0].getLabel());
-        sb.append(" " + MESSAGES.unitFrom() + " ");
+        sb.append(" " + this.MESSAGES.unitFrom() + " ");
         sb.append(tItems[0].getLabel());
-        sb.append(" " + MESSAGES.unitTo() + " ");
+        sb.append(" " + this.MESSAGES.unitTo() + " ");
         sb.append(sItems[0].getLabel());
-        sb.append(" " + MESSAGES.unitWidth());
+        sb.append(" " + this.MESSAGES.unitWidth());
 
-        Label old = new Label(sb.toString());
+        final Label old = new Label(sb.toString());
         old.setWidth(130);
 
-        HLayout layout = new HLayout();
+        final HLayout layout = new HLayout();
         layout.setWidth("400px");
 
-        Label   label  = new Label(dataList.getLabel());
+        final Label label = new Label(dataList.getLabel());
         label.setWidth("200px");
 
-        Canvas back = getBackButton(dataList.getState());
+        final Canvas back = getBackButton(dataList.getState());
 
         layout.addMember(label);
         layout.addMember(old);
@@ -119,40 +106,36 @@
         return layout;
     }
 
-
     /**
      * This method returns the selected data.
      *
      * @return the selected/inserted data.
      */
+    @Override
     public Data[] getData() {
-        List<Data> data = new ArrayList<Data>();
+        final List<Data> data = new ArrayList<Data>();
 
-        boolean valid = saveRangeValues(inputPanel);
+        final boolean valid = saveRangeValues(this.inputPanel);
         if (valid) {
-            String f = Double.valueOf(this.from).toString();
-            String t = Double.valueOf(this.to).toString();
-            String s = Double.valueOf(this.step).toString();
-            DataItem fi = new DefaultDataItem("ld_from", "ld_from", f);
-            DataItem ti = new DefaultDataItem("ld_to", "ld_to", t);
-            DataItem si = new DefaultDataItem("ld_step", "ld_step", s);
-            data.add(new DefaultData(
-                    "ld_from", null, null, new DataItem[]{ fi }));
-            data.add(new DefaultData(
-                    "ld_to", null, null, new DataItem[]{ ti }));
-            data.add(new DefaultData(
-                    "ld_step", null, null, new DataItem[]{ si }));
+            final String f = Double.valueOf(this.from).toString();
+            final String t = Double.valueOf(this.to).toString();
+            final String s = Double.valueOf(this.step).toString();
+            final DataItem fi = new DefaultDataItem("ld_from", "ld_from", f);
+            final DataItem ti = new DefaultDataItem("ld_to", "ld_to", t);
+            final DataItem si = new DefaultDataItem("ld_step", "ld_step", s);
+            data.add(new DefaultData("ld_from", null, null, new DataItem[] { fi }));
+            data.add(new DefaultData("ld_to", null, null, new DataItem[] { ti }));
+            data.add(new DefaultData("ld_step", null, null, new DataItem[] { si }));
         }
         // what else?
         return data.toArray(new Data[data.size()]);
     }
 
+    protected boolean saveRangeValues(final DoubleRangePanel p) {
+        final FormItem[] items = p.getFields();
+        final boolean valid = p.validateForm();
 
-    protected boolean saveRangeValues(DoubleRangePanel p) {
-        FormItem[] items = p.getFields();
-        boolean valid = p.validateForm();
-
-        if(valid) {
+        if (valid) {
             this.from = p.getFrom();
             this.to = p.getTo();
             this.step = p.getStep();
@@ -160,45 +143,45 @@
         return valid;
     }
 
-
     @Override
-    public void setValues(String cid, boolean checked) {
+    public void setValues(final String cid, final boolean checked) {
         // No user interaction, do nothing.
     }
 
-
     @Override
     public boolean renderCheckboxes() {
         // No selection, return false.
         return false;
     }
 
-
+    @Override
     public void success() {
-        inputPanel.setValues(fixInfo.getFrom(), fixInfo.getTo(), 100d);
+        this.inputPanel.setValues(this.fixInfo.getLowerKm(), // TODO: check if revert makes sense
+                this.fixInfo.getUpperKm(), 100d);
     }
 
     /**
      * This method is used to validate the inserted data in the form fields.
      *
-     * @param event The BlurEvent that gives information about the FormItem that
-     * has been modified and its value.
+     * @param event
+     *            The BlurEvent that gives information about the FormItem that
+     *            has been modified and its value.
      */
-    public void onBlur(BlurEvent event) {
-        FormItem item = event.getItem();
-        String  field = item.getFieldName();
+    @Override
+    public void onBlur(final BlurEvent event) {
+        final FormItem item = event.getItem();
+        final String field = item.getFieldName();
 
         if (field == null) {
             return;
         }
-        DoubleRangePanel p = (DoubleRangePanel) event.getForm();
+        final DoubleRangePanel p = (DoubleRangePanel) event.getForm();
     }
 
-
-    public void dumpGWT(String cid) {
+    public void dumpGWT(final String cid) {
         GWT.log("Setting values for cId: " + cid);
-        GWT.log("River: " + fixInfo.getRiver());
-        GWT.log("Date: " + fixInfo.getEventByCId(cid).getDate());
-        GWT.log("Name: " + fixInfo.getEventByCId(cid).getDescription());
+        GWT.log("River: " + this.fixInfo.getRiver());
+        GWT.log("Date: " + this.fixInfo.getEventByCId(cid).getDate());
+        GWT.log("Name: " + this.fixInfo.getEventByCId(cid).getDescription());
     }
 }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixationPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixationPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,6 +8,20 @@
 
 package org.dive4elements.river.client.client.ui.fixation;
 
+import java.util.Date;
+import java.util.HashMap;
+
+import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.services.FixingsOverviewService;
+import org.dive4elements.river.client.client.services.FixingsOverviewServiceAsync;
+import org.dive4elements.river.client.client.ui.AbstractUIProvider;
+import org.dive4elements.river.client.shared.model.AbstractFixBunduArtifact;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.FixFilter;
+import org.dive4elements.river.client.shared.model.FixingsOverviewInfo;
+
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.http.client.URL;
 import com.google.gwt.i18n.client.DateTimeFormat;
@@ -16,7 +30,6 @@
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONString;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-
 import com.smartgwt.client.types.Alignment;
 import com.smartgwt.client.util.SC;
 import com.smartgwt.client.widgets.Button;
@@ -36,41 +49,21 @@
 import com.smartgwt.client.widgets.tab.Tab;
 import com.smartgwt.client.widgets.tab.TabSet;
 
-import org.dive4elements.river.client.client.Config;
-import org.dive4elements.river.client.client.FLYSConstants;
-import org.dive4elements.river.client.client.services.FixingsOverviewService;
-import org.dive4elements.river.client.client.services.FixingsOverviewServiceAsync;
-import org.dive4elements.river.client.client.ui.AbstractUIProvider;
-import org.dive4elements.river.client.shared.model.Data;
-import org.dive4elements.river.client.shared.model.DataList;
-import org.dive4elements.river.client.shared.model.FixAnalysisArtifact;
-import org.dive4elements.river.client.shared.model.FixFilter;
-import org.dive4elements.river.client.shared.model.FixingsOverviewInfo;
-
-import java.util.Date;
-import java.util.HashMap;
-
-
 /**
  * This UIProvider creates helper panel for fixation analysis without input
  * elements.
  *
  * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public abstract class FixationPanel
-extends               AbstractUIProvider
-implements            ResizedHandler
-{
+public abstract class FixationPanel extends AbstractUIProvider implements ResizedHandler {
     private static final long serialVersionUID = -3667553404493415619L;
 
-    protected static HashMap<String, FixationPanel> instances =
-        new HashMap<String, FixationPanel>();
+    protected static HashMap<String, FixationPanel> instances = new HashMap<String, FixationPanel>();
 
     /** The message class that provides i18n strings. */
     protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
 
-    protected FixingsOverviewServiceAsync overviewService =
-        GWT.create(FixingsOverviewService.class);
+    protected FixingsOverviewServiceAsync overviewService = GWT.create(FixingsOverviewService.class);
 
     protected String htmlOverview;
     protected FixingsOverviewInfo fixInfo;
@@ -81,16 +74,13 @@
     protected Img chartImg;
     protected TextItem kmText;
 
-    public static final DateTimeFormat DTF = DateTimeFormat.getFormat(
-        "dd.MM.yyyy");
-
+    public static final DateTimeFormat DTF = DateTimeFormat.getFormat("dd.MM.yyyy");
 
     public FixationPanel() {
-        chartImg = new Img();
-        htmlOverview = "";
+        this.chartImg = new Img();
+        this.htmlOverview = "";
     }
 
-
     /** Get the (master) artifact UUID. */
     protected String getArtifactUuid() {
         return this.artifact.getUuid();
@@ -105,14 +95,14 @@
     }
 
     @Override
-    public Canvas create(DataList list) {
-        VLayout layout = new VLayout();
+    public Canvas create(final DataList list) {
+        final VLayout layout = new VLayout();
 
-        Canvas helper = createHelper();
+        final Canvas helper = createHelper();
         this.helperContainer.addMember(helper);
 
-        Canvas submit = getNextButton();
-        Canvas widget = createWidget(list);
+        final Canvas submit = getNextButton();
+        final Canvas widget = createWidget(list);
 
         layout.addMember(widget);
         layout.addMember(submit);
@@ -120,147 +110,143 @@
     }
 
     @Override
-    public Canvas createOld(DataList list) {
+    public Canvas createOld(final DataList list) {
         return new DynamicForm();
     }
 
     protected Canvas createHelper() {
-        Config config    = Config.getInstance();
-        String locale    = config.getLocale ();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-        tabs = new TabSet();
-        events = new Tab(MESSAGES.events());
-        chart = new Tab(MESSAGES.kmchart());
+        this.tabs = new TabSet();
+        this.events = new Tab(this.MESSAGES.events());
+        this.chart = new Tab(this.MESSAGES.kmchart());
 
-        chartContainer = new VLayout();
-        Canvas scroll = createChartHelper();
+        this.chartContainer = new VLayout();
+        final Canvas scroll = createChartHelper();
 
-        VLayout layout = new VLayout();
+        final VLayout layout = new VLayout();
         layout.addResizedHandler(this);
-        layout.addMember(chartContainer);
+        layout.addMember(this.chartContainer);
         layout.addMember(scroll);
         layout.setAlign(Alignment.CENTER);
-        chart.setPane(layout);
+        this.chart.setPane(layout);
 
         final HTMLPane eventPane = new HTMLPane();
 
-        String river = artifact.getArtifactDescription().getRiver();
+        final String river = this.artifact.getArtifactDescription().getRiver();
         createCallback();
 
-        String callBack = "fixationCallback(this.checked, this.name)";
-
-        if (this.artifact instanceof FixAnalysisArtifact == false)
-            return chartContainer;
-
-        FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact;
+        final String callBack = "fixationCallback(this.checked, this.name)";
 
-        overviewService.generateOverview(
-            locale,
-            artifact.getUuid(),
-            getOverviewFilter(art.getFilter()),
-            renderCheckboxes(),
-            callBack,
-            new AsyncCallback<FixingsOverviewInfo>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Could not receive overview.");
-                    SC.warn(caught.getMessage());
-                }
-                @Override
-                public void onSuccess(FixingsOverviewInfo info) {
-                    GWT.log("Successfully loaded overview.");
-                    fixInfo = info;
-                    htmlOverview = info.getHTML();
-                    FixAnalysisArtifact art = (FixAnalysisArtifact)artifact;
-                    FixFilter filter = art.getFilter();
-                    filter.setRiver(info.getRiver());
-                    if (filter.getCurrentKm() == -Double.MAX_VALUE ||
-                        filter.getCurrentKm() == -1d) {
-                        filter.setCurrentKm(info.getFrom());
-                        filter.setToKm(info.getTo());
+        if (this.artifact instanceof AbstractFixBunduArtifact == false)
+            return this.chartContainer;
+
+        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
+
+        this.overviewService.generateOverview(locale, this.artifact.getUuid(), getOverviewFilter(art.getFilter()),
+                renderCheckboxes(), callBack, new AsyncCallback<FixingsOverviewInfo>() {
+                    @Override
+                    public void onFailure(final Throwable caught) {
+                        GWT.log("Could not receive overview.");
+                        SC.warn(caught.getMessage());
                     }
-                    if (kmText != null) {
-                        NumberFormat nf = NumberFormat.getDecimalFormat();
-                        try {
-                            double d = Double.valueOf(filter.getCurrentKm());
-                            kmText.setValue(nf.format(d));
-                        } catch (NumberFormatException e) {
-                            kmText.setValue(filter.getCurrentKm());
+
+                    @Override
+                    public void onSuccess(final FixingsOverviewInfo info) {
+                        GWT.log("Successfully loaded overview.");
+                        FixationPanel.this.fixInfo = info;
+                        FixationPanel.this.htmlOverview = info.getHTML();
+                        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) FixationPanel.this.artifact;
+                        final FixFilter filter = art.getFilter();
+                        filter.setRiver(info.getRiver());
+                        if (filter.getCurrentKm() == -Double.MAX_VALUE || filter.getCurrentKm() == -1d) {
+                            filter.setCurrentKm(filter.getLowerKm());
+                            filter.setToKm(filter.getUpperKm());
                         }
+                        if (FixationPanel.this.kmText != null) {
+                            final NumberFormat nf = NumberFormat.getDecimalFormat();
+                            try {
+                                final double d = Double.valueOf(filter.getCurrentKm());
+                                FixationPanel.this.kmText.setValue(nf.format(d));
+                            }
+                            catch (final NumberFormatException e) {
+                                FixationPanel.this.kmText.setValue(filter.getCurrentKm());
+                            }
+                        }
+                        eventPane.setContents(FixationPanel.this.htmlOverview);
+                        updateChartTab(FixationPanel.this.fixInfo.getLowerKm());
+                        FixationPanel.this.events.setPane(eventPane);
+                        success();
                     }
-                    eventPane.setContents(htmlOverview);
-                    updateChartTab(fixInfo.getFrom());
-                    events.setPane(eventPane);
-                    success();
-                }
-            });
+                });
 
-        tabs.addTab(events);
-        tabs.addTab(chart);
+        this.tabs.addTab(this.events);
+        this.tabs.addTab(this.chart);
 
-        return tabs;
+        return this.tabs;
     }
 
-
     protected Canvas createChartHelper() {
-        DynamicForm form = new DynamicForm();
-        Button lower = new Button("<<");
+        final DynamicForm form = new DynamicForm();
+        final Button lower = new Button("<<");
         lower.setWidth(30);
-        Button upper = new Button(">>");
+        final Button upper = new Button(">>");
         upper.setWidth(30);
-        kmText = new TextItem();
-        kmText.setWidth(60);
-        kmText.setShowTitle(false);
+        this.kmText = new TextItem();
+        this.kmText.setWidth(60);
+        this.kmText.setShowTitle(false);
 
-
-        form.setFields(kmText);
+        form.setFields(this.kmText);
         form.setWidth(60);
         lower.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(ClickEvent ce) {
-                FixFilter filter = updateChartTabLow();
-                NumberFormat nf = NumberFormat.getDecimalFormat();
+            public void onClick(final ClickEvent ce) {
+                final FixFilter filter = updateChartTabLow();
+                final NumberFormat nf = NumberFormat.getDecimalFormat();
                 try {
-                    double d = Double.valueOf(filter.getCurrentKm());
-                    kmText.setValue(nf.format(d));
-                } catch (NumberFormatException e) {
-                    kmText.setValue(filter.getCurrentKm());
+                    final double d = Double.valueOf(filter.getCurrentKm());
+                    FixationPanel.this.kmText.setValue(nf.format(d));
+                }
+                catch (final NumberFormatException e) {
+                    FixationPanel.this.kmText.setValue(filter.getCurrentKm());
                 }
             }
         });
 
         upper.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(ClickEvent ce) {
-                FixFilter filter = updateChartTabUp();
-                NumberFormat nf = NumberFormat.getDecimalFormat();
+            public void onClick(final ClickEvent ce) {
+                final FixFilter filter = updateChartTabUp();
+                final NumberFormat nf = NumberFormat.getDecimalFormat();
                 try {
-                    double d = Double.valueOf(filter.getCurrentKm());
-                    kmText.setValue(nf.format(d));
-                } catch (NumberFormatException e) {
-                    kmText.setValue(filter.getCurrentKm());
+                    final double d = Double.valueOf(filter.getCurrentKm());
+                    FixationPanel.this.kmText.setValue(nf.format(d));
+                }
+                catch (final NumberFormatException e) {
+                    FixationPanel.this.kmText.setValue(filter.getCurrentKm());
                 }
             }
         });
 
-        kmText.addChangedHandler(new ChangedHandler() {
+        this.kmText.addChangedHandler(new ChangedHandler() {
             @Override
-            public void onChanged(ChangedEvent ce) {
-                //TODO: get current value.
-                if(ce.getItem().getValue() != null) {
-                    NumberFormat nf = NumberFormat.getDecimalFormat();
+            public void onChanged(final ChangedEvent ce) {
+                // TODO: get current value.
+                if (ce.getItem().getValue() != null) {
+                    final NumberFormat nf = NumberFormat.getDecimalFormat();
                     try {
-                        double d = nf.parse(ce.getItem().getValue().toString());
+                        final double d = nf.parse(ce.getItem().getValue().toString());
                         updateChartTab(d);
                     }
-                    catch(NumberFormatException nfe) {
+                    catch (final NumberFormatException nfe) {
                         // Do nothing.
                     }
                 }
             }
         });
 
-        HLayout layout = new HLayout();
+        final HLayout layout = new HLayout();
         layout.setAlign(Alignment.CENTER);
 
         layout.addMember(lower);
@@ -270,122 +256,123 @@
     }
 
     protected void updateChartTab(double km) {
-        Config config    = Config.getInstance();
-        String locale    = config.getLocale ();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-        FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact;
+        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
 
-        if (fixInfo != null) {
-            if (km < fixInfo.getFrom()) km = fixInfo.getFrom();
-            if (km > fixInfo.getTo())   km = fixInfo.getTo();
+        // was soll das all
+        if (this.fixInfo != null) {
+            if (km < this.fixInfo.getLowerKm())
+                km = this.fixInfo.getLowerKm();
+            // if (km > this.fixInfo.getTo())
+            // km = this.fixInfo.getTo();
         }
 
-        FixFilter filter = art.getFilter();
+        final FixFilter filter = art.getFilter();
 
-        if (km < filter.getFromKm()) km = filter.getFromKm();
-        if (km > filter.getToKm())   km = filter.getToKm();
+        if (km < filter.getLowerKm())
+            km = filter.getLowerKm();
+        if (km > filter.getUpperKm())
+            km = filter.getUpperKm();
 
         filter.setCurrentKm(km);
 
-        int hWidth = helperContainer.getWidth() - 12;
-        int hHeight = helperContainer.getHeight() - 62;
+        int hWidth = this.helperContainer.getWidth() - 12;
+        int hHeight = this.helperContainer.getHeight() - 62;
 
-        if ((int)(hHeight *4f/3) < hWidth) {
-            hWidth = (int)(hHeight * 4f/3);
-        }
-        else {
-            hHeight = (int)(hWidth *3f/4);
+        if ((int) (hHeight * 4f / 3) < hWidth) {
+            hWidth = (int) (hHeight * 4f / 3);
+        } else {
+            hHeight = (int) (hWidth * 3f / 4);
         }
 
-        String imgUrl = URL.encode(GWT.getModuleBaseURL()
-            + "fixings-km-chart"
-            + "?locale=" + locale
-            + "&filter=" + getChartFilter(filter, hWidth, hHeight));
+        final String imgUrl = URL.encode(GWT.getModuleBaseURL()
+                + "fixings-km-chart"
+                + "?locale=" + locale
+                + "&filter=" + getChartFilter(filter, hWidth, hHeight));
 
-        if (chartContainer.hasMember(chartImg)) {
-            chartImg.setWidth(hWidth);
-            chartImg.setHeight(hHeight);
-            chartImg.setSrc(imgUrl);
-        }
-        else {
-            chartImg = new Img(imgUrl, hWidth, hHeight);
-            chartContainer.addMember(chartImg);
+        if (this.chartContainer.hasMember(this.chartImg)) {
+            this.chartImg.setWidth(hWidth);
+            this.chartImg.setHeight(hHeight);
+            this.chartImg.setSrc(imgUrl);
+        } else {
+            this.chartImg = new Img(imgUrl, hWidth, hHeight);
+            this.chartContainer.addMember(this.chartImg);
         }
     }
 
-
     protected FixFilter updateChartTabLow() {
-        FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact;
+        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
 
-        FixFilter filter = art.getFilter();
+        final FixFilter filter = art.getFilter();
 
-        double curr = filter.getCurrentKm();
-        if (curr > filter.getFromKm()) {
-            double newVal = (curr - 0.1) * 10;
-            long round = Math.round(newVal);
-            updateChartTab(((double)round) / 10);
+        final double curr = filter.getCurrentKm();
+        if (curr > filter.getLowerKm()) {
+            final double newVal = (curr - 0.1) * 10;
+            final long round = Math.round(newVal);
+            updateChartTab(((double) round) / 10);
         }
         return filter;
     }
 
-
     protected FixFilter updateChartTabUp() {
-        FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact;
+        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
 
-        FixFilter filter = art.getFilter();
+        final FixFilter filter = art.getFilter();
 
-        double curr = filter.getCurrentKm();
-        if (curr < filter.getToKm()) {
-            double newVal = (curr + 0.1) * 10;
-            long round = Math.round(newVal);
-            updateChartTab(((double)round) / 10);
+        final double curr = filter.getCurrentKm();
+        if (curr < filter.getUpperKm()) {
+            final double newVal = (curr + 0.1) * 10;
+            final long round = Math.round(newVal);
+            updateChartTab(((double) round) / 10);
         }
         return filter;
     }
 
-
     @Override
-    public void onResized(ResizedEvent re) {
-        FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact;
+    public void onResized(final ResizedEvent re) {
+        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
 
         updateChartTab(art.getFilter().getCurrentKm());
     }
 
-
     private native void createCallback() /*-{
         $wnd.fixationCallback = @org.dive4elements.river.client.client.ui.fixation.FixationPanel::helperCallback(ZLjava/lang/String;);
     }-*/;
 
-    private static void helperCallback(boolean checked, String name) {
-        String[] parts = name.split(":");
-        String uuid = parts[0];
-        String cid = parts[1];
+    private static void helperCallback(final boolean checked, final String name) {
+        final String[] parts = name.split(":");
+        final String uuid = parts[0];
+        final String cid = parts[1];
 
-        FixationPanel p = FixationPanel.getInstance(uuid);
+        final FixationPanel p = FixationPanel.getInstance(uuid);
         if (p != null) {
             p.setValues(cid, checked);
         }
     }
 
-    private static FixationPanel getInstance(String uuid) {
+    private static FixationPanel getInstance(final String uuid) {
         return instances.get(uuid);
     }
 
     public abstract Canvas createWidget(DataList data);
+
     public abstract void setValues(String cid, boolean checked);
+
     public abstract boolean renderCheckboxes();
+
     public abstract void success();
 
-
     /** Creates JSON string from filter. */
-    public static String getOverviewFilter(FixFilter filter) {
-        String river = filter.getRiver();
+    public static String getOverviewFilter(final FixFilter filter) {
+        final String river = filter.getRiver();
 
         if (river != null && river.length() > 0) {
-            JSONObject jfix = new JSONObject();
-            JSONObject jfilter = new JSONObject();
-            JSONObject jrName = new JSONObject();
-            JSONString jrValue = new JSONString(river);
+            final JSONObject jfix = new JSONObject();
+            final JSONObject jfilter = new JSONObject();
+            final JSONObject jrName = new JSONObject();
+            final JSONString jrValue = new JSONString(river);
             jrName.put("name", jrValue);
             jfilter.put("river", jrName);
             jfix.put("fixings", createFilter(filter, jfilter));
@@ -394,24 +381,22 @@
         return "";
     }
 
-    public String getChartFilter(FixFilter filter, int width, int height) {
-        String river     = filter.getRiver();
-        double currentKm = filter.getCurrentKm();
-        double fromKm    = filter.getFromKm();
-        double toKm      = filter.getToKm();
+    public String getChartFilter(final FixFilter filter, final int width, final int height) {
+        final String river = filter.getRiver();
+        final double currentKm = filter.getCurrentKm();
+        final double fromKm = filter.getLowerKm();
+        final double toKm = filter.getUpperKm();
 
-        if (river != null && river.length() > 0 &&
-            currentKm >= fromKm && currentKm <= toKm)
-        {
-            JSONObject jfix = new JSONObject();
-            JSONObject jfilter = new JSONObject();
-            JSONObject jrName = new JSONObject();
-            JSONString jrValue = new JSONString(river);
-            JSONObject jkm = new JSONObject();
-            JSONNumber jkmValue = new JSONNumber(currentKm);
-            JSONObject jextent = new JSONObject();
-            JSONNumber jwidth = new JSONNumber(width);
-            JSONNumber jheight = new JSONNumber(height);
+        if (river != null && river.length() > 0 && currentKm >= fromKm && currentKm <= toKm) {
+            final JSONObject jfix = new JSONObject();
+            final JSONObject jfilter = new JSONObject();
+            final JSONObject jrName = new JSONObject();
+            final JSONString jrValue = new JSONString(river);
+            final JSONObject jkm = new JSONObject();
+            final JSONNumber jkmValue = new JSONNumber(currentKm);
+            final JSONObject jextent = new JSONObject();
+            final JSONNumber jwidth = new JSONNumber(width);
+            final JSONNumber jheight = new JSONNumber(height);
 
             jkm.put("value", jkmValue);
             jrName.put("name", jrValue);
@@ -426,69 +411,67 @@
         return "";
     }
 
-    protected static JSONObject createFilter(
-        FixFilter filter,
-        JSONObject root
-    ) {
-        double fromKm = filter.getFromKm();
-        double toKm   = filter.getToKm();
-        boolean hasDate = filter.hasDate();
+    protected static JSONObject createFilter(final FixFilter filter, final JSONObject root) {
+        final double fromKm = filter.getLowerKm();
+        final double toKm = filter.getUpperKm();
+        final boolean hasDate = filter.hasDate();
 
         if (fromKm >= 0 && toKm >= 0 && fromKm <= toKm) {
-            JSONObject range = new JSONObject();
-            JSONObject fromtokm = new JSONObject();
-            JSONNumber f = new JSONNumber(fromKm);
-            JSONNumber t = new JSONNumber(toKm);
+            final JSONObject range = new JSONObject();
+            final JSONObject fromtokm = new JSONObject();
+            final JSONNumber f = new JSONNumber(fromKm);
+            final JSONNumber t = new JSONNumber(toKm);
             fromtokm.put("from", f);
             fromtokm.put("to", t);
             root.put("range", fromtokm);
         }
 
-        JSONObject and = new JSONObject();
+        final JSONObject and = new JSONObject();
         if (hasDate) {
-            long fromDate = filter.getFromDate();
-            long toDate   = filter.getToDate();
+            final long fromDate = filter.getFromDate();
+            final long toDate = filter.getToDate();
 
-            Date df = new Date(fromDate);
-            Date dt = new Date(toDate);
+            final Date df = new Date(fromDate);
+            final Date dt = new Date(toDate);
 
-            JSONObject daterange = new JSONObject();
-            JSONString f = new JSONString(DTF.format(df));
-            JSONString t = new JSONString(DTF.format(dt));
+            final JSONObject daterange = new JSONObject();
+            final JSONString f = new JSONString(DTF.format(df));
+            final JSONString t = new JSONString(DTF.format(dt));
 
             daterange.put("from", f);
             daterange.put("to", t);
             and.put("date-range", daterange);
         }
 
-        int fromClass = filter.getFromClass();
-        int toClass   = filter.getToClass();
+        final int fromClass = filter.getFromClass();
+        final int toClass = filter.getToClass();
 
         if (fromClass >= 0 && toClass >= 0 && fromClass <= toClass) {
-            JSONObject classrange = new JSONObject();
-            JSONNumber f = new JSONNumber(fromClass);
-            JSONNumber t = new JSONNumber(toClass);
+            final JSONObject classrange = new JSONObject();
+            final JSONNumber f = new JSONNumber(fromClass);
+            final JSONNumber t = new JSONNumber(toClass);
 
             classrange.put("from", f);
             classrange.put("to", t);
             and.put("sector-range", classrange);
         }
 
-        int[] events = filter.getEvents();
+        final int[] events = filter.getEvents();
 
         if (events.length > 0) {
-            StringBuilder cids = new StringBuilder();
+            final StringBuilder cids = new StringBuilder();
 
             for (int i = 0; i < events.length; i++) {
-                if (i > 0) cids.append(' ');
+                if (i > 0)
+                    cids.append(' ');
                 cids.append(events[i]);
             }
-            JSONObject columns = new JSONObject();
+            final JSONObject columns = new JSONObject();
             columns.put("cids", new JSONString(cids.toString()));
             and.put("columns", columns);
         }
         if (and.size() > 0) {
-            JSONObject jFilter = new JSONObject();
+            final JSONObject jFilter = new JSONObject();
             jFilter.put("and", and);
             root.put("filter", jFilter);
         }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/BedHeightsDatacagePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/BedHeightsDatacagePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,90 +8,62 @@
 
 package org.dive4elements.river.client.client.ui.minfo;
 
+import java.util.List;
+
+import org.dive4elements.river.client.client.ui.AbstractPairRecommendationPanel;
+import org.dive4elements.river.client.client.ui.DatacageWidget;
+import org.dive4elements.river.client.client.ui.DatacageWidgetData;
+import org.dive4elements.river.client.client.ui.DefaultDatacageTwinPanelInfo;
+import org.dive4elements.river.client.client.ui.RecommendationPairRecord;
+import org.dive4elements.river.client.client.ui.WaterlevelTwinPanelValidator;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.ToLoad;
+import org.dive4elements.river.client.shared.model.User;
+
 import com.google.gwt.core.client.GWT;
-
 import com.smartgwt.client.util.SC;
 import com.smartgwt.client.widgets.Button;
 import com.smartgwt.client.widgets.Canvas;
-
 import com.smartgwt.client.widgets.events.ClickEvent;
 import com.smartgwt.client.widgets.events.ClickHandler;
-
+import com.smartgwt.client.widgets.grid.ListGrid;
 import com.smartgwt.client.widgets.layout.VLayout;
 import com.smartgwt.client.widgets.tree.TreeNode;
 
-import org.dive4elements.river.client.client.FLYSConstants;
-
-import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
-import org.dive4elements.river.client.client.services.RemoveArtifactServiceAsync;
-
-import org.dive4elements.river.client.client.ui.DatacageTwinPanel;
-import org.dive4elements.river.client.client.ui.DatacageWidget;
-import org.dive4elements.river.client.client.ui.RecommendationPairRecord;
-
-import org.dive4elements.river.client.shared.model.DataList;
-import org.dive4elements.river.client.shared.model.ToLoad;
-
-import org.dive4elements.river.client.shared.model.Recommendation;
-import org.dive4elements.river.client.shared.model.User;
-
-import java.util.ArrayList;
-import java.util.List;
-
-// TODO Probably better to branch off AbstractUIProvider.
-public class BedHeightsDatacagePanel
-extends      DatacageTwinPanel {
+public class BedHeightsDatacagePanel extends AbstractPairRecommendationPanel {
 
-    protected static FLYSConstants MSG = GWT.create(FLYSConstants.class);
-
-    /**
-     * List to track previously selected but now removed pairs. (Needed to
-     * be able to identify artifacts that can be removed from the collection.
-     */
-    protected List<RecommendationPairRecord> removedPairs =
-        new ArrayList<RecommendationPairRecord>();
+    private static final DefaultDatacageTwinPanelInfo INFO = new DefaultDatacageTwinPanelInfo(null, "bedheight", null);
 
-    /** Service handle to clone and add artifacts to collection. */
-    LoadArtifactServiceAsync loadArtifactService = GWT.create(
-        org.dive4elements.river.client.client.services
-        .LoadArtifactService.class);
+    private static final long serialVersionUID = 1L;
 
-    /** Service to remove artifacts from collection. */
-    RemoveArtifactServiceAsync removeArtifactService = GWT.create(
-        org.dive4elements.river.client.client.services
-        .RemoveArtifactService.class);
-
-    protected DatacageWidget datacage;
-
-    public BedHeightsDatacagePanel(User user) {
-        super(user);
+    public BedHeightsDatacagePanel(final User user) {
+        // FIXME: This will lead to a bad error message in English (i.e. contains something about waterlevels), for
+        // M-Info/Bed-Differences calculation
+        // BUT: this is the behavior of 3.2.1 (because of sloppy derivation), so we do not change it now
+        super(user, new WaterlevelTwinPanelValidator(), INFO, INFO);
     }
 
-    /**
-     * Creates graphical representation and interaction widgets for the data.
-     * @param dataList the data.
-     * @return graphical representation and interaction widgets for data.
-     */
     @Override
-    public Canvas create(DataList dataList) {
+    protected Canvas createChooserWidgets(final Canvas widget, final DataList dataList, final User user, final ListGrid differencesList) {
         GWT.log("createData()");
 
-        Canvas widget = createWidget();
-        Canvas submit = getNextButton();
-        datacage = new DatacageWidget(
-            this.artifact, user, "minfo_diff_panel", "load-system:true", false);
+        final Canvas submit = getNextButton();
 
-        Button plusBtn = new Button(MSG.datacage_add_pair());
+        final DatacageWidgetData data = new DatacageWidgetData(this.artifact, user, "minfo_diff_panel", "load-system:true", false);
+
+        final DatacageWidget datacage = new DatacageWidget(data);
+
+        final Button plusBtn = new Button(msg().datacage_add_pair());
         plusBtn.setAutoFit(true);
         plusBtn.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(ClickEvent event) {
-                plusClicked();
+            public void onClick(final ClickEvent event) {
+                plusClicked(datacage, differencesList);
             }
         });
 
-        VLayout layout       = new VLayout();
-        VLayout helperLayout = new VLayout();
+        final VLayout layout = new VLayout();
+        final VLayout helperLayout = new VLayout();
         helperLayout.addMember(datacage);
         helperLayout.addMember(plusBtn);
 
@@ -100,69 +72,42 @@
         layout.setMembersMargin(10);
         this.helperContainer.addMember(helperLayout);
 
-        populateGrid(dataList, "bedheight");
-
         return layout;
     }
 
-    public void adjustRecommendation(Recommendation recommendation) {
-        recommendation.setFactory("bedheight");
-    }
-
-    @Override
-    protected String createDataString(
-        String artifact,
-        Recommendation recommendation
-    ) {
-        return createDataString(artifact, recommendation, "bedheight");
-    }
-
     /**
      * Callback for add-button.
      * Fires to load for every selected element and handler.
+     *
+     * @param differencesList
      */
-    public void plusClicked() {
-        List<TreeNode> selection = datacage.getPlainSelection();
+    protected final static void plusClicked(final DatacageWidget datacage, final ListGrid differencesList) {
+        final List<TreeNode> selection = datacage.getPlainSelection();
 
         if (selection == null || selection.isEmpty()) {
-            SC.say(MSG.warning());
+            SC.say(msg().warning());
             return;
         }
 
-        for (TreeNode node : selection) {
-            ToLoad toLoad1 = new ToLoad();
-            ToLoad toLoad2 = new ToLoad();
-
-            String factory = node.getAttribute("factory");
-            if (factory != null) { // we need at least a factory
-                String artifact    = node.getAttribute("artifact-id");
-                String out         = node.getAttribute("out");
-                String name        = node.getAttribute("facet");
-                String ids         = node.getAttribute("ids");
-                String info        = node.getAttribute("info");
-                String targetOut   = node.getAttribute("target_out");
+        for (final TreeNode node : selection) {
+            final ToLoad toLoad1 = new ToLoad();
+            final ToLoad toLoad2 = new ToLoad();
 
-                String[] splitIds = ids.split("#");
-                String[] splitInfo = info.split("#");
-                toLoad1.add(artifact,
-                     factory,
-                     out,
-                     name,
-                     splitIds[0],
-                     splitInfo[0],
-                     targetOut);
-                toLoad2.add(artifact,
-                     factory,
-                     out,
-                     name,
-                     splitIds[1],
-                     splitInfo[1],
-                     targetOut);
+            final String factory = node.getAttribute("factory");
+            if (factory != null) { // we need at least a factory
+                final String artifact = node.getAttribute("artifact-id");
+                final String out = node.getAttribute("out");
+                final String name = node.getAttribute("facet");
+                final String ids = node.getAttribute("ids");
+                final String info = node.getAttribute("info");
+                final String targetOut = node.getAttribute("target_out");
+
+                final String[] splitIds = ids.split("#");
+                final String[] splitInfo = info.split("#");
+                toLoad1.add(artifact, factory, out, name, splitIds[0], splitInfo[0], targetOut);
+                toLoad2.add(artifact, factory, out, name, splitIds[1], splitInfo[1], targetOut);
             }
-            differencesList.addData(new RecommendationPairRecord(
-                toLoad1.toRecommendations().get(0),
-                toLoad2.toRecommendations().get(0)));
+            differencesList.addData(new RecommendationPairRecord(toLoad1.toRecommendations().get(0), toLoad2.toRecommendations().get(0)));
         }
     }
-}
-// 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/ui/minfo/SedLoadDistancePanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadDistancePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,17 +10,6 @@
 
 import java.util.List;
 
-import com.smartgwt.client.data.Record;
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
-import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
-import com.smartgwt.client.widgets.grid.events.CellClickEvent;
-import com.smartgwt.client.widgets.grid.events.CellClickHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
-
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.ui.AbstractUIProvider;
 import org.dive4elements.river.client.client.ui.DoubleRangeOnlyPanel;
@@ -34,11 +23,18 @@
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.grid.events.CellClickEvent;
+import com.smartgwt.client.widgets.grid.events.CellClickHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
 
-public class SedLoadDistancePanel
-extends AbstractUIProvider
-implements BlurHandler, CellClickHandler
-{
+public class SedLoadDistancePanel extends AbstractUIProvider implements BlurHandler, CellClickHandler {
     public static final String FIELD_LOWER = "ld_from";
     public static final String FIELD_UPPER = "ld_to";
 
@@ -48,14 +44,14 @@
     protected LocationPicker picker;
 
     @Override
-    public Canvas createOld(DataList dataList) {
-        String s = getOldSelectionString(dataList);
-        String l = dataList.getLabel();
+    public Canvas createOld(final DataList dataList) {
+        final String s = getOldSelectionString(dataList);
+        final String l = dataList.getLabel();
 
-        Label label    = new Label(l);
-        Label selected = new Label(s);
+        final Label label = new Label(l);
+        final Label selected = new Label(s);
 
-        HLayout layout = new HLayout();
+        final HLayout layout = new HLayout();
 
         layout.setWidth(400);
         label.setWidth(200);
@@ -68,174 +64,171 @@
         return layout;
     }
 
-    protected String getOldSelectionString(DataList dataList) {
-        List<Data> items = dataList.getAll();
-
-        Data dFrom = getData(items, FIELD_LOWER);
-        Data dTo   = getData(items, FIELD_UPPER);
+    protected String getOldSelectionString(final DataList dataList) {
+        final List<Data> items = dataList.getAll();
 
-        DataItem[] from = dFrom.getItems();
-        DataItem[] to   = dTo.getItems();
+        final Data dFrom = getData(items, FIELD_LOWER);
+        final Data dTo = getData(items, FIELD_UPPER);
 
-        StringBuilder sb = new StringBuilder();
+        final DataItem[] from = dFrom.getItems();
+        final DataItem[] to = dTo.getItems();
+
+        final StringBuilder sb = new StringBuilder();
         sb.append(from[0].getLabel());
-        sb.append(" " + MSG.dpUnitFrom() + " - ");
+        sb.append(" " + this.MSG.dpUnitFrom() + " - ");
         sb.append(to[0].getLabel());
-        sb.append(" " + MSG.dpUnitTo());
+        sb.append(" " + this.MSG.dpUnitTo());
 
         return sb.toString();
     }
 
     @Override
-    public Canvas create(DataList data) {
-        picker = new LocationPicker(this);
-        distancePanel = new DoubleRangeOnlyPanel(
-            MSG.dpUnitFrom() + " - ",
-            MSG.dpUnitTo(), 0d, 0d, 250, this, "right");
-        VLayout layout = new VLayout();
+    public Canvas create(final DataList data) {
+        this.picker = new LocationPicker(this);
+        this.distancePanel = new DoubleRangeOnlyPanel(this.MSG.dpUnitFrom() + " - ", this.MSG.dpUnitTo(), 0d, 0d, 250, this, "right");
+        final VLayout layout = new VLayout();
         layout.setMembersMargin(10);
 
-        Label label = new Label(MSG.distance_state());
+        final Label label = getLabel(data);
 
-        Canvas submit = getNextButton();
+        final Canvas submit = getNextButton();
 
         label.setHeight(25);
-        distancePanel.setHeight(50);
+        this.distancePanel.setHeight(50);
 
         layout.addMember(label);
-        layout.addMember(distancePanel);
+        layout.addMember(this.distancePanel);
         layout.addMember(submit);
 
         initMinMaxValues(data);
         initDefaultValues(data);
 
+        this.picker.setIsDistance(true);
+        this.picker.getLocationTable().setAutoFetchData(true);
+        this.picker.prepareFilter();
 
-        picker.setIsDistance(true);
-        picker.getLocationTable().setAutoFetchData(true);
-        picker.prepareFilter();
-
-        helperContainer.addMember(picker.getLocationTable());
-        helperContainer.addMember(picker.getFilterLayout());
-        helperContainer.addMember(picker.getResultCountForm());
+        this.helperContainer.addMember(this.picker.getLocationTable());
+        this.helperContainer.addMember(this.picker.getFilterLayout());
+        this.helperContainer.addMember(this.picker.getResultCountForm());
 
         setPickerDataSource();
-        picker.createLocationTable();
+        this.picker.createLocationTable();
 
         return layout;
     }
 
-    protected void initMinMaxValues(DataList data) {
-        Data f = getData(data.getAll(), FIELD_LOWER);
-        Data t = getData(data.getAll(), FIELD_UPPER);
+    protected void initMinMaxValues(final DataList data) {
+        final Data f = getData(data.getAll(), FIELD_LOWER);
+        final Data t = getData(data.getAll(), FIELD_UPPER);
 
-        DataItem[] fItems = f.getItems();
-        DataItem[] tItems = t.getItems();
+        final DataItem[] fItems = f.getItems();
+        final DataItem[] tItems = t.getItems();
 
         try {
-            min = Double.valueOf(fItems[0].getStringValue());
-            max = Double.valueOf(tItems[0].getStringValue());
+            this.min = Double.valueOf(fItems[0].getStringValue());
+            this.max = Double.valueOf(tItems[0].getStringValue());
         }
-        catch (NumberFormatException nfe) {
-            min = -Double.MAX_VALUE;
-            max =  Double.MAX_VALUE;
+        catch (final NumberFormatException nfe) {
+            this.min = -Double.MAX_VALUE;
+            this.max = Double.MAX_VALUE;
         }
     }
 
-    protected void initDefaultValues(DataList data) {
+    protected void initDefaultValues(final DataList data) {
         initDefaultFrom(data);
         initDefaultTo(data);
     }
 
-    protected void initDefaultFrom(DataList data) {
-        Data f = getData(data.getAll(), FIELD_LOWER);
+    private Label getLabel(final DataList data) {
+        final Data item = data.get(0);
+        // if (data.getState().contains("uinfo")) { // "Wahl der Berechnungsstrecke/des Darstellungsbereichs" (server) vs.
+        // "Berechnungsstrecke wählen" (client)
+        return new Label(item.getDescription()); // holt das Label vom Server (funktoniert schon sehr oft so!)
+        // }
+        // return new Label(getLabel()); // holt das Label aus den Flys-Constants..
+    }
+
+    protected void initDefaultFrom(final DataList data) {
+        final Data f = getData(data.getAll(), FIELD_LOWER);
 
         double from = getDefaultFrom();
 
         try {
             from = getDefaultValue(f);
         }
-        catch (NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             // do nothing
         }
 
-        distancePanel.setFrom(from);
+        this.distancePanel.setFrom(from);
     }
 
-
     protected double getDefaultFrom() {
-        return min;
+        return this.min;
     }
 
-
-    protected void initDefaultTo(DataList data) {
-        Data t = getData(data.getAll(), FIELD_UPPER);
+    protected void initDefaultTo(final DataList data) {
+        final Data t = getData(data.getAll(), FIELD_UPPER);
 
         double to = getDefaultTo();
 
         try {
             to = getDefaultValue(t);
         }
-        catch (NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             // do nothing
         }
 
-        distancePanel.setTo(to);
+        this.distancePanel.setTo(to);
     }
 
-
     protected double getDefaultTo() {
-        return max;
+        return this.max;
     }
 
-    protected double getDefaultValue(Data data)
-    throws NumberFormatException
-    {
-        DataItem def      = data.getDefault();
-        String   defValue = def != null ? def.getStringValue() : null;
+    protected double getDefaultValue(final Data data) throws NumberFormatException {
+        final DataItem def = data.getDefault();
+        final String defValue = def != null ? def.getStringValue() : null;
 
         return Double.valueOf(defValue);
     }
 
     /** Hook service to the listgrid with possible input values. */
     protected void setPickerDataSource() {
-        Config config = Config.getInstance();
-        String url    = config.getServerUrl();
-        String river  = "";
+        final Config config = Config.getInstance();
+        final String url = config.getServerUrl();
+        String river = "";
 
-        ArtifactDescription adescr = artifact.getArtifactDescription();
-        DataList[] data = adescr.getOldData();
+        final ArtifactDescription adescr = this.artifact.getArtifactDescription();
+        final DataList[] data = adescr.getOldData();
 
         // Try to find a "river" data item to set the source for the
         // list grid.
         String dataFilter = "locations";
         if (data != null && data.length > 0) {
-            for (int i = 0; i < data.length; i++) {
-                DataList dl = data[i];
+            for (final DataList dl : data) {
                 if (dl.getState().equals("state.minfo.river")) {
                     dataFilter = "measuringpoint";
                 }
-                if (dl.getState().equals("state.winfo.river") ||
-                    dl.getState().equals("state.chart.river") ||
-                    dl.getState().equals("state.minfo.river")) {
+                if (dl.getState().equals("state.winfo.river") || dl.getState().equals("state.chart.river") || dl.getState().equals("state.minfo.river")) {
                     for (int j = 0; j < dl.size(); j++) {
-                        Data d = dl.get(j);
-                        DataItem[] di = d.getItems();
+                        final Data d = dl.get(j);
+                        final DataItem[] di = d.getItems();
                         if (di != null && di.length == 1) {
-                           river = d.getItems()[0].getStringValue();
-                           break;
+                            river = d.getItems()[0].getStringValue();
+                            break;
                         }
                     }
                 }
             }
         }
 
-        picker.getLocationTable().setDataSource(new DistanceInfoDataSource(
-            url, river, dataFilter));
+        this.picker.getLocationTable().setDataSource(new DistanceInfoDataSource(url, river, dataFilter));
     }
 
     @Override
     protected Data[] getData() {
-        Data[] data = new Data[2];
+        final Data[] data = new Data[2];
 
         data[0] = getDataFrom();
         data[1] = getDataTo();
@@ -244,42 +237,45 @@
     }
 
     protected Data getDataFrom() {
-        String value = String.valueOf(distancePanel.getFrom());
-        String field = FIELD_LOWER;
+        final String value = String.valueOf(this.distancePanel.getFrom());
+        final String field = FIELD_LOWER;
 
-        DataItem item = new DefaultDataItem(field, field, value);
-        return new DefaultData(
-            field, null, null, new DataItem[] { item });
+        final DataItem item = new DefaultDataItem(field, field, value);
+        return new DefaultData(field, null, null, new DataItem[] { item });
     }
 
     protected Data getDataTo() {
-        String value = String.valueOf(distancePanel.getTo());
-        String field = FIELD_UPPER;
+        final String value = String.valueOf(this.distancePanel.getTo());
+        final String field = FIELD_UPPER;
 
-        DataItem item = new DefaultDataItem(field, field, value);
-        return new DefaultData(
-            field, null, null, new DataItem[] { item });
+        final DataItem item = new DefaultDataItem(field, field, value);
+        return new DefaultData(field, null, null, new DataItem[] { item });
     }
 
     @Override
-    public void onBlur(BlurEvent event) {
-        distancePanel.validateForm();
+    public void onBlur(final BlurEvent event) {
+        this.distancePanel.validateForm();
     }
 
     @Override
-    public void onCellClick(CellClickEvent e) {
-        Record record = e.getRecord();
-        int ndx = e.getColNum();
-        String from   = record.getAttribute("from");
+    public void onCellClick(final CellClickEvent e) {
+        final Record record = e.getRecord();
+        final int ndx = e.getColNum();
+        final String from = record.getAttribute("from");
         try {
-            double value = Double.valueOf(from);
+            final double value = Double.valueOf(from);
             switch (ndx) {
-                case 0: distancePanel.setFrom(value); break;
-                case 1: distancePanel.setTo(value); break;
+            case 0:
+                this.distancePanel.setFrom(value);
+                break;
+            case 1:
+                this.distancePanel.setTo(value);
+                break;
             }
         }
-        catch(NumberFormatException nfe) {
-            SC.warn(MSG.wrongFormat());
+        catch (final NumberFormatException nfe) {
+            SC.warn(this.MSG.wrongFormat());
         }
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/sinfo/CollisionLoadEpochPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,128 @@
+/* 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.client.client.ui.sinfo;
+
+import org.dive4elements.river.client.client.ui.AbstractEpochPanel;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+public class CollisionLoadEpochPanel extends AbstractEpochPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected String getDatakey() {
+        return "epochs";
+    }
+
+    public CollisionLoadEpochPanel() {
+        super(Type.multi);
+    }
+
+    @Override
+    protected Canvas createWidget(final DataList data) {
+        final HLayout input = new HLayout();
+        final VLayout root = new VLayout();
+        final VLayout grid = new VLayout();
+        final VLayout intFields = new VLayout();
+        final Button add = new Button(this.MSG.add_date());
+        final ListGrid elements = createListGrid();
+        elements.setWidth(185);
+        elements.setHeight(120);
+
+        final Label title = new Label(data.get(0).getDescription());
+        title.setHeight("25px");
+
+        final DynamicForm form = new DynamicForm();
+        form.setNumCols(4);
+        final TextItem start = createStartInputItem(this.MSG.from());
+        final TextItem end = createEndInputItem(this.MSG.to());
+
+        form.setFields(start, end);
+        add.addClickHandler(new ClickHandler() {
+            @Override
+            public void onClick(final ClickEvent ce) {
+                final String v1 = start.getValueAsString();
+                final String v2 = end.getValueAsString();
+                if (v1 == null || v2 == null) {
+                    return;
+                }
+                if (!isValidEpoch(v1, v2)) {
+                    return;
+                }
+                final ListGridRecord r = new ListGridRecord();
+                r.setAttribute("from", v1);
+                r.setAttribute("to", v2);
+                elements.addData(r);
+            }
+        });
+
+        final Label sel = new Label(this.MSG.select());
+        sel.setHeight(25);
+
+        final ListGridField from = new ListGridField("from", this.MSG.from());
+        final ListGridField to = new ListGridField("to", this.MSG.to());
+        from.setWidth(70);
+        to.setWidth(70);
+
+        final ListGridField removeField = new ListGridField("_removeRecord", "Remove Record") {
+            {
+                setType(ListGridFieldType.ICON);
+                setIcon(GWT.getHostPageBaseURL() + CollisionLoadEpochPanel.this.MSG.removeFeature());
+                setCanEdit(false);
+                setCanFilter(false);
+                setCanSort(false);
+                setCanGroupBy(false);
+                setCanFreeze(false);
+                setWidth(25);
+            }
+        };
+
+        elements.addRecordClickHandler(new RecordClickHandler() {
+            @Override
+            public void onRecordClick(final RecordClickEvent event) {
+                // Just handle remove-clicks
+                if (!event.getField().getName().equals(removeField.getName())) {
+                    return;
+                }
+                event.getViewer().removeData(event.getRecord());
+            }
+        });
+
+        elements.setFields(from, to, removeField);
+
+        intFields.addMember(form);
+        intFields.addMember(add);
+        grid.addMember(sel);
+        grid.addMember(elements);
+        input.addMember(intFields);
+        input.addMember(grid);
+        root.addMember(title);
+        root.addMember(input);
+
+        return root;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/sinfo/CollisionLoadYearPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,57 @@
+/* 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.client.client.ui.sinfo;
+
+import org.dive4elements.river.client.client.ui.AbstractSingleItemPanel;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+public class CollisionLoadYearPanel extends AbstractSingleItemPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public CollisionLoadYearPanel() {
+        super(Type.multi);
+    }
+
+    @Override
+    protected String getDatakey() {
+        return "years"; // MULTIPLE; get From server (sinfo.xml data for state)
+    }
+
+    @Override
+    public Canvas createWidget(final DataList data) {
+        final VLayout layout = new VLayout();
+
+        final Label title = new Label(data.get(0).getDescription());
+        title.setHeight("25px");
+
+        final DynamicForm form = new DynamicForm();
+        form.setNumCols(4);
+
+        final TextItem inputItem = createInputItem(this.MSG.years());
+        inputItem.setWidth(100);
+        form.setFields(inputItem);
+
+        layout.addMember(title);
+        layout.addMember(form);
+
+        return layout;
+    }
+
+    @Override
+    protected String errorForItemMsg() {
+        return this.MSG.no_data_for_year();
+    }
+}
\ 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/FlowDepthMinMaxTwinPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,32 @@
+/** 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.NilDatacageTwinPanelInfo;
+import org.dive4elements.river.client.shared.model.User;
+
+/**
+ * @author Gernot Belger
+ */
+public final class FlowDepthMinMaxTwinPanel extends DatacageTwinPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final DefaultDatacageTwinPanelInfo LEFT_INFO = new DefaultDatacageTwinPanelInfo(MSG.sinfo_columnlabel_soundings(), "bedheight",
+            "sinfo_flowdepthminmax_heights");
+
+    private static final NilDatacageTwinPanelInfo RIGHT_INFO = new NilDatacageTwinPanelInfo(MSG.sinfo_columnlabel_waterlevels(), "sinfo_flowdepth_waterlevels");
+
+    public FlowDepthMinMaxTwinPanel(final User user) {
+        super(user, new FlowDepthTwinPanelValidator(), new WaterlevelSoundingSelectionController(MSG), LEFT_INFO, RIGHT_INFO, 9999, "");
+    }
+}
\ 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/FlowDepthTwinPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,33 @@
+/** 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.NilDatacageTwinPanelInfo;
+import org.dive4elements.river.client.shared.model.User;
+
+/**
+ * @author Gernot Belger
+ */
+public final class FlowDepthTwinPanel extends DatacageTwinPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final DefaultDatacageTwinPanelInfo SOUNDING_INFO = new DefaultDatacageTwinPanelInfo(MSG.sinfo_columnlabel_soundings(), "bedheight",
+            "sinfo_flowdepth_minfo_heights");
+
+    private static final NilDatacageTwinPanelInfo WATERLEVEL_INFO = new NilDatacageTwinPanelInfo(MSG.sinfo_columnlabel_waterlevels(),
+            "sinfo_flowdepth_waterlevels");
+
+    public FlowDepthTwinPanel(final User user, final int maxCount, final String msgMaxCount) {
+        super(user, new FlowDepthTwinPanelValidator(), new WaterlevelSoundingSelectionController(MSG), SOUNDING_INFO, WATERLEVEL_INFO, maxCount, msgMaxCount);
+    }
+}
\ 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	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,38 @@
+/** 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;
+
+/**
+ * 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/sinfo/WaterlevelSoundingSelectionController.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,157 @@
+/** 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.List;
+
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.ui.DatacagePairWidget.IDatacagePairControler;
+import org.dive4elements.river.client.client.ui.DatacageWidget;
+import org.dive4elements.river.client.client.ui.DatacageWidget.DatacageFilter;
+import org.dive4elements.river.client.shared.model.AttrList;
+import org.dive4elements.river.client.shared.model.DataCageNode;
+
+import com.smartgwt.client.data.DataSource;
+import com.smartgwt.client.data.DataSourceField;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.types.FieldType;
+import com.smartgwt.client.types.TitleOrientation;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.events.ItemChangedEvent;
+import com.smartgwt.client.widgets.form.events.ItemChangedHandler;
+import com.smartgwt.client.widgets.grid.events.SelectionUpdatedEvent;
+import com.smartgwt.client.widgets.grid.events.SelectionUpdatedHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.tree.TreeNode;
+
+/**
+ * Implements special behavior when selecting soundings and waterlevels: datacage of waterlevels depends on selection of
+ * sounding.
+ *
+ * @author Gernot Belger
+ */
+final class WaterlevelSoundingSelectionController implements IDatacagePairControler {
+
+    private static final String FIELD_INTELLIGENCE = "field_intelligence";
+
+    static final String ATTRIBUTE_YEAR = "year";
+
+    private final FLYSConstants msg;
+
+    private boolean turnFilterOff;
+
+    public WaterlevelSoundingSelectionController(final FLYSConstants msg) {
+        this.msg = msg;
+    }
+
+    @Override
+    public void setup(final DatacageWidget soundingWidget, final DatacageWidget waterlevelWidget, final HLayout toolbarLayout) {
+
+        /* do not show ever any soundings that do not have a year */
+        soundingWidget.setFilter(new DatacageFilter() {
+            @Override
+            public boolean accept(final DataCageNode node) {
+
+                final AttrList attributes = node.getAttributes();
+                if (WaterlevelSoundingYearFilter.isFolder(attributes))
+                    return true;
+
+                final String year = attributes.getValue(WaterlevelSoundingSelectionController.ATTRIBUTE_YEAR);
+
+                final Integer waterlevelYear = WaterlevelSoundingYearFilter.parseYear(year);
+                if (waterlevelYear == null) {
+                    // should never happen, we should only show waterlevels that have a year
+                    return false;
+                }
+
+                return true;
+            }
+        });
+
+        /* react to selections of a sounding */
+        soundingWidget.getTreeGrid().addSelectionUpdatedHandler(new SelectionUpdatedHandler() {
+
+            @Override
+            public void onSelectionUpdated(final SelectionUpdatedEvent event) {
+                final List<TreeNode> selection = soundingWidget.getPlainSelection();
+                handleSoundingChanged(waterlevelWidget, selection);
+            }
+        });
+
+        /* check box to deactivate intellicence */
+        final DynamicForm form = createIntelligenCheckbox();
+        toolbarLayout.addMember(form);
+        form.addItemChangedHandler(new ItemChangedHandler() {
+
+            @Override
+            public void onItemChanged(final ItemChangedEvent event) {
+                final Boolean value = (Boolean) form.getValue(FIELD_INTELLIGENCE);
+                checkboxToggled(value);
+                handleSoundingChanged(waterlevelWidget, soundingWidget.getPlainSelection());
+            }
+        });
+
+        /* initialize by applying the current selection */
+        handleSoundingChanged(waterlevelWidget, soundingWidget.getPlainSelection());
+    }
+
+    private DynamicForm createIntelligenCheckbox() {
+
+        final DynamicForm form = new DynamicForm();
+        form.setTitlePrefix("");
+        form.setTitleSuffix(": ");
+        form.setTitleAlign(Alignment.LEFT);
+        form.setTitleOrientation(TitleOrientation.LEFT);
+
+        final DataSourceField item = new DataSourceField(FIELD_INTELLIGENCE, FieldType.BOOLEAN);
+        item.setTitle(this.msg.sinfo_deactivate_intelligent_datacord());
+
+        final DataSource source = new DataSource();
+        source.setFields(item);
+        form.setDataSource(source);
+
+        form.setValue(FIELD_INTELLIGENCE, false);
+
+        return form;
+    }
+
+    protected final void checkboxToggled(final Boolean selected) {
+        this.turnFilterOff = selected == null ? false : selected;
+    }
+
+    protected final void handleSoundingChanged(final DatacageWidget waterlevelWidget, final List<TreeNode> selection) {
+
+        if (this.turnFilterOff) {
+            waterlevelWidget.setFilter(DatacageWidget.ACCEPT_ALL_FILTER);
+            waterlevelWidget.getTreeGrid().setEmptyMessage(this.msg.databasket_empty());
+            return;
+        }
+
+        // more than one should never happen, as the bedhhave single selection
+        final TreeNode soundingNode = selection.isEmpty() ? null : selection.get(0);
+
+        if (soundingNode == null || soundingNode.getAttribute("factory") == null) {
+            waterlevelWidget.setFilter(DatacageWidget.ACCEPT_NONE_FILTER);
+            waterlevelWidget.getTreeGrid().setEmptyMessage(this.msg.sinfo_sounding_waterlevel_select_waterlevel());
+            return;
+        }
+
+        final Integer soundingYear = WaterlevelSoundingYearFilter.parseYear(soundingNode.getAttribute(ATTRIBUTE_YEAR));
+
+        if (soundingYear == null) {
+            // should never happen, as we should only show soundings that actually have a year
+            waterlevelWidget.setFilter(DatacageWidget.ACCEPT_NONE_FILTER);
+            waterlevelWidget.getTreeGrid().setEmptyMessage("Die gewählte Peilung hat keine Informations zum Jahr");
+        } else {
+            waterlevelWidget.setFilter(new WaterlevelSoundingYearFilter(soundingYear));
+            waterlevelWidget.getTreeGrid().setEmptyMessage(this.msg.databasket_empty());
+        }
+    }
+}
\ 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/WaterlevelSoundingYearFilter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,85 @@
+/** 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.DatacageWidget.DatacageFilter;
+import org.dive4elements.river.client.shared.model.AttrList;
+import org.dive4elements.river.client.shared.model.DataCageNode;
+
+/**
+ * @author Gernot Belger
+ */
+final class WaterlevelSoundingYearFilter implements DatacageFilter {
+
+    private final int soundingYear;
+
+    public WaterlevelSoundingYearFilter(final int soundingYear) {
+        this.soundingYear = soundingYear;
+    }
+
+    @Override
+    public boolean accept(final DataCageNode node) {
+
+        final AttrList attributes = node.getAttributes();
+
+        if (isFolder(attributes))
+            return true;
+
+        final String year = attributes.getValue(WaterlevelSoundingSelectionController.ATTRIBUTE_YEAR);
+        final Integer waterlevelYear = parseYear(year);
+        if (waterlevelYear == null) {
+            // should never happen, we should only show waterlevels that have a year
+            return false;
+        }
+
+        final int diff = Math.abs(this.soundingYear - waterlevelYear);
+
+        return diff <= getMaxYearDifference();
+    }
+
+    private int getMaxYearDifference() {
+
+        if (this.soundingYear < 1918)
+            return 25;
+
+        if (1918 <= this.soundingYear && this.soundingYear < 1958)
+            return 12;
+
+        if (1958 <= this.soundingYear && this.soundingYear < 1998)
+            return 6;
+
+        // > 1998
+        return 3;
+    }
+
+    static Integer parseYear(final String year) {
+
+        if (year == null || year.trim().isEmpty())
+            return null;
+
+        try {
+            return Integer.valueOf(year);
+        }
+        catch (final NumberFormatException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    static boolean isFolder(final AttrList attributes) {
+        if (attributes == null)
+            return true;
+
+        if (!attributes.hasAttribute("factory"))
+            return true;
+
+        return false;
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/GaugeListGrid.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/GaugeListGrid.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,15 +11,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.grid.ListGridField;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
-import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
-
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYS;
 import org.dive4elements.river.client.client.services.AdvanceService;
@@ -41,40 +32,49 @@
 import org.dive4elements.river.client.shared.model.GaugeInfo;
 import org.dive4elements.river.client.shared.model.RiverInfo;
 
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
 
 /**
  * @author <a href="mailto:bjoern.ricks@intevation.de">Björn Ricks</a>
  */
 public class GaugeListGrid extends InfoListGrid implements RecordClickHandler {
 
+    public static enum DisappearType {
+        remove, collapse, stayVisible
+    }
+
     private static final int ABFLUSSTAFEL_COLUMN = 6;
 
     /** The ArtifactService used to communicate with the Artifact server. */
-    protected ArtifactServiceAsync artifactService =
-        GWT.create(ArtifactService.class);
-
-    /** The StepForwardService used to put data into an existing artifact. */
-    protected StepForwardServiceAsync forwardService =
-        GWT.create(StepForwardService.class);
-
-    /** The ArtifactService used to communicate with the Artifact server. */
-    protected CreateCollectionServiceAsync createCollectionService =
-        GWT.create(CreateCollectionService.class);
+    protected ArtifactServiceAsync artifactService = GWT.create(ArtifactService.class);
 
     /** The StepForwardService used to put data into an existing artifact. */
-    protected AdvanceServiceAsync advanceService =
-        GWT.create(AdvanceService.class);
+    protected StepForwardServiceAsync forwardService = GWT.create(StepForwardService.class);
 
-    public GaugeListGrid(FLYS flys) {
+    /** The ArtifactService used to communicate with the Artifact server. */
+    protected CreateCollectionServiceAsync createCollectionService = GWT.create(CreateCollectionService.class);
+
+    /** The StepForwardService used to put data into an existing artifact. */
+    protected AdvanceServiceAsync advanceService = GWT.create(AdvanceService.class);
+
+    private final List<GaugeInfo> gauges = new ArrayList<GaugeInfo>();
+
+    public GaugeListGrid(final FLYS flys) {
         super(flys);
-        //TODO i18n!!!
-        ListGridField nfield = new ListGridField("name", "Pegel");
-        ListGridField sfield = new ListGridField("kmstart", "Start [km]", 60);
-        ListGridField efield = new ListGridField("kmend", "Ende [km]", 60);
-        ListGridField stfield = new ListGridField("station", "Station [km]");
-        ListGridField lfield = new ListGridField("infolink", "Info");
-        ListGridField cfield = new ListGridField(
-            "curvelink", MSG.gauge_curve_link());
+        // TODO i18n!!!
+        final ListGridField nfield = new ListGridField("name", "Pegel");
+        final ListGridField sfield = new ListGridField("kmstart", "Start [km]", 60);
+        final ListGridField efield = new ListGridField("kmend", "Ende [km]", 60);
+        final ListGridField stfield = new ListGridField("station", "Station [km]");
+        final ListGridField lfield = new ListGridField("infolink", "Info");
+        final ListGridField cfield = new ListGridField("curvelink", this.MSG.gauge_curve_link());
         cfield.addRecordClickHandler(this);
 
         this.setShowRecordComponents(true);
@@ -82,127 +82,121 @@
         this.setFields(nfield, sfield, efield, stfield, lfield, cfield);
     }
 
-    public void setRiverInfo(RiverInfo riverinfo) {
-        List<GaugeInfo> gauges = riverinfo.getGauges();
+    @Override
+    public void setRiverInfo(final RiverInfo riverinfo) {
+        final List<GaugeInfo> gauges = riverinfo.getGauges();
 
         if (gauges != null && !gauges.isEmpty()) {
 
-            ArrayList<GaugeInfo> emptygauges = new ArrayList<GaugeInfo>();
+            final ArrayList<GaugeInfo> emptygauges = new ArrayList<GaugeInfo>();
 
             if (!riverinfo.isKmUp()) {
-                for (GaugeInfo gauge : gauges) {
+                for (final GaugeInfo gauge : gauges) {
                     addGauge(gauge, emptygauges);
                 }
-            }
-            else {
-                for (int i = gauges.size()-1; i >= 0; i--) {
-                    GaugeInfo gauge = gauges.get(i);
+            } else {
+                for (int i = gauges.size() - 1; i >= 0; i--) {
+                    final GaugeInfo gauge = gauges.get(i);
                     addGauge(gauge, emptygauges);
                 }
             }
 
             // put empty gauges to the end
-            for (GaugeInfo gauge : emptygauges) {
+            for (final GaugeInfo gauge : emptygauges) {
                 addGauge(gauge);
             }
         }
     }
 
-    private void addGauge(GaugeInfo gauge, List<GaugeInfo> empty) {
+    private void addGauge(final GaugeInfo gauge, final List<GaugeInfo> empty) {
         if (gauge.getKmStart() != null && gauge.getKmEnd() != null) {
             addGauge(gauge);
-        }
-        else {
+        } else {
             empty.add(gauge);
         }
     }
 
-    private void addGauge(GaugeInfo gauge) {
-        this.addData(new GaugeRecord(gauge));
+    private void addGauge(final GaugeInfo gauge) {
+
+        this.gauges.add(gauge);
+
+        // this.addData(new GaugeRecord(gauge));
+
     }
 
+    @Override
     public void open() {
-        ArrayList<Double> locations = new ArrayList<Double>();
+        final ArrayList<Double> locations = new ArrayList<Double>();
 
-        if (data != null && data.length > 0) {
-            for (int i = 0; i < data.length; i++) {
-                DataList dl = data[i];
-                String state = dl.getState();
+        if (this.data != null && this.data.length > 0) {
+            for (final DataList dl : this.data) {
+
+                final String state = dl.getState();
+                DisappearType type = DisappearType.collapse;
+                if (state.contains("state.bundu.") || state.contains("state.fix.")) {
+                    type = DisappearType.remove;
+                }
+
                 GWT.log("GaugeListGrid - open " + state);
-                if (state.equals("state.winfo.location_distance")) {
+                if (state.contains(".location_distance")) {
                     Double ldfrom = null;
                     Double ldto = null;
 
-                    for (int j = dl.size()-1; j >= 0; --j) {
-                        Data d = dl.get(j);
-                        String label = d.getLabel();
-                        GWT.log("GaugeListGrid - setData - label "
-                            + label + " " + d.getStringValue());
+                    for (int j = dl.size() - 1; j >= 0; --j) {
+                        final Data d = dl.get(j);
+                        final String label = d.getLabel();
+                        GWT.log("GaugeListGrid - setData - label " + label + " " + d.getStringValue());
                         if (label.equals("ld_from")) {
                             ldfrom = getDoubleValue(d);
-                        }
-                        else if (label.equals("ld_to")) {
+                        } else if (label.equals("ld_to")) {
                             ldto = getDoubleValue(d);
-                        }
-                        else if (label.equals("ld_locations")) {
+                        } else if (label.equals("ld_locations")) {
                             getLocationsFromData(locations, d);
                             openOnLocations(locations);
                             return;
                         }
                     }
                     if (ldfrom != null) {
-                        openOnDistance(ldfrom, ldto);
+
+                        openOnDistance(ldfrom, ldto, type);
                         return;
                     }
-                }
-                else if(state.equals("state.winfo.distance_only") ||
-                        state.equals("state.winfo.distance")) {
+                } else if (state.contains(".distance_only") || state.contains(".distance")
+                        || state.contains(".location") && !state.contains(".location_distance")) {
                     Double ldfrom = null;
                     Double ldto = null;
 
-                    for (int j = dl.size()-1; j >= 0; --j) {
-                        Data d = dl.get(j);
-                        String label = d.getLabel();
-                        GWT.log("GaugeListGrid - setData - label "
-                            + label + " " + d.getStringValue());
+                    for (int j = dl.size() - 1; j >= 0; --j) {
+                        final Data d = dl.get(j);
+                        final String label = d.getLabel();
+                        GWT.log("GaugeListGrid - setData - label " + label + " " + d.getStringValue());
                         if (label.equals("ld_from")) {
                             ldfrom = getDoubleValue(d);
-                        }
-                        else if (label.equals("ld_to")) {
+                        } else if (label.equals("ld_to")) {
                             ldto = getDoubleValue(d);
                         }
                     }
 
                     if (ldfrom != null) {
-                        openOnDistance(ldfrom, ldto);
+                        openOnDistance(ldfrom, ldto, type);
                         return;
                     }
-                }
-                else if (state.equals("state.winfo.location")) {
+                } else if (state.equals("state.winfo.location")) {
                     getLocations("ld_locations", locations, dl);
                     openOnLocations(locations);
                     return;
-                }
-                else if (state
-                    .equals("state.winfo.reference.curve.input.start")
-                ) {
+                } else if (state.equals("state.winfo.reference.curve.input.start")) {
                     getLocations("reference_startpoint", locations, dl);
-                }
-                else if (state
-                    .equals("state.winfo.reference.curve.input.end")
-                ) {
+                } else if (state.equals("state.winfo.reference.curve.input.end")) {
                     getLocations("reference_endpoint", locations, dl);
-                }
-                else if (state
-                    .equals("state.winfo.historicalq.reference_gauge")
-                ) {
-                    for (int j = dl.size()-1; j >= 0; --j) {
-                        Data d = dl.get(j);
-                        String label = d.getLabel();
+                } else if (state.equals("state.winfo.historicalq.reference_gauge")) {
+                    for (int j = dl.size() - 1; j >= 0; --j) {
+                        final Data d = dl.get(j);
+                        final String label = d.getLabel();
                         if (label.equals("reference_gauge")) {
-                            String tmp = d.getStringValue();
+                            final String tmp = d.getStringValue();
                             if (tmp != null) {
-                                Long gaugereference = Long.valueOf(tmp);
+                                final Long gaugereference = Long.valueOf(tmp);
                                 if (gaugereference != null) {
                                     openOnReference(gaugereference);
                                     return;
@@ -215,40 +209,49 @@
         }
         if (!locations.isEmpty()) {
             openOnLocations(locations);
-        }
-        else {
+        } else {
             openAll();
         }
     }
 
-    void getLocations(String labelname, List<Double> locations, DataList dl) {
-        for (int j = dl.size()-1; j >= 0; --j) {
-            Data d = dl.get(j);
-            String label = d.getLabel();
+    @Override
+    public void openAll() {
+
+        GWT.log("InfoListGrid - openAll");
+
+        setData(new ListGridRecord[] {});
+        for (final GaugeInfo gauge : this.gauges) {
+            addExpandedRecord(gauge);
+        }
+    }
+
+    void getLocations(final String labelname, final List<Double> locations, final DataList dl) {
+        for (int j = dl.size() - 1; j >= 0; --j) {
+            final Data d = dl.get(j);
+            final String label = d.getLabel();
             if (label.equals(labelname)) {
                 getLocationsFromData(locations, d);
             }
         }
     }
 
-    void getLocationsFromData(List<Double> locations, Data data) {
-        DataItem[] items = data.getItems();
-        for (int k = 0; k < items.length; k++) {
-            String tmp = items[k].getStringValue();
+    void getLocationsFromData(final List<Double> locations, final Data data) {
+        final DataItem[] items = data.getItems();
+        for (final DataItem item : items) {
+            final String tmp = item.getStringValue();
             GWT.log("GaugeListGrid - getLocationsFromData " + tmp);
             if (tmp != null) {
                 if (tmp.contains(" ")) {
                     // string contains several values ...
-                    String[] values = tmp.split(" ");
-                    for(int i=0; i < values.length; i++) {
-                        Double value = Double.valueOf(values[i]);
+                    final String[] values = tmp.split(" ");
+                    for (final String value2 : values) {
+                        final Double value = Double.valueOf(value2);
                         if (value != null) {
                             locations.add(value);
                         }
                     }
-                }
-                else {
-                    Double value = Double.valueOf(tmp);
+                } else {
+                    final Double value = Double.valueOf(tmp);
                     if (value != null) {
                         locations.add(value);
                     }
@@ -257,73 +260,87 @@
         }
     }
 
-    public void openOnReference(Long number) {
+    public void openOnReference(final Long number) {
         GWT.log("GaugeListGrid - openOnReference " + number);
-        for (ListGridRecord record: this.getRecords()) {
-            GaugeRecord item = (GaugeRecord)record;
-            if (item.getOfficialNumber().equals(number)) {
-                expandRecord(item);
-            }
-            else {
-                collapseRecord(item);
+
+        setData(new ListGridRecord[] {});
+
+        for (final GaugeInfo gauge : this.gauges) {
+
+            if (gauge.getOfficialNumber().equals(number)) {
+                this.addExpandedRecord(gauge);// (gauge);
+            } else {
+                this.addCollapsedRecord(gauge);
             }
         }
     }
 
-    public void openOnDistance(Double start, Double end) {
+    public void openOnDistance(final Double start, final Double end, final DisappearType type) {
         GWT.log("GaugeListGrid - openOnDistance " + start + " " + end);
 
-        for (ListGridRecord record: this.getRecords()) {
-            GaugeRecord item = (GaugeRecord)record;
-            if (end == null && item.getKmStart() != null) {
-                if (item.getKmStart() >= start) {
-                    expandRecord(item);
+        setData(new ListGridRecord[] {});
+
+        for (final GaugeInfo gauge : this.gauges) {
+
+            if (end == null && gauge.getKmStart() != null) {
+                if (gauge.getKmStart() >= start) {
+                    addExpandedRecord(gauge);
+                } else {
+                    removeOrCollapse(gauge, type);
                 }
-                else {
-                    collapseRecord(item);
-                }
-            }
-            else if (item.getKmStart() != null && item.getKmEnd() != null) {
+            } else if (gauge.getKmStart() != null && gauge.getKmEnd() != null) {
                 // as getStart()/getEnd() return Double objects,
                 // they can be null and
                 // can cause NPEs when comparing with double... strange...
-                GWT.log("GaugeListGrid - openOnDistance item "
-                    + item.getKmStart() + " " + item.getKmEnd());
-                if ((start >= item.getKmStart() && start <= item.getKmEnd()) ||
-                      (end >= item.getKmStart() &&   end <= item.getKmEnd()) ||
-                    (start <= item.getKmStart() &&   end >= item.getKmEnd())) {
-                    expandRecord(item);
+                GWT.log("GaugeListGrid - openOnDistance item " + gauge.getKmStart() + " " + gauge.getKmEnd());
+                if ((start >= gauge.getKmStart() && start <= gauge.getKmEnd()) || (end >= gauge.getKmStart() && end <= gauge.getKmEnd())
+                        || (start <= gauge.getKmStart() && end >= gauge.getKmEnd())) {
+                    addExpandedRecord(gauge);
+                } else {
+                    removeOrCollapse(gauge, type);
                 }
-                else {
-                    collapseRecord(item);
-                }
-            }
-            else {
-                collapseRecord(item);
+            } else {
+                removeOrCollapse(gauge, type);
             }
         }
     }
 
+    private void removeOrCollapse(final GaugeInfo gauge, final DisappearType type) {
+        switch (type) {
+        case remove:
+            // Remove: gauge wird der datasource nicht hinzugefügt
+            break;
+        case collapse:
+            addCollapsedRecord(gauge);
+            break;
+        case stayVisible: // TODO: check
+            addExpandedRecord(gauge);
+            break;
+        }
+
+    }
+
     /**
      * Open Gauge entry if a location fits to the gauge.
      */
-    public void openOnLocations(List<Double> locations) {
+    public void openOnLocations(final List<Double> locations) {
         GWT.log("GaugeListGrid - openOnLocations " + locations);
 
+        setData(new ListGridRecord[] {});
+
         if (locations == null || locations.isEmpty()) {
             return;
         }
 
-        for (ListGridRecord record: this.getRecords()) {
-            GaugeRecord item = (GaugeRecord)record;
+        for (final GaugeInfo gauge : this.gauges) {
             boolean isset = false;
-            for (Double location: locations) {
+            for (final Double location : locations) {
                 if (locations == null) {
                     continue;
                 }
 
-                Double start = item.getKmStart();
-                Double end   = item.getKmEnd();
+                final Double start = gauge.getKmStart();
+                final Double end = gauge.getKmEnd();
                 if (start == null || end == null) {
                     // should not occur but avoid NullPointerException
                     continue;
@@ -335,18 +352,33 @@
                 }
             }
             if (isset) {
-                expandRecord(item);
-            }
-            else {
-                collapseRecord(item);
+                addExpandedRecord(gauge);
+            } else {
+                addCollapsedRecord(gauge);
             }
         }
     }
 
+    private void addExpandedRecord(final GaugeInfo gauge) {
+        final GaugeRecord record = new GaugeRecord(gauge);
+
+        this.addData(record);
+
+        expandRecord(record);
+    }
+
+    private void addCollapsedRecord(final GaugeInfo gauge) {
+        final GaugeRecord record = new GaugeRecord(gauge);
+
+        this.addData(record);
+
+        collapseRecord(record);
+    }
+
     @Override
-    protected Canvas getExpandPanel(ListGridRecord record) {
-        GaugeRecord item = (GaugeRecord)record;
-        return new GaugeInfoPanel(item, flys);
+    protected Canvas getExpandPanel(final ListGridRecord record) {
+        final GaugeRecord item = (GaugeRecord) record;
+        return new GaugeInfoPanel(item, this.flys);
     }
 
     /**
@@ -354,122 +386,75 @@
      * Curve view.
      */
     @Override
-    public void onRecordClick(RecordClickEvent event) {
-        final GaugeRecord gauge = (GaugeRecord)event.getRecord();
-        Config config       = Config.getInstance();
+    public void onRecordClick(final RecordClickEvent event) {
+        final GaugeRecord gauge = (GaugeRecord) event.getRecord();
+        final Config config = Config.getInstance();
         final String locale = config.getLocale();
-        createCollectionService.create(
-                locale,
-                flys.getCurrentUser().identifier(),
-                new AsyncCallback<Collection>() {
+        this.createCollectionService.create(locale, this.flys.getCurrentUser().identifier(), new AsyncCallback<Collection>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Could not create the new collection.");
+                SC.warn(FLYS.getExceptionString(GaugeListGrid.this.MSG, caught));
+            }
+
+            @Override
+            public void onSuccess(final Collection collection) {
+                GWT.log("Successfully created a new collection.");
+                createArtifact(collection, locale, gauge);
+            }
+        });
+    }
+
+    private void createArtifact(final Collection collection, final String locale, final GaugeRecord gauge) {
+        this.artifactService.create(locale, "gaugedischargecurve", null, new AsyncCallback<Artifact>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Could not create the new artifact.");
+                SC.warn(FLYS.getExceptionString(GaugeListGrid.this.MSG, caught));
+            }
+
+            @Override
+            public void onSuccess(final Artifact artifact) {
+                GWT.log("Successfully created a new artifact.");
+
+                final DataItem riverItem = new DefaultDataItem("river", "river", gauge.getRiverName());
+                final Data river = new DefaultData("river", null, null, new DataItem[] { riverItem });
+
+                final DataItem refItem = new DefaultDataItem("reference_gauge", "reference_gauge", gauge.getOfficialNumber().toString());
+                final Data ref = new DefaultData("reference_gauge", null, null, new DataItem[] { refItem });
+
+                final DataItem locItem = new DefaultDataItem("ld_locations", "ld_locations", gauge.getStation().toString());
+                final Data loc = new DefaultData("ld_locations", null, null, new DataItem[] { locItem });
+
+                final DataItem nameItem = new DefaultDataItem("gauge_name", "gauge_name", gauge.getName());
+                final Data name = new DefaultData("gauge_name", null, null, new DataItem[] { nameItem });
+
+                final Data[] data = new Data[] { river, ref, loc, name };
+                GaugeListGrid.this.forwardService.go(locale, artifact, data, new AsyncCallback<Artifact>() {
                     @Override
-                    public void onFailure(Throwable caught) {
-                        GWT.log("Could not create the new collection.");
-                        SC.warn(FLYS.getExceptionString(MSG, caught));
+                    public void onFailure(final Throwable caught) {
+                        GWT.log("Could not feed the artifact.");
+                        SC.warn(caught.getMessage());
                     }
 
                     @Override
-                    public void onSuccess(Collection collection) {
-                        GWT.log("Successfully created a new collection.");
-                        createArtifact(collection, locale, gauge);
+                    public void onSuccess(final Artifact artifact) {
+                        GWT.log("Successfully feed the artifact.");
+                        final CollectionView view = new CollectionView(GaugeListGrid.this.flys, collection, artifact);
+                        GaugeListGrid.this.flys.getWorkspace().addView(collection.identifier(), view);
+                        view.addArtifactToCollection(artifact);
                     }
-                }
-            );
-    }
-
-    private void createArtifact(
-        final Collection collection,
-        final String locale,
-        final GaugeRecord gauge
-    ) {
-        artifactService.create(
-           locale, "gaugedischargecurve", null,
-            new AsyncCallback<Artifact>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Could not create the new artifact.");
-                    SC.warn(FLYS.getExceptionString(MSG, caught));
-                }
-
-                @Override
-                public void onSuccess(Artifact artifact) {
-                    GWT.log("Successfully created a new artifact.");
-
-                    DataItem riverItem = new DefaultDataItem(
-                        "river",
-                        "river",
-                        gauge.getRiverName());
-                    Data river = new DefaultData(
-                        "river",
-                        null,
-                        null,
-                        new DataItem[]{riverItem});
-
-                    DataItem refItem = new DefaultDataItem(
-                        "reference_gauge",
-                        "reference_gauge",
-                        gauge.getOfficialNumber().toString());
-                    Data ref = new DefaultData(
-                        "reference_gauge",
-                        null,
-                        null,
-                        new DataItem[]{refItem});
-
-                    DataItem locItem = new DefaultDataItem(
-                        "ld_locations",
-                        "ld_locations",
-                        gauge.getStation().toString());
-                    Data loc = new DefaultData(
-                        "ld_locations",
-                        null,
-                        null,
-                        new DataItem[]{locItem});
-
-                    DataItem nameItem = new DefaultDataItem(
-                        "gauge_name",
-                        "gauge_name",
-                        gauge.getName());
-                    Data name = new DefaultData(
-                        "gauge_name",
-                        null,
-                        null,
-                        new DataItem[]{nameItem});
-
-                    Data[] data = new Data[]{river, ref, loc, name};
-                    forwardService.go(locale, artifact, data,
-                        new AsyncCallback<Artifact>() {
-                        @Override
-                        public void onFailure(Throwable caught) {
-                            GWT.log("Could not feed the artifact.");
-                            SC.warn(caught.getMessage());
-                        }
-
-                        @Override
-                        public void onSuccess(Artifact artifact) {
-                            GWT.log("Successfully feed the artifact.");
-                            CollectionView view = new CollectionView(
-                                flys,
-                                collection,
-                                artifact);
-                            flys.getWorkspace().addView(
-                                collection.identifier(),
-                                view);
-                            view.addArtifactToCollection(artifact);
-                        }
-                    });
-                }
-            });
+                });
+            }
+        });
     }
 
     @Override
-    public String getCellCSSText(ListGridRecord record, int rowNum,
-            int colNum) {
+    public String getCellCSSText(final ListGridRecord record, final int rowNum, final int colNum) {
         if (colNum == ABFLUSSTAFEL_COLUMN) {
             // display the ablfusstafel cell like a link
-            return "text-decoration: underline; color: #0000EE; "
-                + "cursor: pointer;";
-        }
-        else {
+            return "text-decoration: underline; color: #0000EE; " + "cursor: pointer;";
+        } else {
             return super.getCellCSSText(record, rowNum, colNum);
         }
     }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/InfoListGrid.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/InfoListGrid.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,11 +8,6 @@
 
 package org.dive4elements.river.client.client.ui.stationinfo;
 
-import com.google.gwt.core.client.GWT;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.grid.ListGrid;
-import com.smartgwt.client.widgets.grid.ListGridRecord;
-
 import org.dive4elements.river.client.client.FLYS;
 import org.dive4elements.river.client.client.FLYSConstants;
 import org.dive4elements.river.client.client.ui.WikiLinks;
@@ -20,6 +15,11 @@
 import org.dive4elements.river.client.shared.model.DataList;
 import org.dive4elements.river.client.shared.model.RiverInfo;
 
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 /**
  * @author <a href="mailto:bjoern.ricks@intevation.de">Björn Ricks</a>
  */
@@ -27,11 +27,10 @@
 
     protected FLYS flys;
     protected DataList[] data;
-    /** The message class that provides i18n strings.*/
+    /** The message class that provides i18n strings. */
     protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
 
-
-    public InfoListGrid(FLYS flys) {
+    public InfoListGrid(final FLYS flys) {
         super();
         this.flys = flys;
         this.setCanExpandRecords(true);
@@ -39,37 +38,30 @@
     }
 
     @Override
-    protected Canvas createRecordComponent(
-        final ListGridRecord record,
-        Integer colNum
-    ) {
-        String name = this.getFieldName(colNum);
+    protected Canvas createRecordComponent(final ListGridRecord record, final Integer colNum) {
+        final String name = this.getFieldName(colNum);
         if (name.equals("infolink")) {
-            return WikiLinks.linkDynamicForm(
-                flys,
-                record.getAttribute("link"),
-                record.getLinkText());
-        }
-        else {
+            return WikiLinks.linkDynamicForm(this.flys, record.getAttribute("link"), record.getLinkText());
+        } else {
             return null;
         }
     }
 
     public void openAll() {
         GWT.log("InfoListGrid - openAll");
-        for (ListGridRecord record: this.getRecords()) {
+        for (final ListGridRecord record : this.getRecords()) {
             expandRecord(record);
         }
     }
 
-    public void setData(DataList[] data) {
+    public void setData(final DataList[] data) {
         GWT.log("InfoListGrid - setData");
         this.data = data;
         this.open();
     }
 
-    protected Double getDoubleValue(Data d) {
-        String tmp = d.getStringValue();
+    protected Double getDoubleValue(final Data d) {
+        final String tmp = d.getStringValue();
         if (tmp != null) {
             return Double.valueOf(tmp);
         }
@@ -77,7 +69,7 @@
     }
 
     @Override
-    protected Canvas getExpansionComponent(ListGridRecord record) {
+    protected Canvas getExpansionComponent(final ListGridRecord record) {
         return this.getExpandPanel(record);
     }
 
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/InfoPanel.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/InfoPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -81,6 +81,7 @@
             riverinfopanel.setRiverInfo(riverinfo);
         }
         this.listgrid.setRiverInfo(riverinfo);
+        this.listgrid.open();
     }
 
     protected void removeAllMembers() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/AbstractVegZonesTablePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,261 @@
+/** 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.uinfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.river.client.client.ui.AbstractUIProvider;
+import org.dive4elements.river.client.client.ui.PanelHelper;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.VegetationZone;
+
+import com.google.gwt.core.client.GWT;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.SortNormalizer;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.Layout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class AbstractVegZonesTablePanel extends AbstractUIProvider {
+    private static final long serialVersionUID = 1L;
+
+    private static final String datakey = "vegzones";
+
+    private final ListGrid elements = new ListGrid();
+
+    protected final ListGrid createTable(final Layout root, final DataList data, final String width, final boolean editable) {
+
+        final Label title = new Label(data.get(0).getDescription());
+        title.setHeight("35px");
+
+        this.elements.setWidth(width);
+        this.elements.setHeight(300);
+        this.elements.setShowHeaderContextMenu(false);
+        this.elements.setCanReorderFields(false);
+        this.elements.setCanSort(true);
+        this.elements.setSortField(1);
+        this.elements.setCanResizeFields(false);
+
+        this.elements.setCanEdit(editable);
+
+        final ListGridField vegzoneField = new ListGridField("vegzone", this.MSG.uinfo_vegetation_zones_label());
+        vegzoneField.setType(ListGridFieldType.TEXT);
+        vegzoneField.setWidth("*"); // 245
+        vegzoneField.setCanSort(false);
+        vegzoneField.setCanDragResize(true);
+
+        final ListGridField fromField = createIntTableField("from", this.MSG.uinfo_vegetation_zones_from(), true);
+        final ListGridField toField = createIntTableField("to", this.MSG.uinfo_vegetation_zones_to(), false);// nicht sortierbar nach "ÃœFDauer bis"
+
+        if (editable) {
+            final ListGridField removeField = createRemoveField();
+            this.elements.setFields(vegzoneField, fromField, toField, removeField);
+        } else {
+            this.elements.setFields(vegzoneField, fromField, toField);
+        }
+
+        addDataInit(data);
+        root.setWidth(width);
+        root.addMember(title);
+        root.addMember(this.elements);
+        root.addMember(PanelHelper.getSpacer(10));
+
+        return this.elements;
+    }
+
+    private IntegerRangeValidator getValidator() {
+        final IntegerRangeValidator validator = new IntegerRangeValidator();
+        validator.setMin(0);
+        validator.setMax(365);
+        validator.setErrorMessage(this.MSG.uinfo_vegetation_zones_validation_range());
+        return validator;
+    }
+
+    private SortNormalizer getNormalizer() {
+        final SortNormalizer normalizer = new SortNormalizer() {
+
+            @Override
+            public Object normalize(final ListGridRecord record, final String fieldName) {
+                final String number = record.getAttribute(fieldName);
+                final String numberFormat = "000" + number;
+                return numberFormat.substring(numberFormat.length() - 3);
+            }
+        };
+        return normalizer;
+    }
+
+    private ListGridField createIntTableField(final String key, final String msg, final boolean canSort) {
+        final ListGridField intField = new ListGridField(key, msg);
+        intField.setType(ListGridFieldType.INTEGER);
+        intField.setValidators(getValidator());
+        intField.setWidth(90);
+        intField.setAlign(Alignment.RIGHT);
+        intField.setSortNormalizer(getNormalizer());
+        intField.setCanSort(canSort);
+        intField.setCanDragResize(false);
+
+        return intField;
+    }
+
+    private ListGridField createRemoveField() {
+
+        final ListGridField removeField = new ListGridField("_removeRecord", "Remove Record") {
+            {
+                setType(ListGridFieldType.ICON);
+                setIcon(GWT.getHostPageBaseURL() + AbstractVegZonesTablePanel.this.MSG.removeFeature());
+                setCanEdit(false);
+                setCanFilter(false);
+                setCanSort(false);
+                setCanGroupBy(false);
+                setCanFreeze(false);
+                setWidth(25);
+                setCanDragResize(false);
+                super.setCanToggle(false);
+            }
+        };
+
+        this.elements.addRecordClickHandler(new RecordClickHandler() {
+            @Override
+            public void onRecordClick(final RecordClickEvent event) {
+                // Just handle remove-clicks
+                if (!event.getField().getName().equals(removeField.getName())) {
+                    return;
+                }
+                event.getViewer().removeData(event.getRecord());
+            }
+        });
+
+        return removeField;
+    }
+
+    public abstract void createWidget(final Layout root, final DataList data);
+
+    private final void addDataInit(final DataList data) {
+        for (final Data dataItemContainer : data.getAll()) {
+            if (dataItemContainer.getItems() != null) {
+                for (final DataItem dataItem : dataItemContainer.getItems()) {
+                    if (dataItem.getStringValue() != null) {
+
+                        final List<VegetationZone> rows = VegetationZone.parse(dataItem.getStringValue());
+                        for (final VegetationZone row : rows) {
+                            this.elements.addData(createEntry(row));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public final Canvas create(final DataList data) {
+        final VLayout layout = new VLayout();
+
+        // TODO: Helper zur Vegetationszonen-Auswahl
+        // final Canvas helper = createHelper();
+        // this.helperContainer.addMember(helper);
+
+        final Canvas submit = getNextButton();
+
+        final VLayout root = new VLayout();
+        root.setWidth(450);
+        createWidget(root, data);
+
+        layout.addMember(root);
+        layout.addMember(submit);
+
+        return layout;
+    }
+
+    @Override
+    public Canvas createOld(final DataList dataList) {
+        final HLayout layout = new HLayout();
+        layout.setWidth("400px");
+        final VLayout vLayout = new VLayout();
+        vLayout.setWidth(130);
+        final Label label = new Label(dataList.getLabel());
+        label.setWidth("200px");
+        label.setHeight(25);
+
+        final List<Data> items = dataList.getAll();
+        final Data str = getData(items, datakey);
+        final DataItem[] strItems = str.getItems();
+
+        final List<VegetationZone> entries = VegetationZone.parse(strItems[0].getLabel());
+
+        for (final VegetationZone entry : entries) {
+            final Label dateLabel = new Label(entry.getZoneName() + " (" + entry.getMin_day_overflow() + "-" + entry.getMax_day_overflow() + ")");
+            dateLabel.setHeight(20);
+            vLayout.addMember(dateLabel);
+        }
+        final Canvas back = getBackButton(dataList.getState());
+        layout.addMember(label);
+        layout.addMember(vLayout);
+        layout.addMember(back);
+
+        return layout;
+    }
+
+    @Override
+    protected final Data[] getData() {
+        final List<Data> data = new ArrayList<Data>();
+
+        final ListGridRecord[] lgr = this.elements.getRecords();
+        if (lgr.length == 0) {
+            return new Data[0]; // TODO: Klären, ob Vegetationszonen-Auswahl Pflicht ist, ob es ein Fallback geben soll usw.
+        }
+        final List<VegetationZone> zoneList = new ArrayList<VegetationZone>();
+        for (final ListGridRecord element : lgr) {
+            final Record r = element;
+            final VegetationZone zone = VegetationZone.createFromTableEntry(r.getAttribute("vegzone"), r.getAttribute("from"), r.getAttribute("to"));
+            zoneList.add(zone);
+        }
+
+        final DataItem item = new DefaultDataItem(datakey, null, VegetationZone.parseListToDataString(zoneList)); // DATA-key
+        data.add(new DefaultData(datakey, null, null, new DataItem[] { item }));
+        return data.toArray(new Data[data.size()]);
+    }
+
+    public final ListGridRecord createEntry(final VegetationZone row) {
+
+        final String vegzone = row.getZoneName();
+        final Integer from = row.getMin_day_overflow();
+        final Integer to = row.getMax_day_overflow();
+
+        if (vegzone == null || from == null || to == null) {
+            return null;
+        }
+
+        final ListGridRecord r = new ListGridRecord();
+        r.setAttribute("vegzone", vegzone);
+        r.setAttribute("from", from);
+        r.setAttribute("to", to);
+        return r;
+
+    }
+}
\ 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/uinfo/LoadSedimentHeightPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,62 @@
+/* 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.client.client.ui.uinfo;
+
+import org.dive4elements.river.client.client.ui.AbstractSingleItemPanel;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.StaticTextItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+public class LoadSedimentHeightPanel extends AbstractSingleItemPanel {
+    private static final long serialVersionUID = 1L;
+
+    public LoadSedimentHeightPanel(final Type type) {
+        super(type);
+    }
+
+    @Override
+    protected String getDatakey() {
+        return "sedimentheight";
+    }
+
+    @Override
+    protected String errorForItemMsg() {
+        return this.MSG.no_data_sediment_difference();
+    }
+
+    @Override
+    public Canvas createWidget(final DataList data) {
+        final VLayout layout = new VLayout();
+
+        final Label title = new Label(data.get(0).getDescription());
+        title.setHeight("35px");
+
+        final DynamicForm form = new DynamicForm();
+
+        form.setNumCols(4);
+        final TextItem inputItem = createInputItem("waterlevelDifference_Name_to_prevent_errorMsg");
+        inputItem.setShowTitle(false);
+        inputItem.setWidth(200);
+        final StaticTextItem textItem = new StaticTextItem("IRRELEVANT_NAME");
+
+        textItem.setValue("cm");
+        textItem.setShowTitle(false);
+        form.setFields(inputItem, textItem);
+
+        layout.addMember(title);
+        layout.addMember(form);
+
+        return layout;
+    }
+}
\ 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/uinfo/LoadSingleYearPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,66 @@
+/* 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.client.client.ui.uinfo;
+
+import org.dive4elements.river.client.client.ui.AbstractSingleItemPanel;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+public class LoadSingleYearPanel extends AbstractSingleItemPanel {
+
+    private static final long serialVersionUID = 1L;
+    private boolean showHint = false;
+
+    public LoadSingleYearPanel() {
+        super(Type.single);
+    }
+
+    public LoadSingleYearPanel(final boolean showHint) {
+        super(Type.single);
+        this.showHint = showHint;
+    }
+
+    @Override
+    protected String getDatakey() {
+        return "singleyear";
+    }
+
+    @Override
+    protected String errorForItemMsg() {
+        return this.MSG.no_data_for_year();
+    }
+
+    @Override
+    public Canvas createWidget(final DataList data) {
+        final VLayout layout = new VLayout();
+
+        final Label title = new Label(data.get(0).getDescription());
+        title.setHeight("25px");
+
+        final DynamicForm form = new DynamicForm();
+        form.setNumCols(4);
+
+        final TextItem inputItem = createInputItem("YEAR_INPUT");
+        inputItem.setShowHint(this.showHint);
+        inputItem.setHint(this.MSG.common_input_hint_year());
+        inputItem.setShowHintInField(true);
+        inputItem.setShowTitle(false);
+        form.setFields(inputItem);
+
+        layout.addMember(title);
+        layout.addMember(form);
+
+        return layout;
+    }
+}
\ 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/uinfo/LoadSingleYearPseudoEpochPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,25 @@
+/* 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.client.client.ui.uinfo;
+
+public class LoadSingleYearPseudoEpochPanel extends LoadSingleYearPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected String getDatakey() {
+        return "singleepoch";
+    }
+
+    @Override
+    protected String errorForItemMsg() {
+        return this.MSG.no_data_for_year();// NO DATA FOR EPOCH TODO möglicherweise, wenn der ablauf klar ist
+    }
+
+}
\ 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/uinfo/SupraRegionalTablePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,423 @@
+/* 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.client.client.ui.uinfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.river.client.client.ui.AbstractUIProvider;
+import org.dive4elements.river.client.client.ui.DistancePanelInputHelper;
+import org.dive4elements.river.client.client.ui.PanelHelper;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.SalixZone;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.user.client.ui.Label;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.grid.CellEditValueFormatter;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.CellSavedEvent;
+import com.smartgwt.client.widgets.grid.events.CellSavedHandler;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.Layout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+public class SupraRegionalTablePanel extends AbstractUIProvider {
+    private static final long serialVersionUID = 1L;
+
+    private Double minKm, maxKm = -1.;
+    // private String tableData = "";
+    private ListGrid table;
+    private final String datakey = "supraregional_table";
+    final Label validationLabel = new Label();
+
+    private final NumberFormat format = NumberFormat.getDecimalFormat();
+
+    @Override
+    public Canvas createOld(final DataList dataList) {
+        final HLayout layout = new HLayout();
+        layout.setWidth("400px");
+        final VLayout vLayout = new VLayout();
+        vLayout.setWidth(130);
+        final Label label = new Label(dataList.getLabel());
+        label.setWidth("200px");
+        label.setHeight("25px");
+
+        final List<Data> items = dataList.getAll();
+        final Data str = getData(items, this.datakey);
+        final DataItem[] strItems = str.getItems();
+
+        final List<SalixZone> entries = SalixZone.parse(strItems[0].getLabel());
+
+        for (final SalixZone entry : entries) {
+            final Label dateLabel = new Label(
+                    entry.getDwsplValue() + " (" + this.format.format(entry.getFromKm()) + "-" + this.format.format(entry.getToKm()) + " km)");
+            dateLabel.setHeight("20px");
+            vLayout.addMember(dateLabel);
+        }
+        final Canvas back = getBackButton(dataList.getState());
+        layout.addMember(label);
+        layout.addMember(vLayout);
+        layout.addMember(back);
+
+        return layout;
+    }
+
+    @Override
+    public Canvas create(final DataList data) {
+
+        final Data dataItem = data.getAll().get(0);
+        String tableData = "";
+        for (final DataItem item : dataItem.getItems()) {
+            final String label = item.getLabel();
+            if (label.equals("salix_zones_min"))
+                this.minKm = Double.valueOf(item.getStringValue());
+            else if (label.equals("salix_zones_max"))
+                this.maxKm = Double.valueOf(item.getStringValue());
+            else if (label.equals("salix_zones"))
+                tableData = item.getStringValue();
+        }
+
+        if (this.minKm > this.maxKm) {
+            final double temp = this.minKm;
+            this.minKm = this.maxKm;
+            this.maxKm = temp;
+        }
+
+        final VLayout layout = new VLayout();
+        final Canvas submit = getNextButton();
+
+        final VLayout root = new VLayout();
+        root.setWidth(420);
+        createWidget(root, data, tableData);
+
+        layout.addMember(root);
+        layout.addMember(submit);
+
+        validateRangeOverlap();// init Text
+        return layout;
+    }
+
+    @Override
+    protected Data[] getData() {
+        final List<Data> data = new ArrayList<Data>();
+
+        final ListGridRecord[] lgr = this.table.getRecords();
+        if (lgr == null) {
+            return new Data[0];
+        }
+        final List<SalixZone> zoneList = getSalixZones(lgr);
+        final DataItem item = new DefaultDataItem(this.datakey, null, SalixZone.parseListToDataString(zoneList));
+        data.add(new DefaultData(this.datakey, null, null, new DataItem[] { item }));
+        return data.toArray(new Data[data.size()]);
+    }
+
+    private List<SalixZone> getSalixZones(final ListGridRecord[] lgr) {
+        final List<SalixZone> zoneList = new ArrayList<SalixZone>();
+        for (final ListGridRecord element : lgr) {
+            final Record r = element;
+            final SalixZone zone = SalixZone.createFromTableEntry(r.getAttribute("dmwspl"), r.getAttribute("from"), r.getAttribute("to"));
+            zoneList.add(zone);
+        }
+        return zoneList;
+    }
+
+    public Canvas createWidget(final Layout root, final DataList data, final String tableData) {
+
+        this.table = createTable(root, data, tableData);
+        final TextItem dwspl = PanelHelper.createItem("_label_dwspl", this.MSG.uinfo_salix_dmwspl_short(), "50");
+        final TextItem start = PanelHelper.createIntegerItem("_from_dwspl", getLabelFromTo(this.MSG.from()), "50");
+        final TextItem end = PanelHelper.createIntegerItem("_to_dwspl", getLabelFromTo(this.MSG.to()), "50");
+
+        final HLayout fields = new HLayout();
+
+        final Button add = new Button(this.MSG.add_date()); // TODO: make key more generic or change to more specific
+
+        final DynamicForm newEntryForm = new DynamicForm();
+        newEntryForm.setWidth(320);
+        newEntryForm.setNumCols(12);
+        newEntryForm.setFields(start, end, dwspl);
+
+        add.addClickHandler(new ClickHandler() {
+            @Override
+            public void onClick(final ClickEvent ce) {
+                final String v1 = start.getValueAsString();
+                final String v2 = end.getValueAsString();
+                final String v3 = dwspl.getValueAsString();
+                final String message = validate(v1, v2, v3);
+                if (message != null) {
+                    SC.warn(message);
+                    return;
+                }
+                final ListGridRecord r = new ListGridRecord();
+                r.setAttribute("dmwspl", v3);
+                r.setAttribute("from", SupraRegionalTablePanel.this.format.parse(v1));
+                r.setAttribute("to", SupraRegionalTablePanel.this.format.parse(v2));
+                SupraRegionalTablePanel.this.table.addData(r);
+                validateRangeOverlap();
+            }
+        });
+
+        fields.addMember(newEntryForm);
+
+        root.addMember(fields);
+        root.addMember(PanelHelper.getSpacer(10));
+
+        initHelperPanel(start, end);
+
+        root.addMember(add);
+        root.addMember(PanelHelper.getSpacer(20));
+        return root;
+    }
+
+    private String getLabelFromTo(final String fromOrTo) {
+        return new StringBuilder().append(fromOrTo).append(" [").append(this.MSG.dpUnitFrom()).append("]").toString();
+    }
+
+    protected void initHelperPanel(final TextItem start, final TextItem end) {
+        final DistancePanelInputHelper helper = new DistancePanelInputHelper(this.MSG, this.helperContainer, this.getRiverName());
+
+        helper.getDistancesTable().addRecordClickHandler(new RecordClickHandler() {
+            @Override
+            public void onRecordClick(final RecordClickEvent e) {
+                final Record r = e.getRecord();
+
+                final String from = r.getAttribute("from");
+                final String to = r.getAttribute("to");
+
+                try {
+                    start.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(from)));
+                    end.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(to)));
+                }
+                catch (final NumberFormatException nfe) {
+                    SC.warn(SupraRegionalTablePanel.this.MSG.wrongFormat());
+                }
+            }
+        });
+
+        helper.getLocationsTable().addRecordClickHandler(new RecordClickHandler() {
+            @Override
+            public void onRecordClick(final RecordClickEvent e) {
+                final Record r = e.getRecord();
+                final int field = e.getFieldNum();
+
+                try {
+                    final String value = r.getAttribute("from");
+                    switch (field) {
+                    case 0:
+                        start.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(value)));
+                        break;
+                    case 1:
+                        end.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(value)));
+                        break;
+                    }
+                }
+                catch (final NumberFormatException nfe) {
+                    SC.warn(SupraRegionalTablePanel.this.MSG.wrongFormat());
+                }
+            }
+        });
+
+    }
+
+    protected final ListGrid createTable(final Layout root, final DataList data, final String tableData) {
+
+        final Label title = new Label(data.get(0).getDescription());
+        title.setHeight("35px");
+        this.validationLabel.setHeight("10px");
+        this.validationLabel.getElement().getStyle().setColor("red");
+        final ListGrid elements = new ListGrid();
+        elements.setWidth(320);
+        elements.setHeight(300);
+        elements.setShowHeaderContextMenu(false);
+        elements.setCanReorderFields(false);
+        elements.setCanResizeFields(false);
+        elements.setCanEdit(true);
+        elements.setCanSort(false);
+        elements.setCanResizeFields(false);
+
+        final ListGridField dmwsplField = new ListGridField("dmwspl", this.MSG.uinfo_salix_dmwspl_short());
+        dmwsplField.setAlign(Alignment.RIGHT);
+        dmwsplField.setWidth(95);
+        dmwsplField.addCellSavedHandler(new CellSavedHandler() {
+            @Override
+            public void onCellSaved(final CellSavedEvent event) {
+                final Object value = event.getNewValue();
+                event.getRecord().setAttribute("dmwspl", event.getOldValue());
+                try {
+                    final int intValue = Integer.valueOf(String.valueOf(value));
+                    event.getRecord().setAttribute("dmwspl", intValue);
+                }
+                catch (final NumberFormatException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+        final ListGridField fromField = createDoubleTableField("from", getLabelFromTo(this.MSG.from()));
+        final ListGridField toField = createDoubleTableField("to", getLabelFromTo(this.MSG.to()));
+        final ListGridField removeField = PanelHelper.createRemoveField(elements, GWT.getHostPageBaseURL() + this.MSG.removeFeature());
+        elements.addRecordClickHandler(new RecordClickHandler() { // adding another custom record-Remove-Handler which is not included in the Panelhelper
+            @Override
+            public void onRecordClick(final RecordClickEvent event) {
+                if (event.getField().getName().equals(removeField.getName())) {
+                    validateRangeOverlap();
+                }
+            }
+        });
+        elements.setFields(fromField, toField, dmwsplField, removeField);
+        addDataInit(elements, tableData);
+
+        root.addMember(title);
+        root.addMember(elements);
+        root.addMember(PanelHelper.getSpacer(3));
+        root.addMember(this.validationLabel);
+        root.addMember(PanelHelper.getSpacer(4));
+        return elements;
+    }
+
+    private void addDataInit(final ListGrid table, final String tableData) {
+        if (tableData != null) {
+            final List<SalixZone> rows = SalixZone.parse(tableData);
+            for (final SalixZone row : rows) {
+                table.addData(createEntry(row));
+            }
+        }
+    }
+
+    public final ListGridRecord createEntry(final SalixZone row) {
+
+        final Integer dwspl = row.getDwsplValue();
+        final Double from = row.getFromKm();
+        final Double to = row.getToKm();
+
+        if (dwspl == null || from == null || to == null) {
+            return null;
+        }
+
+        final ListGridRecord r = new ListGridRecord();
+        r.setAttribute("dmwspl", dwspl);
+        r.setAttribute("from", from);
+        r.setAttribute("to", to);
+
+        return r;
+
+    }
+
+    private ListGridField createDoubleTableField(final String key, final String msg) {
+        final ListGridField field = new ListGridField(key, msg);
+        field.setAlign(Alignment.RIGHT);
+        field.setWidth(90);
+        field.addCellSavedHandler(new CellSavedHandler() {
+            @Override
+            public void onCellSaved(final CellSavedEvent event) {
+                final Object value = event.getNewValue();
+                event.getRecord().setAttribute(key, event.getOldValue());
+                try {
+                    final double d = SupraRegionalTablePanel.this.format.parse(String.valueOf(value));
+                    if (d > SupraRegionalTablePanel.this.maxKm) {
+                        event.getRecord().setAttribute(key, SupraRegionalTablePanel.this.maxKm);
+                    } else if (d < SupraRegionalTablePanel.this.minKm) {
+                        event.getRecord().setAttribute(key, SupraRegionalTablePanel.this.minKm);
+                    } else {
+                        event.getRecord().setAttribute(key, d);
+                    }
+                    validateRangeOverlap();
+                }
+                catch (final NumberFormatException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+        field.setEditValueFormatter(new CellEditValueFormatter() {
+            @Override
+            public Object format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) {
+                if (!(value instanceof Float || value instanceof Double)) {
+                    try {
+                        return (float) SupraRegionalTablePanel.this.format.parse(String.valueOf(value));
+                    }
+                    catch (final Exception e2) {
+                        return record.getAttribute(key);
+                    }
+                } else {
+                    return SupraRegionalTablePanel.this.format.format((Double) value);
+                }
+            }
+        });
+        field.setCellFormatter(new CellFormatter() {
+            @Override
+            public String format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) {
+                return SupraRegionalTablePanel.this.format.format(Double.valueOf(String.valueOf(value)));
+            }
+        });
+        return field;
+    }
+
+    private String validate(final String fromInput, final String toInput, final String dmwspl) {
+
+        final List<SalixZone> zones = getSalixZones(this.table.getRecords());
+
+        if (fromInput == null || toInput == null || dmwspl == null || fromInput.trim().isEmpty() || toInput.trim().isEmpty() || dmwspl.trim().isEmpty())
+            return this.MSG.uinfo_vegetation_zones_validation_empty();
+
+        try {
+            final Double from = this.format.parse(fromInput);
+            final Double to = this.format.parse(toInput);
+            Integer.valueOf(dmwspl);
+
+            if (!SalixZone.hasGaps(zones, this.minKm, this.maxKm))
+                return this.MSG.uinfo_salix_input_complete();
+
+            if (from < this.minKm || from > this.maxKm || to > this.maxKm || to < this.minKm)
+                return this.MSG.uinfo_salix_km_limit_exceed();
+
+            // range anschluss
+            if (!SalixZone.isValidAnschlussRange(from, to, zones, this.minKm)) {
+                return this.MSG.uinfo_salix_km_anschluss();
+            }
+            return null;
+        }
+        catch (final NumberFormatException e) {
+            return this.MSG.wrongFormat();
+        }
+    }
+
+    @Override
+    public List<String> validate() {
+        final List<String> errors = new ArrayList<String>();
+
+        if (SalixZone.zonesAreOverlapping(this.getSalixZones(this.table.getRecords())))
+            errors.add(this.MSG.uinfo_salix_km_overlap());
+        if (SalixZone.hasGaps(this.getSalixZones(this.table.getRecords()), this.minKm, this.maxKm))
+            errors.add(this.MSG.uinfo_salix_km_has_gaps());// "Der Km-Bereich wird nicht vollst. abgedeckt.";
+        return errors;
+    }
+
+    private void validateRangeOverlap() {
+        this.validationLabel.setText(validate().toString().replace("[", "").replace("]", "").replace(",", ""));
+    }
+}
\ 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/uinfo/VegetationzonesTableEditPanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,110 @@
+/* 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.client.client.ui.uinfo;
+
+import org.dive4elements.river.client.client.ui.PanelHelper;
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.layout.Layout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+public class VegetationzonesTableEditPanel extends AbstractVegZonesTablePanel {
+    private static final long serialVersionUID = 1L;
+
+    private TextItem vegzone;
+
+    private TextItem start;
+
+    private TextItem end;
+
+    @Override
+    public void createWidget(final Layout root, final DataList data) {
+
+        final ListGrid elements = super.createTable(root, data, "450", true);
+
+        this.vegzone = PanelHelper.createItem("uinfo_vegetation_zone_label", this.MSG.uinfo_vegetation_zone_label(), "*");// 450);
+        this.vegzone.setColSpan(4);
+        this.start = PanelHelper.createIntegerItem("uinfo_vegetation_zones_from", this.MSG.uinfo_vegetation_zones_from(), "*");
+        this.end = PanelHelper.createIntegerItem("uinfo_vegetation_zones_to", this.MSG.uinfo_vegetation_zones_to(), "*");
+        final VLayout fields = new VLayout();
+
+        final Button add = new Button(this.MSG.add_date()); // TODO: make key more generic or change to more specific
+
+        final DynamicForm form1 = new DynamicForm();
+
+        form1.setNumCols(4); // für Layout untereinander muss 2 eingestellt werden
+
+        form1.setFields(this.vegzone, this.start, this.end);
+
+        add.addClickHandler(new ClickHandler() {
+            @Override
+            public void onClick(final ClickEvent ce) {
+                final String v1 = VegetationzonesTableEditPanel.this.start.getValueAsString();
+                final String v2 = VegetationzonesTableEditPanel.this.end.getValueAsString();
+                final String v3 = VegetationzonesTableEditPanel.this.vegzone.getValueAsString();
+                final String message = validate(v1, v2, v3);
+                if (message != null) {
+                    SC.warn(message);
+                    return;
+                }
+
+                final ListGridRecord r = new ListGridRecord();
+                r.setAttribute("vegzone", v3);
+                r.setAttribute("from", v1);
+                r.setAttribute("to", v2);
+                elements.addData(r);
+                final String sortField = elements.getSortField();
+                if (sortField != null) {
+                    elements.toggleSort(sortField);
+                    elements.toggleSort(sortField); // HACK. has to be. otherwise normalizer won't be called :-(
+                }
+            }
+        });
+
+        fields.addMember(form1);
+
+        root.addMember(fields);
+        root.addMember(PanelHelper.getSpacer(10));
+        root.addMember(add);
+        root.addMember(PanelHelper.getSpacer(20));
+    }
+
+    protected String validate(final String v1, final String v2, final String v3) {
+
+        if (v1 == null || v2 == null || v3 == null || v1.trim().isEmpty() || v2.trim().isEmpty() || v3.trim().isEmpty())
+            return this.MSG.uinfo_vegetation_zones_validation_empty();
+
+        try {
+            final Integer from = Integer.valueOf(v1);
+            final Integer to = Integer.valueOf(v2);
+
+            if (from < 0 || from > 365)
+                return this.MSG.uinfo_vegetation_zones_validation_range();
+
+            if (to < 0 || to > 365)
+                return this.MSG.uinfo_vegetation_zones_validation_range();
+
+            if (from > to)
+                return this.MSG.uinfo_vegetation_zones_validation_from_greater_to();
+
+            return null;
+        }
+        catch (final NumberFormatException e) {
+            return this.MSG.uinfo_vegetation_zones_invalid_integer();
+        }
+    }
+}
\ 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/uinfo/VegetationzonesTablePanel.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,26 @@
+/* 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.client.client.ui.uinfo;
+
+import org.dive4elements.river.client.shared.model.DataList;
+
+import com.smartgwt.client.widgets.layout.Layout;
+
+public class VegetationzonesTablePanel extends AbstractVegZonesTablePanel {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public void createWidget(final Layout root, final DataList data) {
+
+        createTable(root, data, "420", false);
+
+        // fetchSedimentLoadData(); //TODO: feed from database...
+    }
+}
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/CSVExportServiceImpl.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/CSVExportServiceImpl.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,83 +8,68 @@
 
 package org.dive4elements.river.client.server;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.util.ArrayList;
 import java.util.List;
 
-import java.io.Reader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.IOException;
-
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.artifacts.httpclient.http.HttpClient;
+import org.dive4elements.artifacts.httpclient.http.HttpClientImpl;
+import org.dive4elements.river.client.client.services.CSVExportService;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import org.apache.log4j.Logger;
-
 import com.google.gwt.user.server.rpc.RemoteServiceServlet;
 
 import au.com.bytecode.opencsv.CSVReader;
 
-import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
-import org.dive4elements.artifacts.common.utils.XMLUtils;
-
-import org.dive4elements.artifacts.httpclient.http.HttpClient;
-import org.dive4elements.artifacts.httpclient.http.HttpClientImpl;
-
-import org.dive4elements.river.client.shared.exceptions.ServerException;
-import org.dive4elements.river.client.client.services.CSVExportService;
-
-
 /**
  * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public class CSVExportServiceImpl
-extends      RemoteServiceServlet
-implements   CSVExportService
-{
-    private static final Logger log =
-        Logger.getLogger(CSVExportServiceImpl.class);
-
+public class CSVExportServiceImpl extends RemoteServiceServlet implements CSVExportService {
+    private static final Logger log = Logger.getLogger(CSVExportServiceImpl.class);
 
-    public static final String ERROR_NO_EXPORT_FOUND =
-        "error_no_export_found";
+    public static final String ERROR_NO_EXPORT_FOUND = "error_no_export_found";
 
-    public List<String[]> getCSV(
-        String locale,
-        String uuid,
-        String name)
-    throws ServerException
-    {
+    @Override
+    public List<String[]> getCSV(final String locale, final String uuid, final String name) throws ServerException {
         log.info("CSVExportServiceImpl.getCSV");
 
-        String url  = getServletContext().getInitParameter("server-url");
-
-        Document requestDoc = XMLUtils.newDocument();
+        final String url = getServletContext().getInitParameter("server-url");
 
-        XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
-            requestDoc,
-            ArtifactNamespaceContext.NAMESPACE_URI,
-            ArtifactNamespaceContext.NAMESPACE_PREFIX);
+        final Document requestDoc = XMLUtils.newDocument();
 
-        Element action = ec.create("action");
+        final XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(requestDoc, ArtifactNamespaceContext.NAMESPACE_URI,
+                ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+        final Element action = ec.create("action");
         ec.addAttr(action, "type", "csv", true);
         ec.addAttr(action, "name", name, true);
 
         requestDoc.appendChild(action);
 
-        HttpClient client = new HttpClientImpl(url, locale);
+        final HttpClient client = new HttpClientImpl(url, locale);
 
         try {
-            InputStream in = client.collectionOut(requestDoc, uuid, "export");
-            Reader reader       = new InputStreamReader (in, "UTF-8");
-            CSVReader csvReader = new CSVReader (reader, ';');
+            final InputStream in = client.collectionOut(requestDoc, uuid, "export");
+            final Reader reader = new InputStreamReader(in, "UTF-8");
+            final CSVReader csvReader = new CSVReader(reader, ';');
 
-            List<String[]> lines = new ArrayList<String[]>();
-            String[]       line  = null;
+            final byte[] BOM = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
+            final char bomChar = new String(BOM, "UTF-8").charAt(0);
+            final StringBuilder bomCharCheckBuilder = new StringBuilder().append(bomChar).append("#");
 
+            final List<String[]> lines = new ArrayList<String[]>();
+            String[] line = null;
             while ((line = csvReader.readNext()) != null) {
                 if (line != null) {
-                    if (!line[0].startsWith("#") && line.length > 0) {
+                    if (line.length > 0 && !line[0].startsWith("#") && !line[0].startsWith(bomCharCheckBuilder.toString())) {
                         if (line[0].replace("'", "").length() > 0) {
                             lines.add(line);
                         }
@@ -94,7 +79,7 @@
 
             return lines;
         }
-        catch (IOException ce) {
+        catch (final IOException ce) {
             log.error(ce.getLocalizedMessage());
         }
 
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/ChartOutputServiceImpl.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/ChartOutputServiceImpl.java	Fri Jul 13 11:56:22 2018 +0200
@@ -44,6 +44,7 @@
 
 
     /** Handle a get, collectionOut. */
+    @Override
     public void doGet(HttpServletRequest req, HttpServletResponse resp) {
         log.info("ChartOutputServiceImpl.doGet");
 
@@ -79,13 +80,9 @@
     }
 
 
-    protected Map<String, String> prepareChartAttributes(
-        HttpServletRequest req
-    ) {
+    private Map<String, String> prepareChartAttributes( final HttpServletRequest req ) {
         Map<String, String> attr = new HashMap<String, String>();
 
-        Map params = req.getParameterMap();
-
         attr.put("width", req.getParameter("width"));
         attr.put("height", req.getParameter("height"));
         attr.put("minx", req.getParameter("minx"));
@@ -93,6 +90,7 @@
         attr.put("miny", req.getParameter("miny"));
         attr.put("maxy", req.getParameter("maxy"));
         attr.put("format", req.getParameter("format"));
+        attr.put("export", req.getParameter("export"));
         attr.put("km", req.getParameter("currentKm"));
 
         if (log.isDebugEnabled()) {
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/ChartServiceHelper.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/ChartServiceHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -62,6 +62,7 @@
 
         appendChartSize(req, attributes, ec);
         appendFormat(req, attributes, ec);
+        appendExport(req, attributes, ec);
         appendXRange(req, attributes, ec);
         appendYRange(req, attributes, ec);
         appendCurrentKm(req, attributes, ec);
@@ -174,7 +175,7 @@
      * @param doc The attribute document used to adjust chart settings.
      * @param ec The ElementCreator that might be used to create new Elements.
      */
-    protected static void appendFormat(
+    private static void appendFormat(
         Map<String, String> req,
         Element             attributes,
         ElementCreator      ec
@@ -193,6 +194,26 @@
         attributes.appendChild(format);
     }
 
+    /**
+     * This method extracts the export string from request object and appends
+     * those format - if existing - to the attribute document used to adjust
+     * the chart settings.
+     *
+     * @param req The request object that might contain the chart export flag.
+     * @param doc The attribute document used to adjust chart settings.
+     * @param ec The ElementCreator that might be used to create new Elements.
+     */
+    private static void appendExport( final Map<String, String> req, final Element attributes, final ElementCreator ec ) {
+        
+        final String exportStr = req.get("export");
+        if (exportStr == null || exportStr.isEmpty()) 
+            return;
+        
+        final Element format = ec.create("export");
+        ec.addAttr(format, "value", exportStr, true);
+        
+        attributes.appendChild(format);
+    }
 
     /**
      * This method extracts the current km for the chart from request object and
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/DataFactory.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DataFactory.java	Fri Jul 13 11:56:22 2018 +0200
@@ -14,11 +14,6 @@
 
 import javax.xml.xpath.XPathConstants;
 
-import org.w3c.dom.Attr;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
 import org.apache.log4j.Logger;
 import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
@@ -27,16 +22,21 @@
 import org.dive4elements.river.client.shared.model.DefaultData;
 import org.dive4elements.river.client.shared.model.DefaultDataItem;
 import org.dive4elements.river.client.shared.model.DoubleArrayData;
+import org.dive4elements.river.client.shared.model.IntDataItem;
 import org.dive4elements.river.client.shared.model.IntegerArrayData;
 import org.dive4elements.river.client.shared.model.IntegerData;
 import org.dive4elements.river.client.shared.model.IntegerOptionsData;
 import org.dive4elements.river.client.shared.model.IntegerRangeData;
+import org.dive4elements.river.client.shared.model.LongRangeData;
 import org.dive4elements.river.client.shared.model.MultiAttributeData;
 import org.dive4elements.river.client.shared.model.MultiDataItem;
 import org.dive4elements.river.client.shared.model.StringData;
 import org.dive4elements.river.client.shared.model.StringOptionsData;
-import org.dive4elements.river.client.shared.model.LongRangeData;
-import org.dive4elements.river.client.shared.model.IntDataItem;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
@@ -47,18 +47,18 @@
 
     public static final String NS_URI = ArtifactNamespaceContext.NAMESPACE_URI;
 
-
     /**
      * Creates a new Data instance based on the <i>art:type</i> attribute of
      * <i>element</i>.
      *
-     * @param element The Data element.
+     * @param element
+     *            The Data element.
      *
      * @return a Data instance.
      */
-    public static Data createDataFromElement(Element element) {
-        String name  = element.getAttributeNS(NS_URI, "name");
-        String type  = element.getAttributeNS(NS_URI, "type");
+    public static Data createDataFromElement(final Element element) {
+        final String name = element.getAttributeNS(NS_URI, "name");
+        String type = element.getAttributeNS(NS_URI, "type");
         String label = element.getAttributeNS(NS_URI, "label");
 
         label = label != null && label.length() > 0 ? label : name;
@@ -74,279 +74,233 @@
 
             if (type.equals(StringData.TYPE)) {
                 return createStringData(element, name, label);
-            }
-            else if (type.equals(IntegerData.TYPE)) {
+            } else if (type.equals(IntegerData.TYPE)) {
                 return createIntegerData(element, name, label);
-            }
-            else if (type.equals(StringOptionsData.TYPE)) {
+            } else if (type.equals(StringOptionsData.TYPE)) {
                 return createStringOptionsData(element, name, label);
-            }
-            else if (type.equals(IntegerOptionsData.TYPE)) {
+            } else if (type.equals(IntegerOptionsData.TYPE)) {
                 return createIntegerOptionsData(element, name, label);
-            }
-            else if (type.equals(IntegerRangeData.TYPE)) {
+            } else if (type.equals(IntegerRangeData.TYPE)) {
                 return createIntegerRangeData(element, name, label);
-            }
-            else if (type.equals(IntegerArrayData.TYPE)) {
+            } else if (type.equals(IntegerArrayData.TYPE)) {
                 return createIntegerArrayData(element, name, label);
-            }
-            else if (type.equals(DoubleArrayData.TYPE)) {
+            } else if (type.equals(DoubleArrayData.TYPE)) {
                 return createDoubleArrayData(element, name, label);
-            }
-            else if (type.equals(LongRangeData.TYPE)) {
+            } else if (type.equals(LongRangeData.TYPE)) {
                 return createLongRangeData(element, name, label);
-            }
-            else if (type.equals(MultiAttributeData.TYPE)) {
+            } else if (type.equals(MultiAttributeData.TYPE)) {
                 return createMultiAttributeData(element, name, label);
-            }
-            else {
+            } else {
                 return createDefaultData(element, name, label);
             }
         }
-        catch (Exception e) {
+        catch (final Exception e) {
             log.error("Error while data creation for: " + name);
         }
 
         return null;
     }
 
-
-    public static Data createMultiAttributeData(
-        Element element,
-        String name,
-        String label) {
-        return new MultiAttributeData(
-            name,
-            label,
-            extractMultiDataItems(element),
-            extractMeta(element));
+    public static Data createMultiAttributeData(final Element element, final String name, final String label) {
+        return new MultiAttributeData(name, label, extractMultiDataItems(element), extractMeta(element));
     }
 
-
-    private static Map<String, Map<String, String>> extractMeta(
-        Element element
-    ) {
-        NodeList nl = element.getElementsByTagName("meta");
-        int N = nl.getLength();
-        if (N < 1) {
-            log.debug("No meta data found for multi attribute data");
+    private static Map<String, Map<String, String>> extractMeta(final Element element) {
+        final NodeList nl = element.getElementsByTagName("art:meta");
+        final int N = nl.getLength();
+        if (N != 1) {
+            log.debug("No or too much meta data found for multi attribute data");
             return Collections.<String, Map<String, String>>emptyMap();
         }
-        Map<String, Map<String, String>> map =
-            new HashMap<String, Map<String, String>>();
+        final Map<String, Map<String, String>> map = new HashMap<String, Map<String, String>>();
 
-        for (int i = 0; i < N; ++i) {
-            Element e = (Element)nl.item(i);
-            NamedNodeMap attrs = e.getAttributes();
-            Map<String, String> kvs = new HashMap<String, String>();
-            for (int j = 0, A = attrs.getLength(); j < A; ++j) {
-                Attr attr = (Attr)attrs.item(j);
-                kvs.put(attr.getName(), attr.getValue());
+        final Element metaElement = (Element) nl.item(0);
+        final NodeList metaChildren = metaElement.getChildNodes();
+
+        for (int i = 0; i < metaChildren.getLength(); ++i) {
+
+            final Node childNode = metaChildren.item(i);
+            if (childNode instanceof Element) {
+
+                final Element e = (Element) childNode;
+                final NamedNodeMap attrs = e.getAttributes();
+                final Map<String, String> kvs = new HashMap<String, String>();
+                for (int j = 0, A = attrs.getLength(); j < A; ++j) {
+                    final Attr attr = (Attr) attrs.item(j);
+                    kvs.put(attr.getName(), attr.getValue());
+                }
+                map.put(e.getLocalName(), kvs);
             }
-            map.put(e.getTagName(), kvs);
         }
 
         return map;
     }
 
-
-    protected static DataItem[] extractMultiDataItems(Element element) {
-        NodeList itemList = (NodeList) XMLUtils.xpath(
-            element,
-            "art:item",
-            XPathConstants.NODESET,
-            ArtifactNamespaceContext.INSTANCE);
+    protected static DataItem[] extractMultiDataItems(final Element element) {
+        final NodeList itemList = (NodeList) XMLUtils.xpath(element, "art:item", XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);
 
         if (itemList == null || itemList.getLength() == 0) {
             log.debug("No old data items found.");
             return null;
         }
 
-        int count = itemList.getLength();
-
-        MultiDataItem[] items = new MultiDataItem[count];
-
-         for (int i = 0; i < count; i++) {
-             Element tmp = (Element) itemList.item(i);
+        final int count = itemList.getLength();
 
-             HashMap<String, String> data = new HashMap<String, String>();
-             String label = tmp.getAttributeNS(NS_URI, "label");
-             NamedNodeMap attributes = tmp.getAttributes();
-             for (int j = 0, L = attributes.getLength(); j < L; j++) {
-                 Node n = attributes.item(j);
-                 if (n.getNodeName().equals("label")) {
-                     continue;
-                 }
-                 data.put(n.getNodeName(), n.getNodeValue());
-             }
-             items[i] = new MultiDataItem(label, label, data);
-         }
-         return items;
+        final MultiDataItem[] items = new MultiDataItem[count];
+
+        for (int i = 0; i < count; i++) {
+            final Element tmp = (Element) itemList.item(i);
+
+            final HashMap<String, String> data = new HashMap<String, String>();
+            final String label = tmp.getAttributeNS(NS_URI, "label");
+            final NamedNodeMap attributes = tmp.getAttributes();
+            for (int j = 0, L = attributes.getLength(); j < L; j++) {
+                final Node n = attributes.item(j);
+                if (n.getNodeName().equals("label")) {
+                    continue;
+                }
+                data.put(n.getNodeName(), n.getNodeValue());
+            }
+            items[i] = new MultiDataItem(label, label, data);
+        }
+        return items;
     }
 
-
     /**
      * This method creates a new instance of DefaultData which has no real type
      * set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of DefaultData.
      */
-    protected static Data createDefaultData(
-        Element ele,
-        String name,
-        String label
-    ) {
+    protected static Data createDefaultData(final Element ele, final String name, final String label) {
         log.debug("Create new DefaultData");
         return new DefaultData(name, label, "default", extractDataItems(ele));
     }
 
-
     /**
      * This method creates a new instance of StringData which has a type
      * "string" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of StringData.
      */
-    protected static Data createStringData(
-        Element ele,
-        String name,
-        String label
-    ) {
+    protected static Data createStringData(final Element ele, final String name, final String label) {
         return new StringData(name, label, extractDataItems(ele));
     }
 
-
     /**
      * This method creates a new instance of DefaultData which has a type
      * "integer" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of IntegerData.
      */
-    protected static Data createIntegerData(
-        Element ele,
-        String name,
-        String label
-    ) {
+    protected static Data createIntegerData(final Element ele, final String name, final String label) {
         return new IntegerData(name, label, extractDataItems(ele));
     }
 
-
     /**
      * This method creates a new instance of StringOptionsData which has a type
      * "options" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of StringOptionsData.
      */
-    protected static Data createStringOptionsData(
-        Element ele,
-        String name,
-        String label
-    ) {
+    protected static Data createStringOptionsData(final Element ele, final String name, final String label) {
         return new StringOptionsData(name, label, extractDataItems(ele));
     }
 
-
     /**
      * This method creates a new instance of DefaultData which has a type
      * "intoptions" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of IntegerOptionsData.
      */
-    protected static Data createIntegerOptionsData(
-        Element ele,
-        String name,
-        String label
-    ) {
+    protected static Data createIntegerOptionsData(final Element ele, final String name, final String label) {
         return new IntegerOptionsData(name, label, extractDataItems(ele));
     }
 
-
     /**
      * This method creates a new instance of DefaultData which has a type
      * "intrange" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of IntegerRangeData.
      */
-    protected static Data createIntegerRangeData(
-        Element ele,
-        String name,
-        String label
-    ) {
-        DataItem[] items    = extractDataItems(ele);
-        String     rawValue = items[0].getStringValue();
+    protected static Data createIntegerRangeData(final Element ele, final String name, final String label) {
+        final DataItem[] items = extractDataItems(ele);
+        final String rawValue = items[0].getStringValue();
 
-        String[] minmax = rawValue.split(";");
+        final String[] minmax = rawValue.split(";");
 
-        return new IntegerRangeData(
-            name,
-            label,
-            Integer.valueOf(minmax[0]),
-            Integer.valueOf(minmax[1]));
+        return new IntegerRangeData(name, label, Integer.valueOf(minmax[0]), Integer.valueOf(minmax[1]));
     }
 
-
     /**
      * This method creates a new instance of DefaultData which has a type
      * "integerarray" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of IntegerArrayData.
      */
-    protected static Data createIntegerArrayData(
-        Element ele,
-        String name,
-        String label
-    ) {
-        IntDataItem[] items    = extractIntDataItems(ele);
+    protected static Data createIntegerArrayData(final Element ele, final String name, final String label) {
+        final IntDataItem[] items = extractIntDataItems(ele);
         return new IntegerArrayData(name, label, items);
     }
 
-
     /**
      * This method creates a new instance of DefaultData which has a type
      * "doublearray" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of DoubleArrayData.
      */
-    protected static Data createDoubleArrayData(
-        Element ele,
-        String name,
-        String label
-    ) {
-        DataItem[] items    = extractDataItems(ele);
-        String     rawValue = items[0].getStringValue();
+    protected static Data createDoubleArrayData(final Element ele, final String name, final String label) {
+        final DataItem[] items = extractDataItems(ele);
+        final String rawValue = items[0].getStringValue();
 
-        String[] values  = rawValue.split(";");
-        double[] doubles = new double[values.length];
+        final String[] values = rawValue.split(";");
+        final double[] doubles = new double[values.length];
 
         for (int i = 0; i < values.length; i++) {
             try {
                 doubles[i] = Double.valueOf(values[i]);
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 log.warn("Error while parsing DoubleArrayData: " + nfe);
             }
         }
@@ -354,37 +308,33 @@
         return new DoubleArrayData(name, label, doubles);
     }
 
-
     /**
      * This method extracts the art:item elements placed under <i>elements</i>.
      *
-     * @param element A data node that contains items.
+     * @param element
+     *            A data node that contains items.
      *
      * @return a list of DataItems.
      */
-    protected static DataItem[] extractDataItems(Element element) {
-        NodeList itemList = (NodeList) XMLUtils.xpath(
-            element,
-            "art:item",
-            XPathConstants.NODESET,
-            ArtifactNamespaceContext.INSTANCE);
+    protected static DataItem[] extractDataItems(final Element element) {
+        final NodeList itemList = (NodeList) XMLUtils.xpath(element, "art:item", XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);
 
         if (itemList == null || itemList.getLength() == 0) {
             log.debug("No data items found.");
             return null;
         }
 
-        int count = itemList.getLength();
+        final int count = itemList.getLength();
 
-        DataItem[] items = new DataItem[count];
+        final DataItem[] items = new DataItem[count];
 
         log.debug("There are " + count + " data items in element.");
 
         for (int i = 0; i < count; i++) {
-            Element tmp = (Element) itemList.item(i);
+            final Element tmp = (Element) itemList.item(i);
 
-            String value = tmp.getAttributeNS(NS_URI, "value");
-            String label = tmp.getAttributeNS(NS_URI, "label");
+            final String value = tmp.getAttributeNS(NS_URI, "value");
+            final String label = tmp.getAttributeNS(NS_URI, "label");
 
             log.debug("Found data item:");
             log.debug("   label: " + label);
@@ -396,71 +346,61 @@
         return items;
     }
 
-
     /**
      * This method extracts the art:item elements placed under <i>elements</i>.
      *
-     * @param element A data node that contains items.
+     * @param element
+     *            A data node that contains items.
      *
      * @return a list of DataItems.
      */
-    protected static IntDataItem[] extractIntDataItems(Element element) {
-        NodeList itemList = (NodeList) XMLUtils.xpath(
-            element,
-            "art:item",
-            XPathConstants.NODESET,
-            ArtifactNamespaceContext.INSTANCE);
+    protected static IntDataItem[] extractIntDataItems(final Element element) {
+        final NodeList itemList = (NodeList) XMLUtils.xpath(element, "art:item", XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);
 
         if (itemList == null || itemList.getLength() == 0) {
             log.debug("No old data items found.");
             return null;
         }
 
-        int count = itemList.getLength();
-
-        IntDataItem[] items = new IntDataItem[count];
-
-         for (int i = 0; i < count; i++) {
-             Element tmp = (Element) itemList.item(i);
+        final int count = itemList.getLength();
 
-             String value = tmp.getAttributeNS(NS_URI, "value");
-             String label = tmp.getAttributeNS(NS_URI, "label");
+        final IntDataItem[] items = new IntDataItem[count];
 
-             try {
-                 int data = Integer.parseInt(value);
-                 items[i] = new IntDataItem(label, label, data);
-             }
-             catch(NumberFormatException nfe) {
-                 log.debug(nfe, nfe);
-             }
-         }
-         return items;
+        for (int i = 0; i < count; i++) {
+            final Element tmp = (Element) itemList.item(i);
+
+            final String value = tmp.getAttributeNS(NS_URI, "value");
+            final String label = tmp.getAttributeNS(NS_URI, "label");
+
+            try {
+                final int data = Integer.parseInt(value);
+                items[i] = new IntDataItem(label, label, data);
+            }
+            catch (final NumberFormatException nfe) {
+                log.debug(nfe, nfe);
+            }
+        }
+        return items;
     }
 
     /**
      * This method creates a new instance of LongRangeData which has a type
      * "longrange" set.
      *
-     * @param ele The Data element.
-     * @param name The name of the Data instance.
+     * @param ele
+     *            The Data element.
+     * @param name
+     *            The name of the Data instance.
      *
      * @return an instance of IntegerRangeData.
      */
-    protected static Data createLongRangeData(
-        Element ele,
-        String name,
-        String label
-    ) {
-        DataItem[] items    = extractDataItems(ele);
-        String     rawValue = items[0].getStringValue();
+    protected static Data createLongRangeData(final Element ele, final String name, final String label) {
+        final DataItem[] items = extractDataItems(ele);
+        final String rawValue = items[0].getStringValue();
 
-        String[] minmax = rawValue.split(";");
+        final String[] minmax = rawValue.split(";");
 
-        return new LongRangeData(
-            name,
-            label,
-            Long.valueOf(minmax[0]),
-            Long.valueOf(minmax[1]));
+        return new LongRangeData(name, label, Long.valueOf(minmax[0]), Long.valueOf(minmax[1]));
     }
 
 }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/FLYSArtifactCreator.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/FLYSArtifactCreator.java	Fri Jul 13 11:56:22 2018 +0200
@@ -13,28 +13,26 @@
 
 import javax.xml.xpath.XPathConstants;
 
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
 import org.apache.log4j.Logger;
-
-import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
-
+import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.artifacts.httpclient.utils.ArtifactCreator;
-
 import org.dive4elements.river.client.shared.model.Artifact;
+import org.dive4elements.river.client.shared.model.BUNDUArtifact;
 import org.dive4elements.river.client.shared.model.CalculationMessage;
 import org.dive4elements.river.client.shared.model.ChartArtifact;
 import org.dive4elements.river.client.shared.model.DefaultArtifact;
 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.MINFOArtifact;
+import org.dive4elements.river.client.shared.model.MapArtifact;
+import org.dive4elements.river.client.shared.model.SINFOArtifact;
 import org.dive4elements.river.client.shared.model.StaticSQRelationArtifact;
+import org.dive4elements.river.client.shared.model.UINFOArtifact;
 import org.dive4elements.river.client.shared.model.WINFOArtifact;
-
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
 
 /**
  * An implementation of an {@link ArtifactCreator}. This class uses the document
@@ -45,28 +43,25 @@
  */
 public class FLYSArtifactCreator implements ArtifactCreator {
 
-    private static final Logger log =
-        Logger.getLogger(FLYSArtifactCreator.class);
+    private static final Logger log = Logger.getLogger(FLYSArtifactCreator.class);
 
-
-    /** The XPath to the artifact's uuid.*/
+    /** The XPath to the artifact's uuid. */
     public static final String XPATH_UUID = "/art:result/art:uuid/@art:value";
 
-    /** The XPath to the artifact's hash value.*/
+    /** The XPath to the artifact's hash value. */
     public static final String XPATH_HASH = "/art:result/art:hash/@art:value";
 
-    /** The XPath to the artifact's name value.*/
+    /** The XPath to the artifact's name value. */
     public static final String XPATH_NAME = "/art:result/art:name/@art:value";
 
-    /** The XPath to the value that determines if the artifact is processing in
-     * background.*/
-    public static final String XPATH_BACKGROUND_VALUE =
-        "/art:result/art:background-processing/@art:value";
+    /**
+     * The XPath to the value that determines if the artifact is processing in
+     * background.
+     */
+    public static final String XPATH_BACKGROUND_VALUE = "/art:result/art:background-processing/@art:value";
 
-    /** The XPath that points to the (if existing) background messages.*/
-    public static final String XPATH_BACKGROUND =
-        "/art:result/art:background-processing";
-
+    /** The XPath that points to the (if existing) background messages. */
+    public static final String XPATH_BACKGROUND = "/art:result/art:background-processing";
 
     /**
      * Creates a new instance of an {@link ArtifactCreator}.
@@ -74,54 +69,50 @@
     public FLYSArtifactCreator() {
     }
 
-
     /**
      * This concreate implementation returns an instance of {@link Artifact}
      * that is used in the FLYS GWT Client code.
      *
-     * @param doc A document that describes the artifact that has been created
-     * in the artifact server.
+     * @param doc
+     *            A document that describes the artifact that has been created
+     *            in the artifact server.
      *
      * @return an instance if {@link Artifact}.
      */
-    public Object create(Document doc) {
-        Artifact artifact = extractArtifact(doc);
-        artifact.setArtifactDescription(
-            ArtifactDescriptionFactory.createArtifactDescription(doc));
+    @Override
+    public Object create(final Document doc) {
+        final Artifact artifact = extractArtifact(doc);
+        artifact.setArtifactDescription(ArtifactDescriptionFactory.createArtifactDescription(doc));
 
         return artifact;
     }
 
-
     /**
      * This method extracts the UUID und HASH information of the returned
      * artifact document.
      *
-     * @param doc The result of the CREATE operation.
+     * @param doc
+     *            The result of the CREATE operation.
      *
      * @return an instance of an {@link Artifact}.
      */
-    protected Artifact extractArtifact(Document doc) {
+    protected Artifact extractArtifact(final Document doc) {
         log.debug("FLYSArtifactCreator - extractArtifact()");
 
-        String uuid = XMLUtils.xpathString(
-            doc, XPATH_UUID, ArtifactNamespaceContext.INSTANCE);
+        final String uuid = XMLUtils.xpathString(doc, XPATH_UUID, ArtifactNamespaceContext.INSTANCE);
 
-        String hash = XMLUtils.xpathString(
-            doc, XPATH_HASH, ArtifactNamespaceContext.INSTANCE);
+        final String hash = XMLUtils.xpathString(doc, XPATH_HASH, ArtifactNamespaceContext.INSTANCE);
 
-        String name = XMLUtils.xpathString(
-            doc, XPATH_NAME, ArtifactNamespaceContext.INSTANCE);
+        String name = XMLUtils.xpathString(doc, XPATH_NAME, ArtifactNamespaceContext.INSTANCE);
 
-        String backgroundStr = XMLUtils.xpathString(
-            doc, XPATH_BACKGROUND_VALUE, ArtifactNamespaceContext.INSTANCE);
+        final String backgroundStr = XMLUtils.xpathString(doc, XPATH_BACKGROUND_VALUE, ArtifactNamespaceContext.INSTANCE);
 
         boolean background = false;
         if (backgroundStr != null && backgroundStr.length() > 0) {
             background = Boolean.valueOf(backgroundStr);
         }
 
-        List<CalculationMessage> msg = parseBackgroundMessages(doc);
+        final List<CalculationMessage> msg = parseBackgroundMessages(doc);
 
         log.debug("NEW Artifact UUID: " + uuid);
         log.debug("NEW Artifact HASH: " + hash);
@@ -134,53 +125,70 @@
 
         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);
+        }
+
+        if (name.equals("uinfo")) {
+            log.debug("+++++ NEW UINFO ARTIFACT.");
+            return new UINFOArtifact(uuid, hash, background, msg);
+        }
+        if (name.equals("bundu")) {
+            log.debug("+++++ NEW BUNDU ARTIFACT.");
+            return new BUNDUArtifact(uuid, hash, background, msg);
+        }
         return new DefaultArtifact(uuid, hash, background, msg);
     }
 
+    public static List<CalculationMessage> parseBackgroundMessages(final Document d) {
+        final NodeList list = (NodeList) XMLUtils.xpath(d, XPATH_BACKGROUND, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);
 
-    public static List<CalculationMessage> parseBackgroundMessages(Document d) {
-        NodeList list = (NodeList) XMLUtils.xpath(
-            d, XPATH_BACKGROUND, XPathConstants.NODESET,
-            ArtifactNamespaceContext.INSTANCE);
-
-        int len = list != null ? list.getLength() : 0;
+        final int len = list != null ? list.getLength() : 0;
 
         log.debug("Found " + len + " background messages.");
 
-        List<CalculationMessage> res = new ArrayList<CalculationMessage>(len);
+        final List<CalculationMessage> res = new ArrayList<CalculationMessage>(len);
 
         for (int i = 0; i < len; i++) {
-            CalculationMessage msg = parseBackgroundMessage(
-                (Element) list.item(i));
+            final CalculationMessage msg = parseBackgroundMessage((Element) list.item(i));
 
             if (msg != null) {
                 res.add(msg);
@@ -190,25 +198,21 @@
         return res;
     }
 
+    public static CalculationMessage parseBackgroundMessage(final Element e) {
+        final String steps = e.getAttribute("art:steps");
+        final String currentStep = e.getAttribute("art:currentStep");
+        final String message = e.getTextContent();
 
-    public static CalculationMessage parseBackgroundMessage(Element e) {
-        String steps       = e.getAttribute("art:steps");
-        String currentStep = e.getAttribute("art:currentStep");
-        String message     = e.getTextContent();
-
-        int lenCurStep = currentStep != null ? currentStep.length() : 0;
-        int lenSteps   = steps       != null ? steps.length()       : 0;
-        int lenMessage = message     != null ? message.length()     : 0;
+        final int lenCurStep = currentStep != null ? currentStep.length() : 0;
+        final int lenSteps = steps != null ? steps.length() : 0;
+        final int lenMessage = message != null ? message.length() : 0;
 
         if (lenSteps > 0 && lenMessage > 0 && lenCurStep > 0) {
             try {
-                return new CalculationMessage(
-                    Integer.parseInt(steps),
-                    Integer.parseInt(currentStep),
-                    message);
+                return new CalculationMessage(Integer.parseInt(steps), Integer.parseInt(currentStep), message);
 
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 nfe.printStackTrace();
             }
         }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/ModuleServiceImpl.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/ModuleServiceImpl.java	Fri Jul 13 11:56:22 2018 +0200
@@ -42,29 +42,29 @@
         "error_no_module_found";
 
     @Override
-    public Module[] list(String locale) throws ServerException {
-        User user = this.getUser();
+    public Module[] list(final String locale) throws ServerException {
+        final User user = this.getUser();
 
         log.info("ModuleService.list");
 
-        String url = getServletContext().getInitParameter("server-url");
+        final String url = getServletContext().getInitParameter("server-url");
 
         // create dummy xml
-        Document doc = XMLUtils.newDocument();
+        final Document doc = XMLUtils.newDocument();
 
-        XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
+        final XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
             doc,
             ArtifactNamespaceContext.NAMESPACE_URI,
             ArtifactNamespaceContext.NAMESPACE_PREFIX);
 
-        Element dummy = ec.create("modules");
+        final Element dummy = ec.create("modules");
         doc.appendChild(dummy);
 
-        HttpClient client = new HttpClientImpl(url, locale);
+        final HttpClient client = new HttpClientImpl(url, locale);
         try {
-            Document result = client.callService(url, "modules", doc);
+            final Document result = client.callService(url, "modules", doc);
 
-            NodeList list = (NodeList) XMLUtils.xpath(
+            final NodeList list = (NodeList) XMLUtils.xpath(
                 result,
                 XPATH_MODULES,
                 XPathConstants.NODESET,
@@ -76,29 +76,27 @@
                 throw new ServerException(ERROR_NO_MODULES_FOUND);
             }
 
-            int num = list.getLength();
+            final int num = list.getLength();
 
-            List<Module> modules = new ArrayList<Module>(list.getLength());
+            final List<Module> modules = new ArrayList<Module>(list.getLength());
             for(int i =0; i < num; i++) {
-                Element em = (Element)list.item(i);
-                String name = em.getAttributeNS(
-                        ArtifactNamespaceContext.NAMESPACE_URI, "name");
-                String localname = em.getAttributeNS(
-                        ArtifactNamespaceContext.NAMESPACE_URI, "localname");
-                String strselected = em.getAttributeNS(
-                        ArtifactNamespaceContext.NAMESPACE_URI, "selected");
-                boolean selected = strselected == null ? false :
-                        strselected.equalsIgnoreCase("true");
-                NodeList rivers = em.getChildNodes();
-                List<String> riverUuids = new ArrayList<String>();
+                final Element em = (Element)list.item(i);
+                final String name = em.getAttributeNS(ArtifactNamespaceContext.NAMESPACE_URI, "name");
+                final String localname = em.getAttributeNS(ArtifactNamespaceContext.NAMESPACE_URI, "localname");
+                final String strselected = em.getAttributeNS(ArtifactNamespaceContext.NAMESPACE_URI, "selected");
+                boolean selected = Boolean.parseBoolean(strselected); 
+                final String group = em.getAttributeNS(ArtifactNamespaceContext.NAMESPACE_URI, "groupId");
+                final String groupLabel = em.getAttributeNS(ArtifactNamespaceContext.NAMESPACE_URI, "groupLabel");
+
+                final NodeList rivers = em.getChildNodes();
+                final List<String> riverUuids = new ArrayList<String>(rivers.getLength());
                 for (int j = 0; j < rivers.getLength(); j++) {
-                    Element re = (Element)rivers.item(j);
+                    final Element re = (Element)rivers.item(j);
                     riverUuids.add(re.getAttribute("uuid"));
                 }
                 log.debug("Found module " + name + " " + localname);
                 if (user == null || user.canUseFeature("module:" + name)) {
-                    modules.add(new DefaultModule(
-                            name, localname, selected, riverUuids));
+                    modules.add(new DefaultModule(name, localname, selected, group, groupLabel, riverUuids));
                 }
             }
             return modules.toArray(new Module[modules.size()]);
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/UserClient.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/UserClient.java	Fri Jul 13 11:56:22 2018 +0200
@@ -84,6 +84,8 @@
         account.setAttribute("name", user.getAccount());
 
         //TODO create roles
+        // FIXME: not creating the roles will write an broken xmldocument (only header) into the artifacts db 
+        // which in turn will result in an exception (which is handled)
         artuser.appendChild(account);
         action.appendChild(type);
         action.appendChild(artuser);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/AbstractFixBunduArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,143 @@
+/** 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.shared.model;
+
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class AbstractFixBunduArtifact extends DefaultArtifact {
+
+    /** The name of this artifact: 'fixanalysis'. */
+
+    protected FixFilter filter;
+
+    public AbstractFixBunduArtifact() {
+        this.filter = null;
+    }
+
+    public AbstractFixBunduArtifact(final String uuid, final String hash) {
+        super(uuid, hash);
+        this.filter = null;
+    }
+
+    public AbstractFixBunduArtifact(final String uuid, final String hash, final boolean inBackground, final List<CalculationMessage> messages) {
+        super(uuid, hash, inBackground, messages);
+    }
+
+    public FixFilter getFilter() {
+        return createFilter();
+    }
+
+    protected abstract String getEventstateId();
+
+    protected FixFilter createFilter() {
+        if (this.filter == null) {
+            this.filter = new FixFilter();
+        }
+        final DataList[] old = this.artifactDescription.getOldData();
+
+        final String river = this.artifactDescription.getDataValueAsString("river");
+        if (river != null) {
+            this.filter.setRiver(river);
+        }
+
+        final String from = this.artifactDescription.getDataValueAsString("ld_from");
+        if (from != null) {
+            try {
+                final double fkm = Double.parseDouble(from);
+                this.filter.setFromKm(fkm);
+            }
+            catch (final NumberFormatException nfe) {
+                GWT.log("Could not parse from km.");
+            }
+        }
+
+        final String to = this.artifactDescription.getDataValueAsString("ld_to");
+        if (to != null) {
+            try {
+                final double tkm = Double.parseDouble(to);
+                this.filter.setToKm(tkm);
+            }
+            catch (final NumberFormatException nfe) {
+                GWT.log("Could not parse to km");
+            }
+        }
+
+        final String start = this.artifactDescription.getDataValueAsString("start");
+        if (start != null) {
+            try {
+                final long s = Long.parseLong(start);
+                this.filter.setFromDate(s);
+            }
+            catch (final NumberFormatException nfe) {
+                GWT.log("Could not parse start date");
+            }
+        }
+
+        final String end = this.artifactDescription.getDataValueAsString("end");
+        if (end != null) {
+            try {
+                final long e = Long.parseLong(end);
+                this.filter.setToDate(e);
+            }
+            catch (final NumberFormatException nfe) {
+                GWT.log("Could not parse end date");
+            }
+        }
+
+        final String q1 = this.artifactDescription.getDataValueAsString("q1");
+        if (q1 != null) {
+            try {
+                final int q1i = Integer.parseInt(q1);
+                this.filter.setFromClass(q1i);
+            }
+            catch (final NumberFormatException nfe) {
+                GWT.log("Could not parse start class");
+            }
+        }
+
+        final String q2 = this.artifactDescription.getDataValueAsString("q2");
+        if (q2 != null) {
+            try {
+                final int q2i = Integer.parseInt(q2);
+                this.filter.setToClass(q2i);
+            }
+            catch (final NumberFormatException nfe) {
+                GWT.log("could not parse end class");
+            }
+        }
+
+        for (final DataList list : old) {
+            final List<Data> items = list.getAll();
+            final String state = list.getState();
+            if (state.equals(getEventstateId())) {
+                final Data de = getData(items, "events");
+                final IntegerArrayData iad = (IntegerArrayData) de;
+                this.filter.setEvents(iad.getValues());
+            }
+        }
+
+        return this.filter;
+    }
+
+    protected Data getData(final List<Data> data, final String name) {
+        for (final Data d : data) {
+            if (name.equals(d.getLabel())) {
+                return d;
+            }
+        }
+        return null;
+    }
+}
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/Artifact.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/Artifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,7 +11,6 @@
 import java.io.Serializable;
 import java.util.List;
 
-
 /**
  * This class represents an artifact for the client. It contains the necessary
  * information for the client and the communication with the artifact server.
@@ -27,7 +26,6 @@
      */
     public String getUuid();
 
-
     /**
      * Returns the hash of the artifact.
      *
@@ -35,7 +33,6 @@
      */
     public String getHash();
 
-
     /**
      * Returns the name of the artifact.
      * This happens to be the factory name, too.
@@ -51,7 +48,6 @@
      */
     public ArtifactDescription getArtifactDescription();
 
-
     /**
      * Returns true, if the Artifact is in Background mode.
      *
@@ -59,7 +55,6 @@
      */
     public boolean isInBackground();
 
-
     /**
      * Return a list of background messages.
      *
@@ -67,11 +62,11 @@
      */
     public List<CalculationMessage> getBackgroundMessages();
 
-
     /**
      * Sets a new ArtifactDescription.
      *
-     * @param artifactDescription The new artifact description.
+     * @param artifactDescription
+     *            The new artifact description.
      */
     public void setArtifactDescription(ArtifactDescription artifactDescription);
 }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/AttrList.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/AttrList.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,47 +8,64 @@
 
 package org.dive4elements.river.client.shared.model;
 
-import java.util.List;
+import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.List;
 
-import java.io.Serializable;
-
+// FIXME: who implements a thing like this?? this is a HashMap!!
 public class AttrList implements Serializable
 {
-    protected List<String> keyValues;
+    private static final long serialVersionUID = 1L;
+
+    private List<String> keyValues;
 
     public AttrList() {
         this(5);
     }
 
-    public AttrList(int size) {
-        keyValues = new ArrayList<String>(size*2);
+    public AttrList(final int size) {
+        this.keyValues = new ArrayList<String>(size*2);
     }
 
     public int size() {
-        return keyValues != null ? keyValues.size()/2 : null;
-    }
-
-    public String getKey(int index) {
-        return keyValues.get(index*2);
+        return this.keyValues.size() / 2;
     }
 
-    public String getValue(int index) {
-        return keyValues.get(index*2 + 1);
+    /**
+     * IMPORTANT: necessary for serialization
+     */
+    public void setKeyValues(final List<String> keyValues) {
+        this.keyValues = keyValues;
     }
 
-    public void add(String key, String value) {
-        keyValues.add(key);
-        keyValues.add(value);
+    public String getKey(final int index) {
+        return this.keyValues.get(index*2);
     }
 
-    public boolean hasAttribute(String key) {
-        for (int i = 0, N = keyValues.size(); i < N; i += 2) {
-            if (keyValues.get(i).equals(key)) {
+    public String getValue(final int index) {
+        return this.keyValues.get(index*2 + 1);
+    }
+
+    public String getValue(final String key) {
+        for (int i = 0, N = this.keyValues.size(); i < N; i += 2) {
+            if (this.keyValues.get(i).equals(key)) {
+                return this.keyValues.get(i + 1);
+            }
+        }
+        return null;
+    }
+
+    public void add(final String key, final String value) {
+        this.keyValues.add(key);
+        this.keyValues.add(value);
+    }
+
+    public boolean hasAttribute(final String key) {
+        for (int i = 0, N = this.keyValues.size(); i < N; i += 2) {
+            if (this.keyValues.get(i).equals(key)) {
                 return true;
             }
         }
         return false;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ 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/shared/model/BUNDUArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,45 @@
+/* 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 BUNDU implementation of an Artifact.
+ *
+ * @author Gernot Belger
+ */
+public class BUNDUArtifact extends AbstractFixBunduArtifact {
+
+    /** The name of this artifact: 'bundu'. */
+    private static final String NAME = "bundu";
+
+    public BUNDUArtifact() {
+        super();
+    }
+
+    public BUNDUArtifact(final String uuid, final String hash) {
+        super(uuid, hash);
+    }
+
+    public BUNDUArtifact(final String uuid, final String hash, final boolean background, final List<CalculationMessage> msg) {
+        super(uuid, hash, background, msg);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    protected String getEventstateId() {
+
+        return "state.bundu.eventselect"; // mit bundu.xml im server synchron halten :-(
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/DefaultModule.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/DefaultModule.java	Fri Jul 13 11:56:22 2018 +0200
@@ -14,26 +14,31 @@
 
     private String name;
     private String localname;
-    private boolean selected = false;
+    private ModuleGroup group;
+    private boolean selected;
     private List<String> rivers;
 
     public DefaultModule() {
     }
 
     public DefaultModule(
-        String name,
-        String localname,
-        boolean selected,
-        List<String> rivers) {
+        final String name,
+        final String localname,
+        final boolean selected,
+        final String groupId,
+        final String groupLabel,
+        final List<String> rivers) {
         this.name = name;
         this.localname = localname;
         this.selected = selected;
+        this.group = new ModuleGroup(groupId, groupLabel);
         this.rivers = rivers;
     }
 
     /**
      * Returns the name of the module
      */
+    @Override
     public String getName() {
         return this.name;
     }
@@ -41,6 +46,7 @@
     /**
      * Returns the localized name of the module
      */
+    @Override
     public String getLocalizedName() {
         return this.localname;
     }
@@ -48,15 +54,21 @@
     /**
      * Returns true if the module should be selected
      */
+    @Override
     public boolean isSelected() {
         return this.selected;
     }
+    
+    @Override
+    public ModuleGroup getGroup() {
+        return this.group;
+    }
 
     /**
      * @return the rivers
      */
+    @Override
     public List<String> getRivers() {
         return this.rivers;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 tw=80 :
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixAnalysisArtifact.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixAnalysisArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,150 +10,36 @@
 
 import java.util.List;
 
-import com.google.gwt.core.client.GWT;
-
-
 /**
  * The Fixanalysis implementation of an Artifact (client side).
  *
  * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public class FixAnalysisArtifact extends DefaultArtifact {
+public class FixAnalysisArtifact extends AbstractFixBunduArtifact {
 
-    /** The name of this artifact: 'fixanalysis'.*/
     public static final String NAME = "fixanalysis";
 
-    protected FixFilter filter;
-
-
     public FixAnalysisArtifact() {
-        this.filter = null;
+        super();
     }
 
-
-    public  FixAnalysisArtifact(String uuid, String hash) {
+    public FixAnalysisArtifact(final String uuid, final String hash) {
         super(uuid, hash);
-        this.filter = null;
     }
 
-
-    public FixAnalysisArtifact(
-        String                   uuid,
-        String                   hash,
-        boolean                  inBackground,
-        List<CalculationMessage> messages
-    ) {
-        super(uuid, hash, inBackground, messages);
+    public FixAnalysisArtifact(final String uuid, final String hash, final boolean background, final List<CalculationMessage> msg) {
+        super(uuid, hash, background, msg);
     }
 
-
+    @Override
     public String getName() {
         return NAME;
     }
 
-
-    public FixFilter getFilter () {
-        return createFilter();
+    @Override
+    protected String getEventstateId() {
+        return "state.fix.eventselect"; // synchron halten mit xml-file im Server
     }
 
-
-    protected FixFilter createFilter() {
-        if (this.filter == null) {
-            this.filter = new FixFilter();
-        }
-        DataList[] old = artifactDescription.getOldData();
-
-        String river = artifactDescription.getDataValueAsString("river");
-        if (river != null) {
-            this.filter.setRiver(river);
-        }
-
-        String from = artifactDescription.getDataValueAsString("ld_from");
-        if (from != null) {
-            try {
-                double fkm = Double.parseDouble(from);
-                this.filter.setFromKm(fkm);
-            }
-            catch(NumberFormatException nfe) {
-                GWT.log("Could not parse from km.");
-            }
-        }
-
-        String to = artifactDescription.getDataValueAsString("ld_to");
-        if (to != null) {
-            try {
-                double tkm = Double.parseDouble(to);
-                this.filter.setToKm(tkm);
-            }
-            catch(NumberFormatException nfe) {
-                GWT.log("Could not parse to km");
-            }
-        }
-
-        String start = artifactDescription.getDataValueAsString("start");
-        if (start != null) {
-            try {
-                long s = Long.parseLong(start);
-                this.filter.setFromDate(s);
-            }
-            catch(NumberFormatException nfe) {
-                GWT.log("Could not parse start date");
-            }
-        }
-
-        String end = artifactDescription.getDataValueAsString("end");
-        if (end != null) {
-            try {
-                long e = Long.parseLong(end);
-                this.filter.setToDate(e);
-            }
-            catch(NumberFormatException nfe) {
-                GWT.log("Could not parse end date");
-            }
-        }
-
-        String q1 = artifactDescription.getDataValueAsString("q1");
-        if (q1 != null) {
-            try {
-                int q1i = Integer.parseInt(q1);
-                this.filter.setFromClass(q1i);
-            }
-            catch(NumberFormatException nfe) {
-                GWT.log("Could not parse start class");
-            }
-        }
-
-        String q2 = artifactDescription.getDataValueAsString("q2");
-        if (q2 != null) {
-            try {
-                int q2i = Integer.parseInt(q2);
-                this.filter.setToClass(q2i);
-            }
-            catch(NumberFormatException nfe) {
-                GWT.log("could not parse end class");
-            }
-        }
-
-        for (DataList list: old) {
-            List<Data> items = list.getAll();
-            String state = list.getState();
-            if(state.equals("state.fix.eventselect")) {
-                Data de = getData(items, "events");
-                IntegerArrayData iad = (IntegerArrayData) de;
-                this.filter.setEvents(iad.getValues());
-            }
-        }
-
-        return this.filter;
-    }
-
-    protected Data getData(List<Data> data, String name) {
-        for (Data d: data) {
-            if (name.equals(d.getLabel())) {
-                return d;
-            }
-        }
-        return null;
-    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixFilter.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixFilter.java	Fri Jul 13 11:56:22 2018 +0200
@@ -11,7 +11,7 @@
 import java.io.Serializable;
 
 /** Probably something like *Access, but from client side. */
-public class FixFilter implements Serializable{
+public class FixFilter implements Serializable {
 
     protected String river;
     protected double fromKm;
@@ -37,41 +37,41 @@
         this.events = new int[0];
     }
 
-    public void setRiver(String river) {
+    public void setRiver(final String river) {
         this.river = river;
     }
 
-    public void setFromKm(double from) {
+    public void setFromKm(final double from) {
         this.fromKm = from;
     }
 
-    public void setToKm(double to) {
+    public void setToKm(final double to) {
         this.toKm = to;
     }
 
-    public void setCurrentKm(double km) {
+    public void setCurrentKm(final double km) {
         this.currentKm = km;
     }
 
-    public void setFromClass(int from) {
+    public void setFromClass(final int from) {
         this.fromClass = from;
     }
 
-    public void setToClass(int to) {
+    public void setToClass(final int to) {
         this.toClass = to;
     }
 
-    public void setFromDate(long from) {
+    public void setFromDate(final long from) {
         this.hasDate = true;
         this.fromDate = from;
     }
 
-    public void setToDate(long to) {
+    public void setToDate(final long to) {
         this.hasDate = true;
         this.toDate = to;
     }
 
-    public void setEvents(int[] ev) {
+    public void setEvents(final int[] ev) {
         this.events = ev;
     }
 
@@ -79,14 +79,22 @@
         return this.river;
     }
 
-    public double getFromKm() {
-        return this.fromKm;
+    public double getLowerKm() {
+        return Math.min(this.fromKm, this.toKm);
     }
 
-    public double getToKm() {
-        return this.toKm;
+    public double getUpperKm() {
+        return Math.max(this.fromKm, this.toKm);
     }
 
+    // public double getFromKm() {
+    // return this.fromKm;
+    // }
+    //
+    // public double getToKm() {
+    // return this.toKm;
+    // }
+
     public double getCurrentKm() {
         return this.currentKm;
     }
@@ -112,7 +120,7 @@
     }
 
     public boolean hasDate() {
-        return fromDate != Long.MIN_VALUE && toDate != Long.MIN_VALUE;
+        return this.fromDate != Long.MIN_VALUE && this.toDate != Long.MIN_VALUE;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixingsOverviewInfo.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixingsOverviewInfo.java	Fri Jul 13 11:56:22 2018 +0200
@@ -9,9 +9,8 @@
 package org.dive4elements.river.client.shared.model;
 
 import java.io.Serializable;
-
+import java.util.ArrayList;
 import java.util.List;
-import java.util.ArrayList;
 
 public class FixingsOverviewInfo implements Serializable {
 
@@ -22,22 +21,18 @@
     protected int rid;
     protected String html;
 
-    protected FixingsOverviewInfo() {}
+    private FixingsOverviewInfo() {
+    }
 
-    public FixingsOverviewInfo(
-        int rid,
-        String river,
-        double from,
-        double to,
-        List<FixEvent> events,
-        String html
-    ) {
+    public FixingsOverviewInfo(final int rid, final String river, final double from, final double to, final List<FixEvent> events, final String html) {
         this.rid = rid;
         this.river = river;
         this.from = from;
         this.to = to;
         this.events = new ArrayList<FixEvent>(events);
+        System.out.println(html);
         this.html = html;
+
     }
 
     public int getRId() {
@@ -48,20 +43,29 @@
         return this.river;
     }
 
-    public double getFrom() {
-        return this.from;
+    public double getLowerKm() {
+        return Math.min(this.from, this.to);
     }
 
-    public double getTo() {
-        return this.to;
+    public double getUpperKm() {
+        return Math.max(this.from, this.to);
     }
 
+    // public double getFrom() {
+    // return this.from < this.to ? this.from : this.to; // TODO: prüfung wieder rausnehmen, hat glaube ich keinen
+    // sinnvollen effekt.
+    // }
+    //
+    // public double getTo() {
+    // return this.to > this.from ? this.to : this.from;
+    // }
+
     public List<FixEvent> getEvents() {
         return this.events;
     }
 
-    public FixEvent getEventByCId(String cid) {
-        for (FixEvent event: events) {
+    public FixEvent getEventByCId(final String cid) {
+        for (final FixEvent event : this.events) {
             if (event.getCId().equals(cid)) {
                 return event;
             }
@@ -73,21 +77,16 @@
         return this.html;
     }
 
-
     public static class FixEvent implements Serializable {
         protected String cid;
         protected String date;
         protected String description;
         protected List<Sector> sectors;
 
-        protected FixEvent () {}
+        protected FixEvent() {
+        }
 
-        public FixEvent(
-            String cid,
-            String date,
-            String description,
-            List<Sector> sectors
-        ) {
+        public FixEvent(final String cid, final String date, final String description, final List<Sector> sectors) {
             this.cid = cid;
             this.date = date;
             this.description = description;
@@ -116,13 +115,10 @@
         protected double from;
         protected double to;
 
-        protected Sector () {}
+        protected Sector() {
+        }
 
-        public Sector(
-            int cls,
-            double from,
-            double to
-        ) {
+        public Sector(final int cls, final double from, final double to) {
             this.cls = cls;
             this.from = from;
             this.to = to;
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/Module.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/Module.java	Fri Jul 13 11:56:22 2018 +0200
@@ -18,6 +18,8 @@
     String getLocalizedName();
 
     boolean isSelected();
+    
+    ModuleGroup getGroup();
 
     List<String> getRivers();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ModuleGroup.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,65 @@
+/** 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.shared.model;
+
+import java.io.Serializable;
+
+/**
+ * A module group marks modules to belong to a common group. Modules of the same group are put together in the user-interface.
+ * 
+ * @author Gernot Belger
+ */
+public class ModuleGroup implements Serializable {
+    
+    private static final long serialVersionUID = 1L;
+
+    private String id;
+    private String label;
+
+    public ModuleGroup() {
+        this.id = null;
+        this.label = null;
+    }
+    
+    public ModuleGroup(final String id, final String label) {
+        this.id = id;
+        this.label = label;
+    }
+
+    @Override
+    public String toString() {
+        return label;
+    }
+
+    @Override
+    public int hashCode() {
+        return id == null ? 0 : id.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+
+        if (obj == null)
+            return false;
+        if (obj == this)
+            return true;
+
+        if (obj.getClass() != getClass()) {
+            return false;
+        }
+
+        final ModuleGroup rhs = (ModuleGroup) obj;
+        return (id == rhs.id) || (id != null && id.equals(rhs.id));
+    }
+
+    public boolean showGroupFrame() {
+        return label != null && !label.trim().isEmpty();
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/MultiAttributeData.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/MultiAttributeData.java	Fri Jul 13 11:56:22 2018 +0200
@@ -10,10 +10,9 @@
 
 import java.util.Map;
 
+public class MultiAttributeData implements Data {
 
-public class MultiAttributeData
-implements Data
-{
+    private static final long serialVersionUID = 1L;
 
     public static final String TYPE = "multiattribute";
 
@@ -24,24 +23,18 @@
 
     public DataItem[] opts;
 
-
     public MultiAttributeData() {
     }
 
-
-    public MultiAttributeData(
-        String                           label,
-        String                           desc,
-        DataItem[]                       opts,
-        Map<String, Map<String, String>> meta
-    ) {
-        this.label       = label;
+    public MultiAttributeData(final String label, final String desc, final DataItem[] opts, final Map<String, Map<String, String>> meta) {
+        this.label = label;
         this.description = desc;
-        this.opts        = opts;
+        this.opts = opts;
+        this.meta = meta;
     }
 
     public Map<String, Map<String, String>> getMeta() {
-        return meta;
+        return this.meta;
     }
 
     /**
@@ -49,62 +42,63 @@
      *
      * @return the label.
      */
+    @Override
     public String getLabel() {
-        return label;
+        return this.label;
     }
 
-
     /**
      * Returns the description of the item.
      *
      * @return the description.
      */
+    @Override
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-
     /**
      * Returns the type of the item.
      *
      * @return the type.
      */
+    @Override
     public String getType() {
         return TYPE;
     }
 
-
     /**
      * Returns the data items which represent the allowed options for this Data.
      *
      * @return the allowed options as DataItem array.
      */
+    @Override
     public DataItem[] getItems() {
-        return opts;
+        return this.opts;
     }
 
-
     /**
      * @return always null.
      */
+    @Override
     public DataItem getDefault() {
         return null;
     }
 
-
     /**
      * Returns the values as colon separated string.
      *
      * @return colon separated string.
      */
+    @Override
     public String getStringValue() {
         String data = "";
         boolean first = true;
-        for (int i = 0; i < opts.length; i++) {
+        for (final DataItem opt : this.opts) {
             if (!first) {
                 data += ";";
             }
-            data += opts[i].getStringValue();
+            data += opt.getStringValue();
             first = false;
         }
         return data;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SINFOArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SalixZone.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,177 @@
+/** 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.shared.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SalixZone implements Comparable<SalixZone> {
+
+    // IMMER ABGLEICHEN Server Client SalixZone.java
+    private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR";
+    private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR";
+    private final int dwsplValue;
+    private final double fromKm;
+    private final double toKm;
+
+    private final static double DELTA = 0.0001;
+
+    public static List<SalixZone> parse(final String zonesRaw) {
+        final List<SalixZone> resultList = new ArrayList<SalixZone>();
+
+        final List<String[]> results = new ArrayList<String[]>();
+        if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) {
+            final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR);
+            for (final String row : rows) {
+                if (row.contains(TABLE_CELL_SEPARATOR)) {
+                    final String[] result = row.split(TABLE_CELL_SEPARATOR);
+                    results.add(result);
+                }
+            }
+        }
+        for (final String[] zone : results) {
+            final SalixZone helper = new SalixZone(Integer.valueOf(zone[0]), Double.valueOf(zone[1]), Double.valueOf(zone[2]));
+            resultList.add(helper);
+        }
+        return resultList;
+    }
+
+    public static SalixZone createFromTableEntry(final String dwspl, final String from, final String to) {
+        return new SalixZone(Integer.valueOf(dwspl), Double.valueOf(from), Double.valueOf(to)); // Error-Handling?
+    }
+
+    private SalixZone(final int dwsplValue, final double fromKm, final double toKm) {
+        this.dwsplValue = dwsplValue;
+        this.fromKm = fromKm;
+        this.toKm = toKm;
+    }
+
+    public Double getToKm() {
+        return this.toKm;
+    }
+
+    public int getDwsplValue() {
+        return this.dwsplValue;
+    }
+
+    public Double getFromKm() {
+        return this.fromKm;
+    }
+
+    public static final String parseListToDataString(final List<SalixZone> list) {
+
+        java.util.Collections.sort(list);
+        final StringBuilder builder = new StringBuilder();
+        for (final SalixZone zone : list) {
+            builder.append(zone.getDwsplValue());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getFromKm());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getToKm());
+            builder.append(TABLE_ROW_SEPARATOR);
+        }
+        return builder.toString();
+    }
+
+    public static final boolean zonesAreOverlapping(final List<SalixZone> list) {
+        for (final SalixZone zone : list) {
+            for (final SalixZone zoneOther : list) {
+                if (zone != zoneOther) {
+                    final boolean overlaps = zone.overlaps(zoneOther);
+                    if (overlaps) {
+                        return overlaps; // cancel. only one zone has to overlap
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public static final boolean hasGaps(final List<SalixZone> list, final double lower, final double upper) {
+
+        if (((upper - lower) > DELTA) && list.size() == 0)
+            return true;
+
+        final TreeSet<SalixZone> treeList = new TreeSet<SalixZone>();
+        treeList.addAll(list);
+        double lowerCompare = lower + DELTA;
+        for (final SalixZone zone : treeList) {
+            if ((zone.getUpperFromTo() - zone.getLowerFromTo()) > DELTA) {
+                if (zone.getLowerFromTo() > lowerCompare) {
+                    return true;
+                }
+                lowerCompare = zone.getUpperFromTo() + DELTA;
+            }
+        }
+        if ((lowerCompare + DELTA) < upper)
+            return true; // am Ende nicht geschlossen
+
+        return false;
+    }
+
+    public Double getLowerFromTo() {
+        return this.fromKm < this.toKm ? this.fromKm : this.toKm; // Math. is forbidden :-(
+    }
+
+    public Double getUpperFromTo() {
+        return this.fromKm > this.toKm ? this.fromKm : this.toKm;// Math. is forbidden :-(
+    }
+
+    private boolean overlaps(final SalixZone otherZone) {
+        final double otherLower = otherZone.getLowerFromTo();
+        final double otherUpper = otherZone.getUpperFromTo();
+
+        final double upper = getUpperFromTo();
+        final double lower = getLowerFromTo();
+        final double otherSchwerpunkt = (otherLower + otherUpper) / 2;
+        if ((otherUpper < upper && otherUpper > lower)) {
+            return true;
+        } else if (otherLower > lower && otherLower < upper) {
+            return true;
+        } else if (otherSchwerpunkt > (lower - DELTA) && otherSchwerpunkt < (upper + DELTA)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int compareTo(final SalixZone o) {
+        final int basicCompare = this.getLowerFromTo().compareTo(o.getLowerFromTo());
+        if (basicCompare == 0) {
+            return 1; // necessary for the treeSet!
+        }
+        return basicCompare;
+    }
+
+    public static boolean isValidAnschlussRange(final double fromTest, final double toTest, final List<SalixZone> list, final double minKm) {
+        final SalixZone zone = new SalixZone(0, fromTest, toTest);
+        final double lower = zone.getLowerFromTo();
+        final double anschluss = getAnschluss(list, minKm);
+        final double differenceAbs = (lower - anschluss) > 0 ? (lower - anschluss) : (anschluss - lower); // no Math.abs allowed :-(
+        if (differenceAbs > DELTA) {
+            return false;
+        }
+        return true;
+    }
+
+    private static double getAnschluss(final List<SalixZone> list, final double minKm) {
+        if (list.size() > 0) {
+            return list.get(list.size() - 1).getUpperFromTo();
+        }
+        return minKm;
+    }
+}
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ToLoad.java	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ToLoad.java	Fri Jul 13 11:56:22 2018 +0200
@@ -8,52 +8,46 @@
 
 package org.dive4elements.river.client.shared.model;
 
+import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.HashMap;
-
-import java.io.Serializable;
 
 import com.google.gwt.core.client.GWT;
 
 public class ToLoad implements Serializable
 {
-
-    /** Two strings. */
-    public static class StringTriple {
+    private static class StringTriple {
         public String first;
         public String second;
         public String third;
-        public StringTriple(String first, String second, String third) {
+        public StringTriple(final String first, final String second, final String third) {
             this.first = first;
             this.second = second;
             this.third = third;
         }
         @Override
         public int hashCode() {
-            return first.hashCode() + second.hashCode() + third.hashCode();
+            return this.first.hashCode() + this.second.hashCode() + this.third.hashCode();
         }
         @Override
-        public boolean equals(Object o) {
+        public boolean equals(final Object o) {
             if (!(o instanceof StringTriple)) {
                 return false;
             }
-            StringTriple other = (StringTriple) o;
-            return second.equals(other.second)
-                && first.equals(other.first)
-                && third.equals(other.third);
+            final StringTriple other = (StringTriple) o;
+            return this.second.equals(other.second)
+                    && this.first.equals(other.first)
+                    && this.third.equals(other.third);
         }
     }
-    public static final String SYNTHETIC_KEY = "key-";
-
-    protected Map<String, Map<StringTriple, ArtifactFilter>> artifacts;
 
-    public ToLoad() {
-        artifacts = new HashMap<String, Map<StringTriple, ArtifactFilter>>();
-    }
+    private static final String SYNTHETIC_KEY = "key-";
 
-    public static final String uniqueKey(Map<?, ?> map) {
+    private final Map<String, Map<StringTriple, ArtifactFilter>> artifacts = new HashMap<String, Map<StringTriple, ArtifactFilter>>();
+
+    public static final String uniqueKey(final Map<?, ?> map) {
         int idx = map.size();
 
         String key = SYNTHETIC_KEY + idx;
@@ -64,39 +58,39 @@
     }
 
     public void add(
-         String artifactName,
-         String factory,
-         String out,
-         String name,
-         String ids,
-         String displayName
-     ) {
+            final String artifactName,
+            final String factory,
+            final String out,
+            final String name,
+            final String ids,
+            final String displayName
+            ) {
         add(artifactName, factory, out, name, ids, displayName, null);
-     }
+    }
 
     public void add(
-        String artifactName,
-        String factory,
-        String out,
-        String name,
-        String ids,
-        String displayName,
-        String targetOut
-    ) {
+            String artifactName,
+            final String factory,
+            final String out,
+            final String name,
+            final String ids,
+            final String displayName,
+            final String targetOut
+            ) {
         GWT.log("Adding artifact: " + artifactName + " Factory: " + factory +
                 " Out: " + out + " Name: " + name + " Ids: " + ids +
                 " Display Name: " + displayName + " Target Out: " + targetOut);
 
         if (artifactName == null) {
-            artifactName = uniqueKey(artifacts);
+            artifactName = uniqueKey(this.artifacts);
         }
 
-        Map<StringTriple, ArtifactFilter> artifact = artifacts.get(
-            artifactName);
+        Map<StringTriple, ArtifactFilter> artifact = this.artifacts.get(
+                artifactName);
 
         if (artifact == null) {
             artifact = new HashMap<StringTriple, ArtifactFilter>();
-            artifacts.put(artifactName, artifact);
+            this.artifacts.put(artifactName, artifact);
         }
 
         ArtifactFilter filter = artifact.get(factory);
@@ -110,28 +104,28 @@
     }
 
     public boolean isEmpty() {
-        return artifacts.isEmpty();
+        return this.artifacts.isEmpty();
     }
 
     public List<Recommendation> toRecommendations() {
-        List<Recommendation> recommendations = new ArrayList<Recommendation>();
+        final List<Recommendation> recommendations = new ArrayList<Recommendation>();
 
-        for (Map.Entry<String, Map<StringTriple, ArtifactFilter>> all:
-            artifacts.entrySet()
-        ) {
+        for (final Map.Entry<String, Map<StringTriple, ArtifactFilter>> all:
+            this.artifacts.entrySet()
+                ) {
             String masterArtifact = all.getKey();
 
             if (masterArtifact.startsWith(SYNTHETIC_KEY)) { // system data
                 masterArtifact = null;
             }
 
-            for (Map.Entry<StringTriple, ArtifactFilter> entry:
+            for (final Map.Entry<StringTriple, ArtifactFilter> entry:
                 all.getValue().entrySet()
-            ) {
-                StringTriple triple = entry.getKey();
-                String factory = triple.first;
-                String targetOut = triple.third;
-                ArtifactFilter artifactFilter = entry.getValue();
+                    ) {
+                final StringTriple triple = entry.getKey();
+                final String factory = triple.first;
+                final String targetOut = triple.third;
+                final ArtifactFilter artifactFilter = entry.getValue();
 
                 String                ids;
                 Recommendation.Filter filter;
@@ -145,8 +139,8 @@
                     filter = artifactFilter.toFilter();
                 }
 
-                Recommendation recommendation = new Recommendation(
-                    factory, ids, masterArtifact, filter, targetOut);
+                final Recommendation recommendation = new Recommendation(
+                        factory, ids, masterArtifact, filter, targetOut);
                 recommendation.setDisplayName(triple.second);
 
                 recommendations.add(recommendation);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/UINFOArtifact.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,42 @@
+/* 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 UINFO implementation of an Artifact.
+ *
+ * @author Gernot Belger
+ */
+public class UINFOArtifact extends DefaultArtifact {
+
+    /** The name of this artifact: 'uinfo'.*/
+    private static final String NAME = "uinfo";
+
+    /** Necessary for serialization */
+    public UINFOArtifact() {
+    }
+
+    public UINFOArtifact(
+        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 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/VegetationZone.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,113 @@
+/** 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.shared.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class VegetationZone implements Comparable<VegetationZone> {
+
+    // IMMER ABGLEICHEN MIT VegetationZone.class IM SERVER
+    private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR";
+    private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR";
+    private final String zoneName;
+    private final int min_day_overflow;
+    private final int max_day_overflow;
+
+    public static List<VegetationZone> parse(final String zonesRaw) {
+        final List<VegetationZone> resultList = new ArrayList<VegetationZone>();
+
+        final List<String[]> results = new ArrayList<String[]>();
+        if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) {
+            final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR);
+            for (final String row : rows) {
+                if (row.contains(TABLE_CELL_SEPARATOR)) {
+                    final String[] result = row.split(TABLE_CELL_SEPARATOR);
+                    results.add(result);
+                }
+            }
+        }
+        for (final String[] zone : results) {
+
+            final VegetationZone helper = new VegetationZone(zone[0], Integer.valueOf(zone[1]), Integer.valueOf(zone[2]));
+            resultList.add(helper);
+        }
+
+        return resultList;
+    }
+
+    public static VegetationZone createFromTableEntry(final String zone, final String min_day_overflow, final String max_day_overflow) {
+        return new VegetationZone(zone, Integer.valueOf(min_day_overflow), Integer.valueOf(max_day_overflow)); // Error-Handling?
+    }
+
+    private VegetationZone(final String zone, final Integer min_day_overflow, final Integer max_day_overflow) {
+        this.zoneName = zone;
+        this.min_day_overflow = min_day_overflow;
+        this.max_day_overflow = max_day_overflow;
+    }
+
+    public int getMax_day_overflow() {
+        return this.max_day_overflow;
+    }
+
+    public String getZoneName() {
+        return this.zoneName;
+    }
+
+    public int getMin_day_overflow() {
+        return this.min_day_overflow;
+    }
+
+    public static final List<VegetationZone> getStandardList() {
+
+        final List<VegetationZone> list = new ArrayList<VegetationZone>();
+        list.add(new VegetationZone("Zonaler Wald", 0, 5));
+        list.add(new VegetationZone("Hartholzaue, trocken", 5, 40));
+        list.add(new VegetationZone("Hartholzaue, feucht", 40, 80));
+        list.add(new VegetationZone("Silberweidenwald", 80, 140));
+        list.add(new VegetationZone("Weidengebüsch", 140, 200));
+        list.add(new VegetationZone("Uferröhricht", 200, 260));
+        list.add(new VegetationZone("Uferpioniere", 260, 320));
+        list.add(new VegetationZone("Vegetationslos", 320, 365));
+        list.add(new VegetationZone("Wasserfläche", 365, 365));
+
+        return list;
+    }
+
+    public static final String parseListToDataString(final List<VegetationZone> list) {
+
+        java.util.Collections.sort(list);
+        final StringBuilder builder = new StringBuilder();
+        for (final VegetationZone zone : list) {
+            builder.append(zone.getZoneName());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getMin_day_overflow());
+            builder.append(TABLE_CELL_SEPARATOR);
+            builder.append(zone.getMax_day_overflow());
+            builder.append(TABLE_ROW_SEPARATOR);
+        }
+        return builder.toString();
+
+    }
+
+    @Override
+    public int compareTo(final VegetationZone o) {
+        final int basicCompare = Integer.valueOf(this.getMin_day_overflow()).compareTo(o.getMin_day_overflow());
+        if (basicCompare == 0)
+            return Integer.valueOf(this.getMax_day_overflow()).compareTo(o.getMax_day_overflow()); // wenn min==min && max==max, alphabetisch sortieren?
+        return basicCompare;
+    }
+
+}
--- a/gwt-client/src/main/webapp/WEB-INF/features.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/webapp/WEB-INF/features.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -1,16 +1,19 @@
 <?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:winfo</ftr:feature>
-        <ftr:feature>module:minfo</ftr:feature>
-        <ftr:feature>module:new_map</ftr:feature>
-        <ftr:feature>module:new_chart</ftr:feature>
-        <ftr:feature>module:fixanalysis</ftr:feature>
-        <ftr:feature>river:Beispielfluss</ftr:feature>
-    </ftr:role>
-    <ftr:role name="d4e_demo_extern">
-        <ftr:feature>module:winfo</ftr:feature>
-        <ftr:feature>module:minfo</ftr:feature>
-        <ftr:feature>river:Beispielfluss</ftr:feature>
-    </ftr:role>
+  <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:uinfo</ftr:feature>
+    <ftr:feature>module:bundu</ftr:feature>
+    <ftr:feature>module:new_map</ftr:feature>
+    <ftr:feature>module:new_chart</ftr:feature>
+    <ftr:feature>module:fixanalysis</ftr:feature>
+    <ftr:feature>river:Beispielfluss</ftr:feature> 
+  </ftr:role>
+  <ftr:role name="d4e_demo_extern">
+    <ftr:feature>module:winfo</ftr:feature>
+    <ftr:feature>module:minfo</ftr:feature>
+    <ftr:feature>river:Beispielfluss</ftr:feature>
+  </ftr:role>
 </ftr:features>
--- a/gwt-client/src/main/webapp/WEB-INF/log4j.properties	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/webapp/WEB-INF/log4j.properties	Fri Jul 13 11:56:22 2018 +0200
@@ -1,18 +1,15 @@
 log4j.rootLogger=DEBUG, FLYS
 
 ########## INTERNAL PACKAGES
-log4j.category.de.intevation.flys.client.server=DEBUG
-
+log4j.category.org.dive4elements.river.client.server=DEBUG
 
 ########## EXTERNAL PACKAGES
 log4j.category.org.apache.http=ERROR
-log4j.category.de.intevation.artifacts.httpclient=WARN
+log4j.category.org.dive4elements.artifacts.httpclient=WARN
 
 ########## APPENDER SETTINGS
 log4j.appender.FLYS.layout=org.apache.log4j.PatternLayout
 log4j.appender.FLYS.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
 
-log4j.appender.FLYS=org.apache.log4j.RollingFileAppender
-log4j.appender.FLYS.File=/var/log/d4e-river/d4e-client.log
-log4j.appender.FLYS.MaxFileSize=5000KB
-log4j.appender.FLYS.MaxBackupIndex=3
+log4j.appender.FLYS=org.apache.log4j.ConsoleAppender
+log4j.appender.FLYS.Target = System.out
--- a/gwt-client/src/main/webapp/WEB-INF/stylesheets/fixoverview2html.xsl	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/webapp/WEB-INF/stylesheets/fixoverview2html.xsl	Fri Jul 13 11:56:22 2018 +0200
@@ -357,14 +357,14 @@
   </xsl:template>
 
   <xsl:template match="events">
-    <table width="97%" border="1" cellspacing="0" cellpadding="0"
+    <table width="100%" border="1" cellspacing="0" cellpadding="0"
            style="font-size: 10pt;font-family:Arial;Verdana,sans-serif">
       <colgroup>
         <xsl:if test="$render-checkboxes">
             <col width="20px"/>
         </xsl:if>
         <col width="*"/>
-        <col width="75px"/>
+        <col width="95px"/>
       </colgroup>
       <tr>
         <xsl:if test="$render-checkboxes">
@@ -373,8 +373,20 @@
         <th><xsl:apply-templates mode="gauges" select="/fixings/gauges"/></th>
         <th><xsl:value-of select="$i18n-event"/></th>
       </tr>
-      <xsl:apply-templates/>
-    </table>
+    </table>  
+
+    <div class="lowerDiv" style="height: 65%;  overflow-y: scroll !important;">  
+      <table width="100%" border="1" cellspacing="0" cellpadding="0" style="font-size: 10pt;font-family:Arial;Verdana,sans-serif">
+        <colgroup>
+          <xsl:if test="$render-checkboxes">
+              <col width="20px"/>
+          </xsl:if>
+          <col width="*"/>
+          <col width="75px"/>
+        </colgroup>      
+        <xsl:apply-templates/>
+      </table>
+    </div>
   </xsl:template>
 
   <xsl:template match="/">
--- a/gwt-client/src/main/webapp/WEB-INF/web.xml	Fri Feb 09 15:39:49 2018 +0100
+++ b/gwt-client/src/main/webapp/WEB-INF/web.xml	Fri Jul 13 11:56:22 2018 +0200
@@ -69,6 +69,30 @@
         <param-value>/WEB-INF/log4j.properties</param-value>
     </context-param>
 
+  <filter>
+    <filter-name>GGInAFilter</filter-name>
+    <filter-class>org.dive4elements.river.client.server.filter.GGInAFilter</filter-class>
+    <init-param>
+        <param-name>deactivate</param-name>
+        <param-value>false</param-value>
+    </init-param>
+  </filter>
+
+  <filter>
+    <filter-name>NoCacheFilter</filter-name>
+    <filter-class>org.dive4elements.river.client.server.filter.NoCacheFilter</filter-class>
+  </filter>
+
+  <filter-mapping>
+    <filter-name>GGInAFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>NoCacheFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
     <listener>
         <listener-class>org.dive4elements.river.client.server.BaseServletContextListener</listener-class>
     </listener>
@@ -80,262 +104,132 @@
     <servlet-class>org.dive4elements.river.client.server.UserServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>user</servlet-name>
-    <url-pattern>/flys/user</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>server-info</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ServerInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>server-info</servlet-name>
-    <url-pattern>/flys/server-info</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>artifact</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ArtifactServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>artifact</servlet-name>
-    <url-pattern>/flys/artifact</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>getartifact</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.GetArtifactServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>getartifact</servlet-name>
-    <url-pattern>/flys/getartifact</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>cross-section-km</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.CrossSectionKMServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>cross-section-km</servlet-name>
-    <url-pattern>/flys/cross-section-km</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>create-collection</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.CreateCollectionServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>create-collection</servlet-name>
-    <url-pattern>/flys/create-collection</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>rivers</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.RiverServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>rivers</servlet-name>
-    <url-pattern>/flys/rivers</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>riverinfo</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.RiverInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>riverinfo</servlet-name>
-    <url-pattern>/flys/riverinfo</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>forward</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.StepForwardServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>forward</servlet-name>
-    <url-pattern>/flys/forward</url-pattern>
-  </servlet-mapping>
-
-  <servlet>
-    <servlet-name>feed</servlet-name>
-    <servlet-class>org.dive4elements.river.client.server.FeedServiceImpl</servlet-class>
-  </servlet>
-
-  <servlet-mapping>
-    <servlet-name>feed</servlet-name>
-    <url-pattern>/flys/feed</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>fixings-overview</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.FixingsOverviewServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>fixings-overview</servlet-name>
-    <url-pattern>/flys/fixings-overview</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>advance</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.AdvanceServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>advance</servlet-name>
-    <url-pattern>/flys/advance</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>add-artifact</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.AddArtifactServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>add-artifact</servlet-name>
-    <url-pattern>/flys/add-artifact</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>load-artifact</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.LoadArtifactServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>load-artifact</servlet-name>
-    <url-pattern>/flys/load-artifact</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>describe-collection</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.DescribeCollectionServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>describe-collection</servlet-name>
-    <url-pattern>/flys/describe-collection</url-pattern>
-  </servlet-mapping>
-
-    <servlet>
+  <servlet>
     <servlet-name>user-collections</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.UserCollectionsServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>user-collections</servlet-name>
-    <url-pattern>/flys/user-collections</url-pattern>
-  </servlet-mapping>
+  <servlet>
+    <servlet-name>feed</servlet-name>
+    <servlet-class>org.dive4elements.river.client.server.FeedServiceImpl</servlet-class>
+  </servlet>
 
   <servlet>
     <servlet-name>distanceinfo</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.DistanceInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>distanceinfo</servlet-name>
-    <url-pattern>/flys/distanceinfo</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>dischargeinfo</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.DischargeInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>dischargeinfo</servlet-name>
-    <url-pattern>/flys/dischargeinfo</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>DischargeInfoXML</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.DischargeInfoXML</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>DischargeInfoXML</servlet-name>
-    <url-pattern>/flys/dischargeinfoxml</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>meta-data</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.MetaDataServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>meta-data</servlet-name>
-    <url-pattern>/flys/meta-data</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>mainvalues</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.WQInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>mainvalues</servlet-name>
-    <url-pattern>/flys/mainvalues</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>gaugeinfo</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.GaugeInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>gaugeinfo</servlet-name>
-    <url-pattern>/flys/gaugeinfo</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>csv</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.CSVExportServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>csv</servlet-name>
-    <url-pattern>/flys/csv</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>ChartOutputService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ChartOutputServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>ChartOutputService</servlet-name>
-    <url-pattern>/flys/chart</url-pattern>
-  </servlet-mapping>
-
   <servlet>
   	<servlet-name>DischargeTablesOverviewService</servlet-name>
   	<servlet-class>org.dive4elements.river.client.server.DischargeTablesServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-  	<servlet-name>DischargeTablesOverviewService</servlet-name>
-  	<url-pattern>/flys/dischargetablesoverview</url-pattern>
-  </servlet-mapping>
-
   <!-- MapFish Print -->
   <servlet>
     <servlet-name>MapOutputService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.MapOutputServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>MapOutputService</servlet-name>
-    <url-pattern>/flys/map</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>mapfish.print</servlet-name>
     <servlet-class>org.mapfish.print.servlet.MapPrinterServlet</servlet-class>
@@ -345,11 +239,6 @@
     </init-param>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>mapfish.print</servlet-name>
-    <url-pattern>/flys/mapfish-print/*</url-pattern>
-  </servlet-mapping>
-
   <!-- Servlet to bridge between MapFish Print and FLYS3 -->
   <servlet>
     <servlet-name>MapPrintService</servlet-name>
@@ -364,286 +253,397 @@
     </init-param>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>MapPrintService</servlet-name>
-    <url-pattern>/flys/map-print</url-pattern>
-  </servlet-mapping>
-
-
   <servlet>
     <servlet-name>FixingsKMChartService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.FixingsKMChartServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>FixingsKMChartService</servlet-name>
-    <url-pattern>/flys/fixings-km-chart</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>DistanceInfoXML</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.DistanceInfoXML</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>DistanceInfoXML</servlet-name>
-    <url-pattern>/flys/distanceinfoxml</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>ExportService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ExportServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>ExportService</servlet-name>
-    <url-pattern>/flys/export</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>CollectionAttributeService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.CollectionAttributeServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>CollectionAttributeService</servlet-name>
-    <url-pattern>/flys/collection-attribute</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>CollectionItemAttributeService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.CollectionItemAttributeServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>CollectionItemAttributeService</servlet-name>
-    <url-pattern>/flys/collection-item-attribute</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>ChartInfoService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ChartInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>ChartInfoService</servlet-name>
-    <url-pattern>/flys/chart-info</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>ReportService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ReportServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>ReportService</servlet-name>
-    <url-pattern>/flys/report</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>SetCollectionNameService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.SetCollectionNameServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>SetCollectionNameService</servlet-name>
-    <url-pattern>/flys/set-collectionname</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>SetCollectionTTLService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.SetCollectionTTLServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>SetCollectionTTLService</servlet-name>
-    <url-pattern>/flys/set-collectionttl</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>DeleteCollectionService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.DeleteCollectionServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>DeleteCollectionService</servlet-name>
-    <url-pattern>/flys/delete-collection</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>MapInfoService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.MapInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>MapInfoService</servlet-name>
-    <url-pattern>/flys/map-info</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>getfeatureinfo</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.GFIServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>getfeatureinfo</servlet-name>
-    <url-pattern>/flys/getfeatureinfo</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>getcapabilities</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.GCServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>getcapabilities</servlet-name>
-    <url-pattern>/flys/getcapabilities</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>DescribeArtifactService</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.DescribeArtifactServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>DescribeArtifactService</servlet-name>
-    <url-pattern>/flys/describe</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>remove-artifact</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.RemoveArtifactServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>remove-artifact</servlet-name>
-    <url-pattern>/flys/remove-artifact</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>GetWMSUrls</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.MapUrlServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>GetWMSUrls</servlet-name>
-    <url-pattern>/flys/map-urls</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>FileUpload</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.FileUploadServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>FileUpload</servlet-name>
-    <url-pattern>/flys/fileupload</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>themelisting</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ThemeListingServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>themelisting</servlet-name>
-    <url-pattern>/flys/themelisting</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>SQKMChart</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.SQKMChartServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>SQKMChart</servlet-name>
-    <url-pattern>/flys/sq-km-chart</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>BedKMChart</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.BedKMChartServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>BedKMChart</servlet-name>
-    <url-pattern>/flys/bed-km-chart</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>BedloadKMChart</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.BedloadKMChartServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>BedloadKMChart</servlet-name>
-    <url-pattern>/flys/bedload-km-chart</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>SedimentLoadInfo</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.SedimentLoadInfoServiceImpl</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>SedimentLoadInfo</servlet-name>
-    <url-pattern>/flys/sedimentloadinfo</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>login</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.LoginServlet</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>login</servlet-name>
-    <url-pattern>/flys/login</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>saml</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.SamlServlet</servlet-class>
   </servlet>
 
-  <servlet-mapping>
-    <servlet-name>saml</servlet-name>
-    <url-pattern>/flys/saml</url-pattern>
-  </servlet-mapping>
-
   <servlet>
     <servlet-name>modules</servlet-name>
     <servlet-class>org.dive4elements.river.client.server.ModuleServiceImpl</servlet-class>
   </servlet>
 
   <servlet-mapping>
+    <servlet-name>user</servlet-name>
+    <url-pattern>/flys/user</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>server-info</servlet-name>
+    <url-pattern>/flys/server-info</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>artifact</servlet-name>
+    <url-pattern>/flys/artifact</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>getartifact</servlet-name>
+    <url-pattern>/flys/getartifact</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>cross-section-km</servlet-name>
+    <url-pattern>/flys/cross-section-km</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>create-collection</servlet-name>
+    <url-pattern>/flys/create-collection</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>rivers</servlet-name>
+    <url-pattern>/flys/rivers</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>riverinfo</servlet-name>
+    <url-pattern>/flys/riverinfo</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>forward</servlet-name>
+    <url-pattern>/flys/forward</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>feed</servlet-name>
+    <url-pattern>/flys/feed</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>fixings-overview</servlet-name>
+    <url-pattern>/flys/fixings-overview</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>advance</servlet-name>
+    <url-pattern>/flys/advance</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>add-artifact</servlet-name>
+    <url-pattern>/flys/add-artifact</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>load-artifact</servlet-name>
+    <url-pattern>/flys/load-artifact</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>describe-collection</servlet-name>
+    <url-pattern>/flys/describe-collection</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>user-collections</servlet-name>
+    <url-pattern>/flys/user-collections</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>distanceinfo</servlet-name>
+    <url-pattern>/flys/distanceinfo</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>dischargeinfo</servlet-name>
+    <url-pattern>/flys/dischargeinfo</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>DischargeInfoXML</servlet-name>
+    <url-pattern>/flys/dischargeinfoxml</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>meta-data</servlet-name>
+    <url-pattern>/flys/meta-data</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>mainvalues</servlet-name>
+    <url-pattern>/flys/mainvalues</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>gaugeinfo</servlet-name>
+    <url-pattern>/flys/gaugeinfo</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>csv</servlet-name>
+    <url-pattern>/flys/csv</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>ChartOutputService</servlet-name>
+    <url-pattern>/flys/chart</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+  	<servlet-name>DischargeTablesOverviewService</servlet-name>
+  	<url-pattern>/flys/dischargetablesoverview</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>MapOutputService</servlet-name>
+    <url-pattern>/flys/map</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>mapfish.print</servlet-name>
+    <url-pattern>/flys/mapfish-print/*</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>MapPrintService</servlet-name>
+    <url-pattern>/flys/map-print</url-pattern>
+  </servlet-mapping>
+
+
+  <servlet-mapping>
+    <servlet-name>FixingsKMChartService</servlet-name>
+    <url-pattern>/flys/fixings-km-chart</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>DistanceInfoXML</servlet-name>
+    <url-pattern>/flys/distanceinfoxml</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>ExportService</servlet-name>
+    <url-pattern>/flys/export</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>CollectionAttributeService</servlet-name>
+    <url-pattern>/flys/collection-attribute</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>CollectionItemAttributeService</servlet-name>
+    <url-pattern>/flys/collection-item-attribute</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>ChartInfoService</servlet-name>
+    <url-pattern>/flys/chart-info</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>ReportService</servlet-name>
+    <url-pattern>/flys/report</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>SetCollectionNameService</servlet-name>
+    <url-pattern>/flys/set-collectionname</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>SetCollectionTTLService</servlet-name>
+    <url-pattern>/flys/set-collectionttl</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>DeleteCollectionService</servlet-name>
+    <url-pattern>/flys/delete-collection</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>MapInfoService</servlet-name>
+    <url-pattern>/flys/map-info</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>getfeatureinfo</servlet-name>
+    <url-pattern>/flys/getfeatureinfo</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>getcapabilities</servlet-name>
+    <url-pattern>/flys/getcapabilities</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>DescribeArtifactService</servlet-name>
+    <url-pattern>/flys/describe</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>remove-artifact</servlet-name>
+    <url-pattern>/flys/remove-artifact</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>GetWMSUrls</servlet-name>
+    <url-pattern>/flys/map-urls</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>FileUpload</servlet-name>
+    <url-pattern>/flys/fileupload</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>themelisting</servlet-name>
+    <url-pattern>/flys/themelisting</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>SQKMChart</servlet-name>
+    <url-pattern>/flys/sq-km-chart</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>BedKMChart</servlet-name>
+    <url-pattern>/flys/bed-km-chart</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>BedloadKMChart</servlet-name>
+    <url-pattern>/flys/bedload-km-chart</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>SedimentLoadInfo</servlet-name>
+    <url-pattern>/flys/sedimentloadinfo</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>login</servlet-name>
+    <url-pattern>/flys/login</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>saml</servlet-name>
+    <url-pattern>/flys/saml</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
     <servlet-name>modules</servlet-name>
     <url-pattern>/flys/modules</url-pattern>
   </servlet-mapping>
 
-  <filter>
-    <filter-name>GGInAFilter</filter-name>
-    <filter-class>org.dive4elements.river.client.server.filter.GGInAFilter</filter-class>
-    <init-param>
-        <param-name>deactivate</param-name>
-        <param-value>false</param-value>
-    </init-param>
-  </filter>
-
-  <filter-mapping>
-    <filter-name>GGInAFilter</filter-name>
-    <url-pattern>/*</url-pattern>
-  </filter-mapping>
-
-  <filter>
-    <filter-name>NoCacheFilter</filter-name>
-    <filter-class>org.dive4elements.river.client.server.filter.NoCacheFilter</filter-class>
-  </filter>
-
-  <filter-mapping>
-    <filter-name>NoCacheFilter</filter-name>
-    <url-pattern>/*</url-pattern>
-  </filter-mapping>
-
 
   <!-- Default page to serve -->
   <welcome-file-list>
Binary file gwt-client/src/main/webapp/images/areapattern-paternCross.png has changed
Binary file gwt-client/src/main/webapp/images/areapattern-patternDagonalLeft.png has changed
Binary file gwt-client/src/main/webapp/images/areapattern-patternDiagonalRight.png has changed
Binary file gwt-client/src/main/webapp/images/areapattern-patternFill.png has changed
Binary file gwt-client/src/main/webapp/images/areapattern-patternPoints.png has changed
--- a/gwt-client/src/test/java/org/dive4elements/river/client/FLYSJUnit.gwt.xml	Fri Feb 09 15:39:49 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module>
-  <!-- Inherit our applications main module.                      -->
-  <inherits name='org.dive4elements.river.client.FLYS'/>
-
-  <!-- Specify the path to any remote services.                   -->
-  <!--
-  <servlet path="/flys/greet" class="org.dive4elements.river.client.server.GreetingServiceImpl" />
-  -->
-
-</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/AbstractModuleRunner.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,352 @@
+package test;
+
+/** 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.
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
+import org.dive4elements.artifacts.common.utils.ClientProtocolUtils;
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.artifacts.httpclient.http.HttpClient;
+import org.dive4elements.artifacts.httpclient.http.HttpClientImpl;
+import org.dive4elements.artifacts.httpclient.http.response.DocumentResponseHandler;
+import org.dive4elements.artifacts.httpclient.utils.XMLUtils;
+import org.dive4elements.river.client.server.AdvanceServiceImpl;
+import org.dive4elements.river.client.server.ArtifactHelper;
+import org.dive4elements.river.client.server.CollectionHelper;
+import org.dive4elements.river.client.server.CreateCollectionServiceImpl;
+import org.dive4elements.river.client.server.FLYSArtifactCreator;
+import org.dive4elements.river.client.server.FeedServiceImpl;
+import org.dive4elements.river.client.server.auth.DefaultUser;
+import org.dive4elements.river.client.server.auth.User;
+import org.dive4elements.river.client.server.auth.UserClient;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.Artifact;
+import org.dive4elements.river.client.shared.model.Collection;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DefaultCollection;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.OutputMode;
+import org.dive4elements.river.client.shared.model.StringOptionsData;
+import org.junit.Assert;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import test.BerechnungsartenTester.CalcMode;
+import test.BerechnungsartenTester.FilenameMapper;
+import test.BerechnungsartenTester.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public abstract class AbstractModuleRunner {
+
+    public enum Infotype {
+        sinfo
+    }
+
+    private static final String lineSeparator = System.getProperty("line.separator");
+
+    private final String serverUrl = "http://localhost:8181";
+    private final String locale = "de";
+    private final HttpClient client;
+
+    private static final String exportFileDir = "D:" + File.separator;
+    private static final String IGNORE_ERSTELLDATUM = "# Datum der Erstellung";
+    private static final String IGNORE_FLYS_VERSION = "# FLYS-Version:";
+    private static final String IGNORE_BEARBEITER = "NEIN_DOCH_NICHT";// "# Bearbeiter:";
+
+    private final String username;
+    private final String password;
+    private final Infotype infotype;
+    private final String userUuid;
+    private Collection collection;
+    private Artifact artifact;
+    private final FilenameMapper fileName;
+
+    // common attributes
+    private final CalcMode calcMode;
+    private final double from;
+    private final double to;
+    private final River river;
+
+    public AbstractModuleRunner(final String username, final String password, final Infotype infotype, final CalcMode sinfoCalcFlowDepth,
+            final FilenameMapper helloWorldFile, final double from, final double to, final River beispielfluss) throws ConnectionException, ServerException {
+        // common attributes (evtl. doch in subklassen, evtl. Zwischenhierarchiestufe einführen
+
+        this.calcMode = sinfoCalcFlowDepth;
+        this.river = beispielfluss;
+        this.from = from;
+        this.to = to;
+
+        this.username = username;
+        this.password = password;
+        this.infotype = infotype;
+        this.fileName = helloWorldFile;
+
+        // init
+        this.client = new HttpClientImpl(this.serverUrl, this.locale);
+        this.userUuid = makeUserUuid();
+        this.collection = getCollection();
+        this.artifact = getArtifact();
+    }
+
+    private String makeUserUuid() throws ConnectionException {
+        final User user = new DefaultUser(this.username, this.password, null, false, new ArrayList<String>(), new ArrayList<String>());
+        final UserClient userClient = new UserClient(this.serverUrl);
+        Element userElement;
+
+        userElement = userClient.findUser(user);
+        return userElement.getAttributeNS(ArtifactNamespaceContext.NAMESPACE_URI, "uuid");
+
+    }
+
+    protected final Artifact getArtifact() throws ServerException, ConnectionException {
+        if (this.artifact == null) {
+            this.artifact = ArtifactHelper.createArtifact(this.serverUrl, this.locale, this.infotype.name(), null);
+            setCollection(CollectionHelper.addArtifact(getCollection(), this.artifact, this.serverUrl, this.locale)); // wichtig; sorgt für Persistenz
+        }
+        return this.artifact;
+    }
+
+    protected Collection getCollection() throws ConnectionException {
+
+        if (this.collection == null) {
+            // lazy-Loading
+            final Document create = ClientProtocolUtils.newCreateCollectionDocument(null);
+            final Document doc = (Document) this.client.createCollection(create, this.userUuid, new DocumentResponseHandler());
+            final String uuid = XMLUtils.xpathString(doc, CreateCollectionServiceImpl.XPATH_COLLECTION_UUID, ArtifactNamespaceContext.INSTANCE);
+            final String ttlStr = XMLUtils.xpathString(doc, CreateCollectionServiceImpl.XPATH_COLLECTION_TTL, ArtifactNamespaceContext.INSTANCE);
+            this.collection = new DefaultCollection(uuid, Long.valueOf(ttlStr), uuid);
+        }
+        return this.collection;
+
+    }
+
+    private final void setCollection(final Collection collection) {
+        this.collection = collection;
+    }
+
+    private final void setArtifact(final Artifact artifact) {
+        this.artifact = artifact;
+    }
+
+    public abstract void runTest(final boolean exportToFile) throws ConnectionException, ServerException, IOException;
+
+    protected final void describeCollection() throws ConnectionException {
+
+        final String uuid = getCollection().identifier();
+        final Document describe = ClientProtocolUtils.newDescribeCollectionDocument(uuid);
+        final Document response = (Document) this.client.doCollectionAction(describe, uuid, new DocumentResponseHandler());
+        final Collection c = CollectionHelper.parseCollection(response);
+        setCollection(c);
+
+    }
+
+    protected final void feedAndGo(final Data[] data, final int reachableStateIndex) throws ConnectionException, ServerException {
+        feed(data);
+        advance(getReachableStateByIndex(getArtifact(), reachableStateIndex)); // reachablestate könnte auch String sein.
+
+    }
+
+    private final String getReachableStateByIndex(final Artifact artifact, final int index) {
+
+        final String[] states = artifact.getArtifactDescription().getReachableStates();
+        if (states != null) {
+
+            if (states.length > index)
+                return states[index];
+
+            return states[0];
+        }
+
+        return "";
+    }
+
+    protected final void feed(final Data[] data) throws ServerException, ConnectionException {
+        final Document feed = ClientProtocolUtils.newFeedDocument(getArtifact().getUuid(), getArtifact().getHash(), createKVP(data));
+        final Document description = (Document) this.client.feed(
+                new org.dive4elements.artifacts.httpclient.objects.Artifact(getArtifact().getUuid(), getArtifact().getHash()), feed,
+                new DocumentResponseHandler());
+
+        final String result = XMLUtils.xpathString(description, FeedServiceImpl.XPATH_RESULT, ArtifactNamespaceContext.INSTANCE);
+
+        if (result == null || !result.equals(FeedServiceImpl.OPERATION_FAILURE)) {
+            setArtifact((Artifact) new FLYSArtifactCreator().create(description));
+        } else if (result != null && result.equals(FeedServiceImpl.OPERATION_FAILURE)) {
+            final String msg = XMLUtils.xpathString(description, FeedServiceImpl.XPATH_RESULT_MSG, ArtifactNamespaceContext.INSTANCE);
+            throw new ServerException(msg);
+        }
+    }
+
+    protected final Data[] extractPairData(final List<String> pairIds, final String dataName) {
+        final DataItem[] items = new DataItem[pairIds.size()];
+        int i = 0;
+        final StringBuilder builder = new StringBuilder();
+        for (final String pairId : pairIds) {
+            builder.append(pairId).append("#");
+            i++;
+        }
+        final String allPairIds = builder.delete(builder.length() - 1, builder.length()).toString(); // letztes Gatter entfernen
+        final DataItem[] item = new DataItem[] { new DefaultDataItem(allPairIds, allPairIds, allPairIds) };
+        return new Data[] { new StringOptionsData(dataName, dataName, item) };
+    }
+
+    private final String[][] createKVP(final Data[] data) {
+        if (data != null) {
+            final String[][] kvp = new String[data.length][];
+
+            int i = 0;
+
+            for (final Data d : data) {
+                final String key = d.getLabel();
+                final String value = d.getStringValue();
+
+                kvp[i++] = new String[] { key, value };
+            }
+
+            return kvp;
+        }
+        return null;
+    }
+
+    private final void advance(final String target) throws ConnectionException, ServerException {
+        final Document advance = ClientProtocolUtils.newAdvanceDocument(getArtifact().getUuid(), getArtifact().getHash(), target);
+        final Document description = (Document) this.client.advance(
+                new org.dive4elements.artifacts.httpclient.objects.Artifact(getArtifact().getUuid(), getArtifact().getHash()), advance,
+                new DocumentResponseHandler());
+
+        if (description == null) {
+            throw new ServerException(AdvanceServiceImpl.ERROR_ADVANCE_ARTIFACT);
+        }
+
+        final String result = XMLUtils.xpathString(description, AdvanceServiceImpl.XPATH_RESULT, ArtifactNamespaceContext.INSTANCE);
+
+        if (result == null || !result.equals(AdvanceServiceImpl.OPERATION_FAILURE)) {
+            setArtifact((Artifact) new FLYSArtifactCreator().create(description));
+        }
+    }
+
+    /// ExportServiceImpl
+    protected final void assertAndWriteToFile(final String mode, final boolean exportToFile) throws IOException {
+
+        final String type = "csv";
+
+        final String enc = "windows-1252";// req.getParameter("encoding");
+
+        final URL expectedResource = getClass().getResource(this.fileName.getFilename());
+        final Document attr = null;
+        final Document request = ClientProtocolUtils.newOutCollectionDocument(getCollection().identifier(), mode, type, attr);
+
+        final InputStream response = this.client.collectionOut(request, getCollection().identifier(), mode);
+
+        final String actual = deleteErstelldatum(IOUtils.toString(response, "UTF-8"));
+
+        final String expected = deleteErstelldatum(FileUtils.readFileToString(new File(expectedResource.getFile()), enc));
+
+        // if (!actual.equals(expected)) {
+        if (exportToFile) {
+            doGetWriteToDisk(mode); // TODO: WENN der Test negativ ausfällt, Datei abspeichern -> Diskussion
+        }
+
+        Assert.assertEquals(expected, actual);
+    }
+
+    private final String deleteErstelldatum(final String input) {
+        String result = "";
+        final String[] lines = input.split(lineSeparator);
+        for (final String line : lines) {
+            if (!line.contains(AbstractModuleRunner.IGNORE_ERSTELLDATUM) && !line.contains(AbstractModuleRunner.IGNORE_FLYS_VERSION)
+                    && !line.contains(AbstractModuleRunner.IGNORE_BEARBEITER)) {
+                result = result + line + lineSeparator;
+            }
+        }
+        return result;
+    }
+
+    public final void doGetWriteToDisk(final String mode) throws FileNotFoundException, IOException {
+
+        final String name = mode;
+        final String type = "csv";
+
+        final String fn = name + System.currentTimeMillis() + "." + type;
+        final String enc = "windows-1252";
+
+        final String filepath = exportFileDir + fn;
+
+        final Document attr = null;
+        final Document request = ClientProtocolUtils.newOutCollectionDocument(getCollection().identifier(), mode, type, attr);
+
+        final InputStream response = this.client.collectionOut(request, getCollection().identifier(), mode);
+        final InputStreamReader in = new InputStreamReader(response, "UTF-8");
+
+        IOUtils.copy(in, new FileOutputStream(filepath), enc);
+
+    }
+
+    protected final void selectCalcMode() throws ConnectionException, ServerException {
+
+        /* Select CalcMode */
+        final String calcmodeStr = this.calcMode.name();
+        final Data dataCalcMode = new StringOptionsData("calculation_mode", "calculation_mode",
+                new DataItem[] { new DefaultDataItem(calcmodeStr, calcmodeStr, calcmodeStr) });
+        feedAndGo(new Data[] { dataCalcMode }, 0);
+    }
+
+    protected final void selectRange() throws ConnectionException, ServerException {
+        final String fromStr = String.valueOf(this.from);
+        final String toStr = String.valueOf(this.to);
+        final Data dataFrom = new StringOptionsData("ld_from", "ld_from", new DataItem[] { new DefaultDataItem(fromStr, fromStr, fromStr) });
+        final Data dataTo = new StringOptionsData("ld_to", "ld_to", new DataItem[] { new DefaultDataItem(toStr, toStr, toStr) });
+        final Data[] rangeFromToDetermined = new Data[] { dataFrom, dataTo };
+
+        feedAndGo(rangeFromToDetermined, 0);
+    }
+
+    protected final void selectRiver() throws ConnectionException, ServerException {
+        final String riverStr = this.river.name();
+        final Data data = new StringOptionsData("river", "river", new DataItem[] { new DefaultDataItem(riverStr, riverStr, riverStr) });
+        feedAndGo(new Data[] { data }, 0);
+    }
+
+    protected final void export(final boolean exportToFile) throws IOException, ServerException {
+        final OutputMode[] modes = getArtifact().getArtifactDescription().getOutputModes();
+        boolean exportFacetCreated = false;
+        if (modes != null) {
+            for (final OutputMode mode : modes) {
+                if (mode.getDescription().contains("_export")) {
+                    assertAndWriteToFile(mode.getName(), exportToFile);
+                    exportFacetCreated = true;
+                }
+            }
+
+        }
+        assert (exportFacetCreated == true);
+    }
+
+    protected final String getRecommendationPairString(final SimpleRecommendation rec1, final SimpleRecommendation rec2)
+            throws ConnectionException, ServerException {
+
+        return rec1.getRecommendationPairString(rec2, getCollection(), this.serverUrl, this.locale);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/BerechnungsartenTester.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,160 @@
+package test;
+
+import java.io.IOException;
+
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+
+// REMARK: ignored, because maven will auto-test all tests, but this one needs a running river-artifacts
+// For running the JUunit test, the annotation @Ignore has to be disabled
+@Ignore
+public class BerechnungsartenTester {
+
+    public static enum CalcMode {
+        sinfo_calc_flow_depth, sinfo_calc_flow_depth_development, sinfo_calc_flow_depth_minmax, sinfo_calc_collision, sinfo_calc_transport_bodies_heights, sinfo_calc_flood_duration
+    };
+
+    public static enum River {
+        Beispielfluss, Rhein, Elbe
+    };
+
+    public static enum FilenameMapper {
+
+        FT_MINMAX_RHEIN_1_FILE("/sinfo/flowdepthminmax/sinfo_minmaxft_01.csv"), //
+        FT_MINMAX_ELBE_2_FILE("/sinfo/flowdepthminmax/sinfo_minmaxft_02.csv"), //
+
+        FT_RHEIN_1_FILE("/sinfo/flowdepth/sinfo_ft_01.csv"), //
+        FT_RHEIN_2_FILE("/sinfo/flowdepth/sinfo_ft_02.csv"), //
+
+        FTE_ELBE_FILE("/sinfo/flowdepthdevelopment/sinfo_fte_01.csv"), //
+        FTE_RHEIN_FILE("/sinfo/flowdepthdevelopment/sinfo_fte_02.csv"),
+
+        TKH_1_ELBE_FILE("/sinfo/flowdepthtkh/sinfo_tkh_01.csv"), //
+        TKH_2_RHEIN_FILE("/sinfo/flowdepthtkh/sinfo_tkh_02.csv"),
+
+        TKH_TKH_RHEIN_FILE("/sinfo/tkh/sinfo_tkh_export.csv");
+
+        private final String filename;
+
+        FilenameMapper(final String filename) {
+            this.filename = filename;
+        }
+
+        public String getFilename() {
+            return this.filename;
+        }
+    }
+
+    private final Boolean overrideFileExport() {
+        return null;
+    }
+
+    /* FLOWDEPTH MIN MAX */
+    @Test
+    public void testFTMINMAX1() throws ServerException, IOException {
+
+        RunnerCreatorHelper.createSinfoFlowdepthMinMaxTest(FilenameMapper.FT_MINMAX_RHEIN_1_FILE, 430, 450, River.Rhein,
+                new SimpleRecommendation("bedheight", "bedheight-single-79-2004-MW-DGM-2004_Epoche_NHN", "longitudinal_section"),
+                new SimpleRecommendation("staticwqkms", "additionals-wstv-0-269", "longitudinal_section", "Amtl.Festlegung_GlQ(2002)")
+
+        ).runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+    @Test
+    public void testFTMINMAX2() throws ConnectionException, ServerException, IOException {
+        RunnerCreatorHelper.createSinfoFlowdepthMinMaxTest(FilenameMapper.FT_MINMAX_ELBE_2_FILE, 0, 90, River.Elbe,
+                // first
+                new SimpleRecommendation("bedheight", "bedheight-single-58-2015-MW-FP-2015_0-502", "longitudinal_section", "FP-2015_0-502"),
+                new SimpleRecommendation("staticwqkms", "fixations-wstv-0-156", "longitudinal_section", "02.09.2004"),
+
+                // second
+                new SimpleRecommendation("bedheight", "bedheight-single-58-2015-MW-FP-2015_0-502", "longitudinal_section", "FP-2015_0-502"),
+                new SimpleRecommendation("staticwqkms", "fixations-wstv-1-156", "longitudinal_section", "03.09.2004"))
+                .runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+    /* FLOWDEPTH */
+    @Test
+    public void testRhein1FT() throws ConnectionException, ServerException, IOException {
+
+        RunnerCreatorHelper.createSinfoFlowdepthTest(FilenameMapper.FT_RHEIN_1_FILE, 350, 380, River.Rhein, false,
+
+                new SimpleRecommendation("bedheight", "bedheight-soundings-79-2004-DGM-2004_Epoche_NHN", "longitudinal_section"),
+                new SimpleRecommendation("staticwqkms", "additionals-wstv-0-415", "longitudinal_section"))
+                .runTest(overrideFileExport() != null ? overrideFileExport() : true);
+
+    }
+
+    @Test
+    public void testRhein2FT() throws ConnectionException, ServerException, IOException {
+        RunnerCreatorHelper
+                .createSinfoFlowdepthTest(FilenameMapper.FT_RHEIN_2_FILE, 655, 675, River.Rhein, true,
+                        new SimpleRecommendation("bedheight", "bedheight-soundings-92-2004-NIEDERRHEIN_QP-2004_Epoche_NHN", "longitudinal_section"),
+                        new SimpleRecommendation("staticwqkms", "fixations-wstv-0-323", "longitudinal_section"))
+
+                .runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+    /* FLOWDEPTH DEVELOPMENT */
+
+    @Test
+    public void testElbeFTE() throws ConnectionException, ServerException, IOException {
+        RunnerCreatorHelper.createSinfoFlowdepthDevelopmentTest(FilenameMapper.FTE_ELBE_FILE, 210, 230, River.Elbe,
+                // current
+                new SimpleRecommendation("bedheight", "bedheight-soundings-66-2008-FP-QP-2008",
+                        // "bedheight-single-66-2008-MW-FP-QP-2008",
+                        "longitudinal_section"),
+                new SimpleRecommendation("staticwqkms", "fixations-wstv-0-196", "longitudinal_section", "05.05.2008"), // sicher
+
+                // historical
+                new SimpleRecommendation("bedheight", "bedheight-soundings-70-1995-QP-1995",
+                        // "bedheight-single-70-1995-MW-QP-1995",
+                        "longitudinal_section"),
+                new SimpleRecommendation("staticwqkms", "fixations-wstv-0-186", "longitudinal_section", "18.03.1997")// sicher
+        ).runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+    @Test
+    public void testRheinFTE() throws ConnectionException, ServerException, IOException {
+        RunnerCreatorHelper.createSinfoFlowdepthDevelopmentTest(FilenameMapper.FTE_RHEIN_FILE, 655, 665, River.Rhein,
+                // current
+                new SimpleRecommendation("bedheight", "bedheight-single-94-2008-MW-NIEDERRHEIN_QP-2008_Epoche_NHN",
+                        // "bedheight-single....",
+                        "longitudinal_section"),
+                new SimpleRecommendation("staticwqkms", "fixations-wstv-0-372", "longitudinal_section", "23.09.2009-1"), // sicher
+
+                // historical
+                new SimpleRecommendation("bedheight", "bedheight-single-89-1991-MW-NIEDERRHEIN_QP-1991_Epoche_NHN",
+                        // "bedheight-soundings-89-1991-NIEDERRHEIN_QP-1991_Epoche_NHN",
+                        "longitudinal_section"),
+                new SimpleRecommendation("staticwqkms", "fixations-wstv-0-374", "longitudinal_section", "23.09.1991") // sicher
+        ).runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+    /* TKH */
+
+    @Test
+    public void testElbeTKH_1() throws ConnectionException, ServerException, IOException {
+        RunnerCreatorHelper.createSinfoTkhTest(FilenameMapper.TKH_1_ELBE_FILE, 150, 160, River.Elbe, new double[] { 1520.0 })
+                .runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+    @Test
+    public void testRheinTKH_2() throws ConnectionException, ServerException, IOException {
+        RunnerCreatorHelper.createSinfoTkhTest(FilenameMapper.TKH_2_RHEIN_FILE, 600, 610, River.Rhein, new double[] { 6125, 6526 })
+                .runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+    @Test
+    public void testTKhTkh() throws ConnectionException, ServerException, IOException {
+        RunnerCreatorHelper.createSinfoTkhTest(FilenameMapper.TKH_TKH_RHEIN_FILE, 0, 182.4, River.Beispielfluss, new double[] { 1059.446 })
+                .runTest(overrideFileExport() != null ? overrideFileExport() : true);
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/RunnerCreatorHelper.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,79 @@
+/** 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 test;
+
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+
+import test.BerechnungsartenTester.CalcMode;
+import test.BerechnungsartenTester.FilenameMapper;
+import test.BerechnungsartenTester.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public final class RunnerCreatorHelper {
+
+    private final static String user = "belger";
+
+    private final static String pw = "belger";
+
+    private RunnerCreatorHelper() {
+        throw new UnsupportedOperationException();
+    }
+
+    // HELPER-Methods:
+
+    public final static AbstractModuleRunner createSinfoFlowdepthMinMaxTest(final FilenameMapper file, final double from, final double to,
+            final River beispielfluss, final SimpleRecommendation rec0, final SimpleRecommendation rec1) throws ConnectionException, ServerException {
+        // TODO: make recommendationPair to method parameter if needed
+        final SinfoFlowdepthMinMaxRunner proof = new SinfoFlowdepthMinMaxRunner(user, pw, CalcMode.sinfo_calc_flow_depth_minmax, file, from, to, beispielfluss);
+        proof.addRecommendationPair(rec0, rec1);
+
+        return proof;
+    }
+
+    public static AbstractModuleRunner createSinfoFlowdepthMinMaxTest(final FilenameMapper file, final int from, final int to, final River river,
+            final SimpleRecommendation simpleRecommendation0, final SimpleRecommendation simpleRecommendation1,
+            final SimpleRecommendation simpleRecommendation2, final SimpleRecommendation simpleRecommendation3) throws ConnectionException, ServerException {
+        final SinfoFlowdepthMinMaxRunner proof = (SinfoFlowdepthMinMaxRunner) createSinfoFlowdepthMinMaxTest(file, from, to, river, simpleRecommendation0,
+                simpleRecommendation1);
+        proof.addRecommendationPair(simpleRecommendation2, simpleRecommendation3);
+        return proof;
+    }
+
+    public final static AbstractModuleRunner createSinfoFlowdepthTest(final FilenameMapper file, final double from, final double to, final River river,
+            final boolean useTkh, final SimpleRecommendation rec0, final SimpleRecommendation rec1) throws ConnectionException, ServerException {
+        final SinfoFlowdepthRunner proof = new SinfoFlowdepthRunner(user, pw, CalcMode.sinfo_calc_flow_depth, file, from, to, river, useTkh);
+        proof.addRecommendationPair(rec0, rec1);
+
+        return proof;
+    }
+
+    public final static AbstractModuleRunner createSinfoFlowdepthDevelopmentTest(final FilenameMapper file, final double from, final double to,
+            final River river, final SimpleRecommendation rec0_curr, final SimpleRecommendation rec1_curr, final SimpleRecommendation rec0_hist,
+            final SimpleRecommendation rec1_hist) throws ConnectionException, ServerException {
+        final SinfoFlowdepthDevelopmentRunner proof = new SinfoFlowdepthDevelopmentRunner(user, pw, CalcMode.sinfo_calc_flow_depth_development, file, from, to,
+                river);
+        proof.addCurrentRecommendationPair(rec0_curr, rec1_curr);
+        proof.addHistoricalRecommendationPair(rec0_hist, rec1_hist);
+        return proof;
+    }
+
+    public final static AbstractModuleRunner createSinfoTkhTest(final FilenameMapper file, final double from, final double to, final River river,
+            // final boolean useTkh,
+            final double[] wasserspiegellage) throws ConnectionException, ServerException {
+        final SinfoTkhRunner proof = new SinfoTkhRunner(user, pw, CalcMode.sinfo_calc_transport_bodies_heights, file, from, to, river, wasserspiegellage);
+
+        return proof;
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/SimpleRecommendation.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,111 @@
+/** 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 test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.river.client.client.ui.NilDatacageTwinPanelInfo;
+import org.dive4elements.river.client.client.ui.RecommandationUtils;
+import org.dive4elements.river.client.server.ArtifactHelper;
+import org.dive4elements.river.client.server.CollectionHelper;
+import org.dive4elements.river.client.server.LoadArtifactServiceImpl;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.Artifact;
+import org.dive4elements.river.client.shared.model.Collection;
+import org.dive4elements.river.client.shared.model.Recommendation;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SimpleRecommendation {
+
+    // entspricht den Bezeichnungen im Datacage-Export
+    private final String factory;
+    private final String ids;
+    private final String target;
+    private String displayName;
+
+    public SimpleRecommendation(final String factory, final String ids, final String target) {
+        this.factory = factory;
+        this.ids = ids;
+        this.target = target;
+    }
+
+    public SimpleRecommendation(final String factory, final String ids, final String target, final String displayName) {
+        this(factory, ids, target);
+        this.displayName = displayName;
+    }
+
+    public String getIds() {
+        return this.ids;
+    }
+
+    public String getTarget() {
+        return this.target;
+    }
+
+    public String getFactory() {
+        return this.factory;
+    }
+
+    private String getDisplayName() {
+        return this.displayName;
+    }
+
+    public final String getRecommendationPairString(final SimpleRecommendation rec2, final Collection collection, final String serverUrl, final String locale)
+            throws ConnectionException, ServerException {
+        final Recommendation recom1 = new Recommendation(this.getFactory(), this.getIds(), this.getTarget());
+        recom1.setDisplayName(this.displayName);
+        final Recommendation recom2 = new Recommendation(rec2.getFactory(), rec2.getIds(), rec2.getTarget());
+        recom2.setDisplayName(rec2.getDisplayName());
+        final Artifact[] artifacts = loadMany(new Recommendation[] { recom1, recom2 }, null, collection, serverUrl, locale);
+        final String rec1String = RecommandationUtils.createDataString(artifacts[0].getUuid(), recom1, new NilDatacageTwinPanelInfo(null, "xxxx"));
+        final String rec2String = RecommandationUtils.createDataString(artifacts[1].getUuid(), recom2, new NilDatacageTwinPanelInfo(null, "xxxx"));
+        final String combinedIdNeu = rec1String + "#" + rec2String;
+        return combinedIdNeu;
+    }
+
+    private final Artifact[] loadMany(final Recommendation[] recoms, final String factory, final Collection collection, final String serverUrl,
+            final String locale) throws ServerException, ConnectionException {
+        final ArrayList<Artifact> artifacts = new ArrayList<Artifact>();
+        final HashMap<Recommendation, Artifact> cloneMap = new HashMap<Recommendation, Artifact>();
+
+        for (final Recommendation recom : recoms) {
+
+            final Artifact prevClone = cloneMap.get(recom);
+            if (prevClone != null) {
+
+                artifacts.add(prevClone);
+            } else {
+                // Not already cloned.
+                final String realFactory = factory != null ? factory : recom.getFactory();
+
+                final Artifact clone = ArtifactHelper.createArtifact(serverUrl, locale, realFactory, recom);
+
+                if (clone != null) {
+                    final Collection c = CollectionHelper.addArtifact(collection, clone, serverUrl, locale);
+
+                    if (c != null) {
+                        artifacts.add(clone);
+                        // Remember we cloned a recommendation like this.
+                        cloneMap.put(recom, clone);
+                    } else {
+                        throw new ServerException(LoadArtifactServiceImpl.ERROR_LOAD_ARTIFACT);
+                    }
+                }
+            }
+        }
+
+        return artifacts.toArray(new Artifact[artifacts.size()]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/SinfoFlowdepthDevelopmentRunner.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,67 @@
+/** 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 test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+
+import test.BerechnungsartenTester.CalcMode;
+import test.BerechnungsartenTester.FilenameMapper;
+import test.BerechnungsartenTester.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SinfoFlowdepthDevelopmentRunner extends AbstractModuleRunner {
+
+    private final List<String> pairIdsCurrent = new ArrayList<String>();
+    private final List<String> pairIdsHistorical = new ArrayList<String>();
+
+    public SinfoFlowdepthDevelopmentRunner(final String username, final String password, final CalcMode sinfoCalcFlowDepth, final FilenameMapper file,
+            final double from, final double to, final River river) throws ConnectionException, ServerException {
+        super(username, password, AbstractModuleRunner.Infotype.sinfo, sinfoCalcFlowDepth, file, from, to, river);
+
+    }
+
+    public void addCurrentRecommendationPair(final SimpleRecommendation rec1, final SimpleRecommendation rec2) throws ConnectionException, ServerException {
+        this.pairIdsCurrent.add(super.getRecommendationPairString(rec1, rec2));
+    }
+
+    public void addHistoricalRecommendationPair(final SimpleRecommendation rec1, final SimpleRecommendation rec2) throws ConnectionException, ServerException {
+        this.pairIdsHistorical.add(super.getRecommendationPairString(rec1, rec2));
+    }
+
+    @Override
+    public void runTest(final boolean exportToFile) throws ServerException, IOException {
+        /* Select River */
+        super.selectRiver();
+
+        /* Select CalcMode */
+        super.selectCalcMode();
+
+        /* Select Range */
+        super.selectRange();
+
+        /* Select current Fixpunkte */
+        feedAndGo(super.extractPairData(this.pairIdsCurrent, "diffid_current"), 0);
+
+        /* Select historical Fixpunkte */
+        feedAndGo(super.extractPairData(this.pairIdsHistorical, "diffid_historical"), 0);
+
+        describeCollection();
+
+        super.export(exportToFile);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/SinfoFlowdepthMinMaxRunner.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,61 @@
+/** 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 test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+
+import test.BerechnungsartenTester.CalcMode;
+import test.BerechnungsartenTester.FilenameMapper;
+import test.BerechnungsartenTester.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SinfoFlowdepthMinMaxRunner extends AbstractModuleRunner {
+
+    private final List<String> pairIds = new ArrayList<String>();
+
+    public SinfoFlowdepthMinMaxRunner(final String username, final String password, final CalcMode sinfoCalcFlowDepthMinmax,
+            final FilenameMapper helloWorldFile, final double from, final double to, final River beispielfluss) throws ConnectionException, ServerException {
+        super(username, password, AbstractModuleRunner.Infotype.sinfo, sinfoCalcFlowDepthMinmax, helloWorldFile, from, to, beispielfluss);
+    }
+
+    public void addRecommendationPair(final SimpleRecommendation rec1, final SimpleRecommendation rec2) throws ConnectionException, ServerException {
+        this.pairIds.add(super.getRecommendationPairString(rec1, rec2));
+    }
+
+    @Override
+    public void runTest(final boolean exportToFile) throws ServerException, IOException {
+
+        /* Select River */
+        super.selectRiver();
+
+        /* Select calcmode */
+        super.selectCalcMode();
+
+        /* Select Range */
+        super.selectRange();
+
+        /* Select Fixpunkte */
+        feedAndGo(extractPairData(this.pairIds, "diffids"), 0);
+
+        // Describe collection
+        describeCollection(); // wichtig, damit die Facets erzeugt werden
+
+        // /* Export calculation */
+        super.export(exportToFile);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/SinfoFlowdepthRunner.java	Fri Jul 13 11:56:22 2018 +0200
@@ -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 test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.StringOptionsData;
+
+import test.BerechnungsartenTester.CalcMode;
+import test.BerechnungsartenTester.FilenameMapper;
+import test.BerechnungsartenTester.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SinfoFlowdepthRunner extends AbstractModuleRunner {
+
+    private final boolean useTkh;
+    private final ArrayList<String> pairIds = new ArrayList<String>();
+
+    public SinfoFlowdepthRunner(final String username, final String password, final CalcMode sinfoCalcFlowDepth, final FilenameMapper file, final double from,
+            final double to, final River river, final boolean useTkh) throws ConnectionException, ServerException {
+        super(username, password, AbstractModuleRunner.Infotype.sinfo, sinfoCalcFlowDepth, file, from, to, river);
+        this.useTkh = useTkh;
+    }
+
+    public void addRecommendationPair(final SimpleRecommendation rec1, final SimpleRecommendation rec2) throws ConnectionException, ServerException {
+        this.pairIds.add(super.getRecommendationPairString(rec1, rec2));
+    }
+
+    @Override
+    public void runTest(final boolean exportToFile) throws ServerException, IOException {
+        /* Select River */
+        super.selectRiver();
+
+        /* Select CalcMode */
+        super.selectCalcMode();
+
+        /* Select Range */
+        super.selectRange();
+
+        /* Select Fixpunkte */
+        feedAndGo(extractPairData(this.pairIds, "diffids"), 0);
+
+        /* Select TRANSPORTKÖRPERHÖHHEN - einziger Unterschied zu FlowdepthMinMax */
+        final String useTkhStr = String.valueOf(this.useTkh);
+        feedAndGo(new Data[] { new StringOptionsData("use_transport_bodies", "use_transport_bodies",
+                new DataItem[] { new DefaultDataItem(useTkhStr, useTkhStr, useTkhStr) }) }, 0);
+
+        describeCollection();
+
+        super.export(exportToFile);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/java/test/SinfoTkhRunner.java	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,81 @@
+/** 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 test;
+
+import java.io.IOException;
+
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.StringOptionsData;
+
+import test.BerechnungsartenTester.CalcMode;
+import test.BerechnungsartenTester.FilenameMapper;
+import test.BerechnungsartenTester.River;
+
+/**
+ * @author Domenico Nardi Tironi
+ *
+ */
+public class SinfoTkhRunner extends AbstractModuleRunner {
+
+    private final double[] wasserspiegellage;
+
+    public SinfoTkhRunner(final String username, final String password, final CalcMode sinfoCalcFlowDepth, final FilenameMapper file, final double from,
+            final double to, final River river, final double[] wasserspiegellage) throws ConnectionException, ServerException {
+        super(username, password, AbstractModuleRunner.Infotype.sinfo, sinfoCalcFlowDepth, file, from, to, river);
+        this.wasserspiegellage = wasserspiegellage;
+    }
+
+    @Override
+    public void runTest(final boolean exportToFile) throws ServerException, IOException {
+        /* Select River */
+        super.selectRiver();
+
+        /* Select CalcMode */
+        super.selectCalcMode();
+
+        super.feed(new Data[] {
+                new StringOptionsData("ld_mode", "ld_mode", new DataItem[] { new DefaultDataItem("distance_only", "distance_only", "distance_only") }) }); // leider
+                                                                                                                                                           // wichtig
+                                                                                                                                                           // :-(
+
+        /* Select Range */
+        super.selectRange();
+
+        // from Panel: new DefaultDataItem("wq_single", "wq_single", sb.toString());
+        final StringBuilder sb = new StringBuilder();
+        for (final double value : this.wasserspiegellage) {
+            sb.append(Double.toString(value));
+            sb.append(" ");
+        }
+
+        final DataItem wsplItem = new DefaultDataItem("wq_single", "wq_single", sb.toString());
+
+        super.feedAndGo(new Data[] {
+
+                new DefaultData("wq_isq", null, null, new DataItem[] { new DefaultDataItem("wq_isq", "wq_isq", "true") }),
+                new DefaultData("wq_isfree", null, null, new DataItem[] { new DefaultDataItem("wq_isfree", "wq_isfree", "false") }),
+                new DefaultData("wq_isrange", null, null, new DataItem[] { new DefaultDataItem("wq_isrange", "wq_isrange", "false") }),
+                new DefaultData("wq_from", null, null, new DataItem[] { new DefaultDataItem("wq_from", "wq_from", "") }),
+                new DefaultData("wq_to", null, null, new DataItem[] { new DefaultDataItem("wq_to", "wq_to", "") }),
+                new DefaultData("wq_step", null, null, new DataItem[] { new DefaultDataItem("wq_step", "wq_step", "") }),
+
+                new DefaultData("wq_single", null, null, new DataItem[] { wsplItem }) }, //
+                0);// reachable state index
+
+        describeCollection();
+
+        super.export(exportToFile);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepth/sinfo_ft_01.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,325 @@
+"##Ergebnisausgabe - Rhein - Fließtiefen"
+"# FLYS-Version: 3.3.x"
+"# Bearbeiter: f"
+"# Datum der Erstellung: 23.05.18"
+"# Gewässer: Rhein"
+"# Höhensystem des Flusses: Wasssers[NN "
+"# Bereich (km): 350,000 - 380,000"
+""
+"Fluss-km";"Fließtiefe [m]";"Wasserstand [Wasssers[NN]";"Q [m³/s]";"Bezeichnung";"Bezugspegel";"Mittlere Sohlhöhe [Wasssers[NN]";"Peilung/Epoche";"Lage"
+""
+"##METADATEN PEILUNG"
+"# Jahr der Peilung: 2004"
+"# Aufnahmeart: DGM"
+"# Auswerter: BfG"
+"# Lagesystem: DHDN_Bessel_GK3"
+"# Höhensystem: müNHN "
+"# ursprüngliches Höhensystem: müNHN"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: Amtl.Festlegung_GlQ(2002) "
+"# Bezugspegel: außerh. d. Bez.pegels"
+"# Jahr/Zeitraum der Wasserspiegellage: 2002"
+""
+"350,000";"3,16";"105,88";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,72";"DGM-2004_Epoche_NHN";""
+"350,100";"3,00";"105,83";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,83";"DGM-2004_Epoche_NHN";""
+"350,200";"2,87";"105,79";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,92";"DGM-2004_Epoche_NHN";""
+"350,300";"2,85";"105,74";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,90";"DGM-2004_Epoche_NHN";""
+"350,400";"2,94";"105,69";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,75";"DGM-2004_Epoche_NHN";""
+"350,500";"3,00";"105,65";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,66";"DGM-2004_Epoche_NHN";""
+"350,600";"3,03";"105,61";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,58";"DGM-2004_Epoche_NHN";""
+"350,700";"3,02";"105,56";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,54";"DGM-2004_Epoche_NHN";""
+"350,800";"3,03";"105,51";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,48";"DGM-2004_Epoche_NHN";""
+"350,900";"3,12";"105,47";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,34";"DGM-2004_Epoche_NHN";""
+"351,000";"3,20";"105,42";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,22";"DGM-2004_Epoche_NHN";""
+"351,100";"3,32";"105,38";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,06";"DGM-2004_Epoche_NHN";""
+"351,200";"3,29";"105,33";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,04";"DGM-2004_Epoche_NHN";""
+"351,300";"3,27";"105,29";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"102,02";"DGM-2004_Epoche_NHN";""
+"351,400";"3,31";"105,24";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,93";"DGM-2004_Epoche_NHN";""
+"351,500";"3,28";"105,20";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,92";"DGM-2004_Epoche_NHN";""
+"351,600";"3,16";"105,15";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,99";"DGM-2004_Epoche_NHN";""
+"351,700";"3,14";"105,11";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,96";"DGM-2004_Epoche_NHN";""
+"351,800";"3,19";"105,06";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,87";"DGM-2004_Epoche_NHN";""
+"351,900";"3,23";"105,01";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,78";"DGM-2004_Epoche_NHN";""
+"352,000";"3,22";"104,97";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,76";"DGM-2004_Epoche_NHN";""
+"352,100";"3,14";"104,95";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,81";"DGM-2004_Epoche_NHN";""
+"352,200";"3,20";"104,93";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,73";"DGM-2004_Epoche_NHN";""
+"352,300";"3,15";"104,89";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,74";"DGM-2004_Epoche_NHN";""
+"352,400";"3,13";"104,85";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,72";"DGM-2004_Epoche_NHN";""
+"352,500";"3,10";"104,81";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,71";"DGM-2004_Epoche_NHN";""
+"352,600";"3,23";"104,77";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,54";"DGM-2004_Epoche_NHN";""
+"352,700";"3,28";"104,74";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,46";"DGM-2004_Epoche_NHN";""
+"352,800";"3,31";"104,71";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,40";"DGM-2004_Epoche_NHN";""
+"352,900";"3,23";"104,68";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,45";"DGM-2004_Epoche_NHN";""
+"353,000";"3,04";"104,64";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,60";"DGM-2004_Epoche_NHN";""
+"353,100";"2,92";"104,61";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,68";"DGM-2004_Epoche_NHN";""
+"353,200";"2,90";"104,58";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,68";"DGM-2004_Epoche_NHN";""
+"353,300";"2,96";"104,54";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,58";"DGM-2004_Epoche_NHN";""
+"353,400";"3,04";"104,50";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,46";"DGM-2004_Epoche_NHN";""
+"353,500";"3,08";"104,46";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,38";"DGM-2004_Epoche_NHN";""
+"353,600";"3,10";"104,42";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,32";"DGM-2004_Epoche_NHN";""
+"353,700";"3,27";"104,38";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,11";"DGM-2004_Epoche_NHN";""
+"353,800";"3,17";"104,34";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,16";"DGM-2004_Epoche_NHN";""
+"353,900";"2,91";"104,32";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,41";"DGM-2004_Epoche_NHN";""
+"354,000";"2,68";"104,29";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,61";"DGM-2004_Epoche_NHN";"Fähre: Neuburg-Neiburgweier -Personen"
+"354,100";"2,61";"104,24";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,63";"DGM-2004_Epoche_NHN";""
+"354,200";"2,79";"104,20";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,41";"DGM-2004_Epoche_NHN";""
+"354,300";"2,96";"104,18";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,22";"DGM-2004_Epoche_NHN";""
+"354,400";"3,02";"104,15";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,13";"DGM-2004_Epoche_NHN";""
+"354,500";"3,05";"104,12";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,07";"DGM-2004_Epoche_NHN";""
+"354,600";"3,11";"104,08";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,97";"DGM-2004_Epoche_NHN";""
+"354,700";"3,15";"104,05";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,90";"DGM-2004_Epoche_NHN";""
+"354,800";"3,23";"104,01";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,78";"DGM-2004_Epoche_NHN";""
+"354,900";"3,18";"103,98";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,80";"DGM-2004_Epoche_NHN";""
+"355,000";"2,99";"103,94";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,95";"DGM-2004_Epoche_NHN";""
+"355,100";"2,88";"103,91";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,03";"DGM-2004_Epoche_NHN";""
+"355,200";"2,83";"103,87";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,04";"DGM-2004_Epoche_NHN";""
+"355,300";"2,78";"103,84";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,06";"DGM-2004_Epoche_NHN";""
+"355,400";"2,74";"103,81";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,07";"DGM-2004_Epoche_NHN";""
+"355,500";"2,77";"103,77";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"101,00";"DGM-2004_Epoche_NHN";""
+"355,600";"2,89";"103,73";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,84";"DGM-2004_Epoche_NHN";""
+"355,700";"2,94";"103,69";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,75";"DGM-2004_Epoche_NHN";""
+"355,800";"3,09";"103,65";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,56";"DGM-2004_Epoche_NHN";""
+"355,900";"3,03";"103,61";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,58";"DGM-2004_Epoche_NHN";""
+"356,000";"2,99";"103,57";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,58";"DGM-2004_Epoche_NHN";"Schwebstoffmessstelle: Neuburgweier"
+"356,100";"2,98";"103,54";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,56";"DGM-2004_Epoche_NHN";""
+"356,200";"2,99";"103,50";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,51";"DGM-2004_Epoche_NHN";""
+"356,300";"2,96";"103,47";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,51";"DGM-2004_Epoche_NHN";""
+"356,400";"2,79";"103,44";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,65";"DGM-2004_Epoche_NHN";""
+"356,500";"2,72";"103,41";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,69";"DGM-2004_Epoche_NHN";""
+"356,600";"2,70";"103,37";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,67";"DGM-2004_Epoche_NHN";""
+"356,700";"2,76";"103,34";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,58";"DGM-2004_Epoche_NHN";""
+"356,800";"2,81";"103,31";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,50";"DGM-2004_Epoche_NHN";""
+"356,900";"2,98";"103,28";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,30";"DGM-2004_Epoche_NHN";""
+"357,000";"3,02";"103,24";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,22";"DGM-2004_Epoche_NHN";""
+"357,100";"2,83";"103,19";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,36";"DGM-2004_Epoche_NHN";""
+"357,200";"2,81";"103,15";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,34";"DGM-2004_Epoche_NHN";""
+"357,300";"2,77";"103,10";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,33";"DGM-2004_Epoche_NHN";""
+"357,400";"2,88";"103,07";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,20";"DGM-2004_Epoche_NHN";""
+"357,500";"2,80";"103,04";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,24";"DGM-2004_Epoche_NHN";""
+"357,600";"2,69";"103,01";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,32";"DGM-2004_Epoche_NHN";""
+"357,700";"2,57";"102,98";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,41";"DGM-2004_Epoche_NHN";""
+"357,800";"2,52";"102,94";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,42";"DGM-2004_Epoche_NHN";""
+"357,900";"2,53";"102,90";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,37";"DGM-2004_Epoche_NHN";""
+"358,000";"2,52";"102,87";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,35";"DGM-2004_Epoche_NHN";""
+"358,100";"2,73";"102,83";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"100,10";"DGM-2004_Epoche_NHN";""
+"358,200";"2,84";"102,78";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,94";"DGM-2004_Epoche_NHN";""
+"358,300";"3,00";"102,73";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,73";"DGM-2004_Epoche_NHN";""
+"358,400";"3,03";"102,70";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,67";"DGM-2004_Epoche_NHN";""
+"358,500";"3,03";"102,67";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,64";"DGM-2004_Epoche_NHN";""
+"358,600";"2,91";"102,64";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,73";"DGM-2004_Epoche_NHN";""
+"358,700";"2,77";"102,61";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,84";"DGM-2004_Epoche_NHN";""
+"358,800";"2,59";"102,57";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,98";"DGM-2004_Epoche_NHN";""
+"358,900";"2,58";"102,53";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,95";"DGM-2004_Epoche_NHN";""
+"359,000";"2,92";"102,50";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,58";"DGM-2004_Epoche_NHN";""
+"359,100";"3,07";"102,46";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,39";"DGM-2004_Epoche_NHN";""
+"359,200";"3,18";"102,43";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,25";"DGM-2004_Epoche_NHN";""
+"359,300";"3,26";"102,39";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,13";"DGM-2004_Epoche_NHN";""
+"359,400";"3,37";"102,35";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,98";"DGM-2004_Epoche_NHN";""
+"359,500";"3,45";"102,32";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,87";"DGM-2004_Epoche_NHN";""
+"359,600";"3,48";"102,29";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,81";"DGM-2004_Epoche_NHN";""
+"359,700";"3,58";"102,26";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,68";"DGM-2004_Epoche_NHN";""
+"359,800";"3,48";"102,22";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,74";"DGM-2004_Epoche_NHN";""
+"359,900";"3,15";"102,19";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,04";"DGM-2004_Epoche_NHN";"Hafen: Karlsruhe -Schutzhafen"
+"360,000";"3,06";"102,15";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,09";"DGM-2004_Epoche_NHN";""
+"360,100";"3,06";"102,12";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"99,06";"DGM-2004_Epoche_NHN";""
+"360,200";"3,13";"102,09";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,96";"DGM-2004_Epoche_NHN";""
+"360,300";"3,20";"102,05";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,85";"DGM-2004_Epoche_NHN";""
+"360,400";"3,12";"102,01";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,89";"DGM-2004_Epoche_NHN";""
+"360,500";"3,07";"101,97";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,90";"DGM-2004_Epoche_NHN";""
+"360,600";"3,15";"101,94";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,79";"DGM-2004_Epoche_NHN";""
+"360,700";"3,30";"101,92";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,62";"DGM-2004_Epoche_NHN";""
+"360,800";"3,46";"101,88";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,42";"DGM-2004_Epoche_NHN";""
+"360,900";"3,55";"101,84";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,29";"DGM-2004_Epoche_NHN";""
+"361,000";"3,41";"101,79";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,38";"DGM-2004_Epoche_NHN";""
+"361,100";"3,40";"101,76";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,36";"DGM-2004_Epoche_NHN";""
+"361,200";"3,34";"101,73";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,40";"DGM-2004_Epoche_NHN";""
+"361,300";"3,35";"101,70";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,35";"DGM-2004_Epoche_NHN";""
+"361,400";"3,35";"101,68";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,33";"DGM-2004_Epoche_NHN";""
+"361,500";"3,32";"101,63";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,31";"DGM-2004_Epoche_NHN";""
+"361,600";"3,36";"101,60";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,24";"DGM-2004_Epoche_NHN";""
+"361,700";"3,42";"101,57";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,15";"DGM-2004_Epoche_NHN";""
+"361,800";"3,44";"101,54";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,10";"DGM-2004_Epoche_NHN";""
+"361,900";"3,42";"101,50";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,08";"DGM-2004_Epoche_NHN";""
+"362,000";"3,43";"101,47";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,04";"DGM-2004_Epoche_NHN";""
+"362,100";"3,43";"101,44";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,01";"DGM-2004_Epoche_NHN";""
+"362,200";"3,36";"101,40";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,04";"DGM-2004_Epoche_NHN";""
+"362,300";"3,34";"101,37";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,03";"DGM-2004_Epoche_NHN";""
+"362,400";"3,34";"101,35";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,01";"DGM-2004_Epoche_NHN";""
+"362,500";"3,28";"101,33";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,05";"DGM-2004_Epoche_NHN";""
+"362,600";"3,07";"101,31";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,24";"DGM-2004_Epoche_NHN";""
+"362,700";"3,04";"101,29";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,25";"DGM-2004_Epoche_NHN";"Geschiebemessstelle: Maxau"
+"362,800";"3,08";"101,26";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"98,18";"DGM-2004_Epoche_NHN";""
+"362,900";"3,31";"101,22";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,91";"DGM-2004_Epoche_NHN";""
+"363,000";"3,36";"101,19";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,83";"DGM-2004_Epoche_NHN";""
+"363,100";"3,28";"101,16";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,88";"DGM-2004_Epoche_NHN";""
+"363,200";"3,19";"101,13";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,94";"DGM-2004_Epoche_NHN";""
+"363,300";"3,18";"101,10";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,92";"DGM-2004_Epoche_NHN";""
+"363,400";"3,24";"101,06";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,82";"DGM-2004_Epoche_NHN";""
+"363,500";"3,30";"101,04";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,74";"DGM-2004_Epoche_NHN";""
+"363,600";"3,29";"101,01";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,72";"DGM-2004_Epoche_NHN";""
+"363,700";"3,37";"100,98";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,62";"DGM-2004_Epoche_NHN";""
+"363,800";"3,42";"100,95";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,53";"DGM-2004_Epoche_NHN";""
+"363,900";"3,40";"100,91";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,51";"DGM-2004_Epoche_NHN";""
+"364,000";"3,26";"100,88";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,62";"DGM-2004_Epoche_NHN";""
+"364,100";"3,22";"100,86";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,64";"DGM-2004_Epoche_NHN";""
+"364,200";"3,21";"100,83";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,62";"DGM-2004_Epoche_NHN";""
+"364,300";"3,19";"100,80";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,61";"DGM-2004_Epoche_NHN";""
+"364,400";"3,22";"100,77";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,55";"DGM-2004_Epoche_NHN";""
+"364,500";"3,27";"100,75";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,48";"DGM-2004_Epoche_NHN";""
+"364,600";"3,25";"100,71";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,46";"DGM-2004_Epoche_NHN";""
+"364,700";"3,20";"100,69";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,49";"DGM-2004_Epoche_NHN";""
+"364,800";"3,26";"100,65";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,39";"DGM-2004_Epoche_NHN";""
+"364,900";"3,16";"100,63";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,46";"DGM-2004_Epoche_NHN";""
+"365,000";"3,08";"100,61";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,53";"DGM-2004_Epoche_NHN";""
+"365,100";"3,03";"100,58";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,55";"DGM-2004_Epoche_NHN";""
+"365,200";"2,97";"100,54";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,57";"DGM-2004_Epoche_NHN";""
+"365,300";"2,87";"100,51";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,64";"DGM-2004_Epoche_NHN";""
+"365,400";"2,85";"100,48";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,63";"DGM-2004_Epoche_NHN";""
+"365,500";"2,84";"100,45";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,62";"DGM-2004_Epoche_NHN";""
+"365,600";"2,92";"100,42";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,50";"DGM-2004_Epoche_NHN";""
+"365,700";"3,06";"100,39";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,33";"DGM-2004_Epoche_NHN";""
+"365,800";"3,16";"100,35";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,19";"DGM-2004_Epoche_NHN";""
+"365,900";"3,32";"100,31";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,99";"DGM-2004_Epoche_NHN";""
+"366,000";"3,32";"100,27";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,95";"DGM-2004_Epoche_NHN";""
+"366,100";"3,24";"100,23";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,99";"DGM-2004_Epoche_NHN";""
+"366,200";"3,09";"100,21";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,12";"DGM-2004_Epoche_NHN";""
+"366,300";"2,92";"100,19";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,27";"DGM-2004_Epoche_NHN";""
+"366,400";"2,88";"100,17";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,29";"DGM-2004_Epoche_NHN";""
+"366,500";"2,84";"100,14";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,30";"DGM-2004_Epoche_NHN";""
+"366,600";"2,90";"100,09";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,19";"DGM-2004_Epoche_NHN";""
+"366,700";"2,98";"100,07";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,09";"DGM-2004_Epoche_NHN";""
+"366,800";"2,97";"100,03";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,06";"DGM-2004_Epoche_NHN";""
+"366,900";"2,94";"99,99";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,04";"DGM-2004_Epoche_NHN";""
+"367,000";"2,85";"99,95";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,10";"DGM-2004_Epoche_NHN";""
+"367,100";"2,86";"99,92";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"97,06";"DGM-2004_Epoche_NHN";""
+"367,200";"3,03";"99,89";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,86";"DGM-2004_Epoche_NHN";""
+"367,300";"3,26";"99,86";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,60";"DGM-2004_Epoche_NHN";""
+"367,400";"3,43";"99,83";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,40";"DGM-2004_Epoche_NHN";""
+"367,500";"3,29";"99,80";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,51";"DGM-2004_Epoche_NHN";"Hafen: Karlsruhe -Ölhafen -Schutzhafen"
+"367,600";"3,34";"99,76";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,42";"DGM-2004_Epoche_NHN";""
+"367,700";"3,29";"99,73";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,44";"DGM-2004_Epoche_NHN";""
+"367,800";"3,19";"99,70";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,51";"DGM-2004_Epoche_NHN";""
+"367,900";"3,10";"99,67";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,57";"DGM-2004_Epoche_NHN";""
+"368,000";"3,17";"99,64";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,47";"DGM-2004_Epoche_NHN";""
+"368,100";"3,25";"99,60";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,35";"DGM-2004_Epoche_NHN";""
+"368,200";"3,20";"99,57";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,37";"DGM-2004_Epoche_NHN";""
+"368,300";"3,19";"99,54";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,35";"DGM-2004_Epoche_NHN";""
+"368,400";"3,12";"99,52";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,40";"DGM-2004_Epoche_NHN";""
+"368,500";"3,04";"99,48";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,44";"DGM-2004_Epoche_NHN";""
+"368,600";"3,06";"99,45";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,39";"DGM-2004_Epoche_NHN";""
+"368,700";"3,13";"99,41";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,28";"DGM-2004_Epoche_NHN";""
+"368,800";"3,14";"99,38";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,24";"DGM-2004_Epoche_NHN";""
+"368,900";"3,17";"99,35";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,18";"DGM-2004_Epoche_NHN";""
+"369,000";"3,43";"99,32";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,89";"DGM-2004_Epoche_NHN";""
+"369,100";"3,34";"99,29";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,95";"DGM-2004_Epoche_NHN";""
+"369,200";"3,30";"99,26";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,96";"DGM-2004_Epoche_NHN";""
+"369,300";"3,16";"99,22";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,06";"DGM-2004_Epoche_NHN";""
+"369,400";"2,86";"99,20";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,34";"DGM-2004_Epoche_NHN";""
+"369,500";"2,72";"99,17";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,45";"DGM-2004_Epoche_NHN";""
+"369,600";"2,77";"99,14";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,37";"DGM-2004_Epoche_NHN";""
+"369,700";"2,89";"99,10";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,21";"DGM-2004_Epoche_NHN";""
+"369,800";"3,19";"99,06";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,87";"DGM-2004_Epoche_NHN";""
+"369,900";"3,43";"99,03";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,60";"DGM-2004_Epoche_NHN";""
+"370,000";"3,46";"99,00";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,54";"DGM-2004_Epoche_NHN";""
+"370,100";"3,39";"98,98";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,59";"DGM-2004_Epoche_NHN";""
+"370,200";"3,36";"98,95";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,59";"DGM-2004_Epoche_NHN";""
+"370,300";"3,39";"98,92";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,53";"DGM-2004_Epoche_NHN";""
+"370,400";"3,36";"98,88";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,52";"DGM-2004_Epoche_NHN";""
+"370,500";"3,39";"98,84";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,45";"DGM-2004_Epoche_NHN";""
+"370,600";"3,35";"98,81";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,46";"DGM-2004_Epoche_NHN";""
+"370,700";"3,29";"98,78";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,49";"DGM-2004_Epoche_NHN";""
+"370,800";"3,16";"98,75";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,59";"DGM-2004_Epoche_NHN";""
+"370,900";"3,07";"98,73";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,66";"DGM-2004_Epoche_NHN";""
+"371,000";"2,94";"98,70";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,76";"DGM-2004_Epoche_NHN";""
+"371,100";"2,84";"98,67";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,83";"DGM-2004_Epoche_NHN";""
+"371,200";"2,69";"98,64";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,95";"DGM-2004_Epoche_NHN";"Zufluss: Alb"
+"371,300";"2,63";"98,61";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,98";"DGM-2004_Epoche_NHN";""
+"371,400";"2,66";"98,58";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,92";"DGM-2004_Epoche_NHN";""
+"371,500";"2,70";"98,55";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,85";"DGM-2004_Epoche_NHN";""
+"371,600";"2,71";"98,51";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,80";"DGM-2004_Epoche_NHN";""
+"371,700";"2,66";"98,48";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,82";"DGM-2004_Epoche_NHN";""
+"371,800";"2,61";"98,45";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,84";"DGM-2004_Epoche_NHN";"Geschiebemessstelle: Leimersheim"
+"371,900";"2,57";"98,42";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,85";"DGM-2004_Epoche_NHN";""
+"372,000";"2,48";"98,39";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,91";"DGM-2004_Epoche_NHN";""
+"372,100";"2,35";"98,35";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"96,00";"DGM-2004_Epoche_NHN";"Fähre: Leimersheim-Leopoldshafen"
+"372,200";"2,38";"98,32";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,94";"DGM-2004_Epoche_NHN";""
+"372,300";"2,51";"98,29";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,78";"DGM-2004_Epoche_NHN";""
+"372,400";"2,63";"98,26";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,63";"DGM-2004_Epoche_NHN";""
+"372,500";"2,73";"98,23";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,50";"DGM-2004_Epoche_NHN";""
+"372,600";"2,73";"98,20";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,47";"DGM-2004_Epoche_NHN";""
+"372,700";"2,68";"98,17";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,49";"DGM-2004_Epoche_NHN";""
+"372,800";"2,71";"98,14";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,43";"DGM-2004_Epoche_NHN";""
+"372,900";"2,69";"98,11";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,42";"DGM-2004_Epoche_NHN";""
+"373,000";"2,65";"98,08";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,43";"DGM-2004_Epoche_NHN";""
+"373,100";"2,60";"98,05";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,45";"DGM-2004_Epoche_NHN";""
+"373,200";"2,61";"98,02";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,41";"DGM-2004_Epoche_NHN";""
+"373,300";"2,68";"97,98";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,30";"DGM-2004_Epoche_NHN";""
+"373,400";"2,76";"97,95";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,19";"DGM-2004_Epoche_NHN";""
+"373,500";"2,75";"97,92";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,17";"DGM-2004_Epoche_NHN";""
+"373,600";"2,76";"97,89";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,13";"DGM-2004_Epoche_NHN";""
+"373,700";"2,73";"97,85";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,12";"DGM-2004_Epoche_NHN";""
+"373,800";"2,69";"97,82";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,13";"DGM-2004_Epoche_NHN";""
+"373,900";"2,76";"97,78";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"95,02";"DGM-2004_Epoche_NHN";""
+"374,000";"2,84";"97,75";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,91";"DGM-2004_Epoche_NHN";""
+"374,100";"2,82";"97,71";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,89";"DGM-2004_Epoche_NHN";""
+"374,200";"2,78";"97,67";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,89";"DGM-2004_Epoche_NHN";""
+"374,300";"2,71";"97,64";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,93";"DGM-2004_Epoche_NHN";""
+"374,400";"2,66";"97,60";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,94";"DGM-2004_Epoche_NHN";""
+"374,500";"2,66";"97,57";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,90";"DGM-2004_Epoche_NHN";""
+"374,600";"2,69";"97,53";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,84";"DGM-2004_Epoche_NHN";""
+"374,700";"2,69";"97,49";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,80";"DGM-2004_Epoche_NHN";""
+"374,800";"2,79";"97,45";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,66";"DGM-2004_Epoche_NHN";""
+"374,900";"2,93";"97,42";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,49";"DGM-2004_Epoche_NHN";""
+"375,000";"2,99";"97,39";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,40";"DGM-2004_Epoche_NHN";""
+"375,100";"2,97";"97,36";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,39";"DGM-2004_Epoche_NHN";""
+"375,200";"2,95";"97,33";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,38";"DGM-2004_Epoche_NHN";""
+"375,300";"3,05";"97,29";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,24";"DGM-2004_Epoche_NHN";""
+"375,400";"2,98";"97,25";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,27";"DGM-2004_Epoche_NHN";""
+"375,500";"2,88";"97,21";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,33";"DGM-2004_Epoche_NHN";""
+"375,600";"2,76";"97,18";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,42";"DGM-2004_Epoche_NHN";""
+"375,700";"2,65";"97,15";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,50";"DGM-2004_Epoche_NHN";""
+"375,800";"2,69";"97,13";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,44";"DGM-2004_Epoche_NHN";""
+"375,900";"2,73";"97,10";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,37";"DGM-2004_Epoche_NHN";""
+"376,000";"2,81";"97,07";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,26";"DGM-2004_Epoche_NHN";""
+"376,100";"2,95";"97,02";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"94,07";"DGM-2004_Epoche_NHN";""
+"376,200";"3,21";"96,99";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,78";"DGM-2004_Epoche_NHN";""
+"376,300";"3,19";"96,96";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,77";"DGM-2004_Epoche_NHN";""
+"376,400";"3,20";"96,92";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,72";"DGM-2004_Epoche_NHN";""
+"376,500";"3,40";"96,88";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,48";"DGM-2004_Epoche_NHN";""
+"376,600";"3,44";"96,85";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,41";"DGM-2004_Epoche_NHN";""
+"376,700";"3,39";"96,81";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,42";"DGM-2004_Epoche_NHN";"Altrhein: Hochstetten -Kiesbaggerstelle"
+"376,800";"3,33";"96,78";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,46";"DGM-2004_Epoche_NHN";""
+"376,900";"3,20";"96,74";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,54";"DGM-2004_Epoche_NHN";""
+"377,000";"3,37";"96,71";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,34";"DGM-2004_Epoche_NHN";""
+"377,100";"3,48";"96,68";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,20";"DGM-2004_Epoche_NHN";""
+"377,200";"3,49";"96,66";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,17";"DGM-2004_Epoche_NHN";""
+"377,300";"3,34";"96,63";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,29";"DGM-2004_Epoche_NHN";""
+"377,400";"3,29";"96,60";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,31";"DGM-2004_Epoche_NHN";""
+"377,500";"3,28";"96,56";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,28";"DGM-2004_Epoche_NHN";""
+"377,600";"3,28";"96,52";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,24";"DGM-2004_Epoche_NHN";""
+"377,700";"3,35";"96,49";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,14";"DGM-2004_Epoche_NHN";""
+"377,800";"3,31";"96,46";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,15";"DGM-2004_Epoche_NHN";""
+"377,900";"3,23";"96,42";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,19";"DGM-2004_Epoche_NHN";""
+"378,000";"3,20";"96,39";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,19";"DGM-2004_Epoche_NHN";""
+"378,100";"3,10";"96,35";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,25";"DGM-2004_Epoche_NHN";""
+"378,200";"3,15";"96,32";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,17";"DGM-2004_Epoche_NHN";""
+"378,300";"3,13";"96,28";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,15";"DGM-2004_Epoche_NHN";""
+"378,400";"2,95";"96,25";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,30";"DGM-2004_Epoche_NHN";""
+"378,500";"2,81";"96,22";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,41";"DGM-2004_Epoche_NHN";""
+"378,600";"2,65";"96,19";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,54";"DGM-2004_Epoche_NHN";""
+"378,700";"2,55";"96,16";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,61";"DGM-2004_Epoche_NHN";""
+"378,800";"2,55";"96,13";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,58";"DGM-2004_Epoche_NHN";""
+"378,900";"2,63";"96,10";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,47";"DGM-2004_Epoche_NHN";""
+"379,000";"2,73";"96,06";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,33";"DGM-2004_Epoche_NHN";""
+"379,100";"2,84";"96,02";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,18";"DGM-2004_Epoche_NHN";""
+"379,200";"2,91";"95,98";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,07";"DGM-2004_Epoche_NHN";""
+"379,300";"3,00";"95,94";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"92,94";"DGM-2004_Epoche_NHN";""
+"379,400";"3,14";"95,91";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"92,77";"DGM-2004_Epoche_NHN";""
+"379,500";"3,15";"95,88";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"92,73";"DGM-2004_Epoche_NHN";""
+"379,600";"3,11";"95,85";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"92,74";"DGM-2004_Epoche_NHN";""
+"379,700";"2,91";"95,83";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"92,92";"DGM-2004_Epoche_NHN";""
+"379,800";"2,69";"95,81";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,12";"DGM-2004_Epoche_NHN";""
+"379,900";"2,47";"95,78";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,31";"DGM-2004_Epoche_NHN";""
+"380,000";"2,45";"95,74";"585";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"93,28";"DGM-2004_Epoche_NHN";""
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepth/sinfo_ft_02.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,223 @@
+"##Ergebnisausgabe - Rhein - Fließtiefen"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: f"
+"# Datum der Erstellung: 06.06.18"
+"# Gewässer: Rhein"
+"# Höhensystem des Flusses: Wasssers[NN "
+"# Bereich (km): 655,000 - 675,000"
+""
+"Fluss-km";"Fließtiefe [m]";"Fließtiefe mit TKH [m]";"Transportkörperhöhe [cm]";"Wasserstand [Wasssers[NN]";"Q [m³/s]";"Bezeichnung";"Bezugspegel";"Mittlere Sohlhöhe [Wasssers[NN]";"Peilung/Epoche";"Lage"
+""
+"##METADATEN PEILUNG"
+"# Jahr der Peilung: 2004"
+"# Aufnahmeart: Querprofile"
+"# Auswerter: WSA Duisburg (Abel)"
+"# Lagesystem: LS unbekannt"
+"# Höhensystem: müNHN "
+"# ursprüngliches Höhensystem: müNHN"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: 30.01.1995 "
+"# Bezugspegel: Bonn"
+"# Jahr/Zeitraum der Wasserspiegellage: 1995"
+""
+"655,200";"10,84";"10,78";"12,5";"52,65";"10.500";"30.01.1995";"Bonn";"41,81";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"655,300";"10,87";"10,79";"15,2";"52,64";"10.500";"30.01.1995";"Bonn";"41,77";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"655,400";"10,92";"10,83";"18,0";"52,63";"10.500";"30.01.1995";"Bonn";"41,71";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"655,500";"10,85";"10,72";"25,7";"52,62";"10.500";"30.01.1995";"Bonn";"41,77";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"655,600";"10,87";"10,71";"32,8";"52,60";"10.500";"30.01.1995";"Bonn";"41,73";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"655,700";"10,80";"10,60";"39,0";"52,59";"10.500";"30.01.1995";"Bonn";"41,79";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"655,800";"10,84";"10,61";"45,0";"52,57";"10.500";"30.01.1995";"Bonn";"41,73";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"655,900";"10,97";"10,71";"51,1";"52,56";"10.500";"30.01.1995";"Bonn";"41,59";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,000";"11,07";"10,79";"55,8";"52,54";"10.500";"30.01.1995";"Bonn";"41,47";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,100";"11,26";"10,96";"60,9";"52,52";"10.500";"30.01.1995";"Bonn";"41,26";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,200";"11,41";"11,08";"65,7";"52,50";"10.500";"30.01.1995";"Bonn";"41,09";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,300";"11,59";"11,24";"70,6";"52,47";"10.500";"30.01.1995";"Bonn";"40,88";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,400";"11,58";"11,21";"74,1";"52,45";"10.500";"30.01.1995";"Bonn";"40,87";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,500";"11,69";"11,30";"78,3";"52,42";"10.500";"30.01.1995";"Bonn";"40,73";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,600";"11,49";"11,09";"79,5";"52,40";"10.500";"30.01.1995";"Bonn";"40,91";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,700";"11,84";"11,42";"84,8";"52,38";"10.500";"30.01.1995";"Bonn";"40,54";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,800";"11,98";"11,54";"88,6";"52,36";"10.500";"30.01.1995";"Bonn";"40,38";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"656,900";"11,95";"11,50";"91,0";"52,34";"10.500";"30.01.1995";"Bonn";"40,39";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,000";"11,99";"11,52";"93,9";"52,32";"10.500";"30.01.1995";"Bonn";"40,33";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,100";"11,94";"11,47";"93,5";"52,30";"10.500";"30.01.1995";"Bonn";"40,36";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,200";"12,11";"11,64";"94,6";"52,27";"10.500";"30.01.1995";"Bonn";"40,16";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,300";"11,92";"11,46";"92,8";"52,25";"10.500";"30.01.1995";"Bonn";"40,33";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,400";"12,16";"11,69";"94,6";"52,22";"10.500";"30.01.1995";"Bonn";"40,06";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,500";"12,21";"11,26";"94,7";"52,20";"10.500";"30.01.1995";"Bonn";"39,99";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,600";"11,94";"11,02";"92,2";"52,18";"10.500";"30.01.1995";"Bonn";"40,24";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,700";"11,83";"11,37";"91,4";"52,17";"10.500";"30.01.1995";"Bonn";"40,34";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,800";"11,66";"11,21";"90,0";"52,15";"10.500";"30.01.1995";"Bonn";"40,49";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"657,900";"11,72";"11,27";"90,6";"52,14";"10.500";"30.01.1995";"Bonn";"40,42";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,000";"11,70";"11,25";"90,5";"52,12";"10.500";"30.01.1995";"Bonn";"40,42";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,100";"11,77";"11,31";"91,1";"52,10";"10.500";"30.01.1995";"Bonn";"40,33";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,200";"11,84";"11,38";"91,8";"52,08";"10.500";"30.01.1995";"Bonn";"40,24";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,300";"12,00";"11,53";"93,9";"52,06";"10.500";"30.01.1995";"Bonn";"40,06";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,400";"12,01";"11,54";"94,8";"52,04";"10.500";"30.01.1995";"Bonn";"40,03";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,500";"11,91";"10,96";"94,6";"52,02";"10.500";"30.01.1995";"Bonn";"40,11";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,600";"12,19";"11,21";"97,6";"52,00";"10.500";"30.01.1995";"Bonn";"39,81";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,700";"12,19";"11,70";"98,2";"51,98";"10.500";"30.01.1995";"Bonn";"39,79";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,800";"12,43";"11,93";"100,8";"51,96";"10.500";"30.01.1995";"Bonn";"39,53";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"658,900";"12,68";"12,17";"101,9";"51,93";"10.500";"30.01.1995";"Bonn";"39,25";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,000";"12,37";"11,88";"97,9";"51,91";"10.500";"30.01.1995";"Bonn";"39,54";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,100";"12,65";"12,16";"98,7";"51,89";"10.500";"30.01.1995";"Bonn";"39,24";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,200";"12,65";"12,17";"96,9";"51,87";"10.500";"30.01.1995";"Bonn";"39,22";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,300";"12,40";"11,94";"92,8";"51,85";"10.500";"30.01.1995";"Bonn";"39,45";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,400";"12,08";"11,59";"97,2";"51,83";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,75";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,500";"12,02";"11,06";"95,6";"51,81";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,79";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,600";"12,05";"11,10";"94,6";"51,79";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,74";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,700";"11,95";"11,03";"92,4";"51,76";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,81";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,800";"11,63";"10,75";"88,1";"51,73";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,10";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"659,900";"11,52";"10,67";"85,4";"51,70";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,18";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,000";"11,77";"10,92";"85,2";"51,67";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,90";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,100";"11,91";"11,05";"85,9";"51,64";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,73";"NIEDERRHEIN_QP-2004_Epoche_NHN";"Schwebstoffmessstelle: Mondorf"
+"660,200";"11,86";"11,01";"85,1";"51,61";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,75";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,300";"11,77";"10,93";"84,0";"51,58";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,81";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,400";"11,47";"10,66";"81,3";"51,55";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,08";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,500";"11,26";"10,47";"79,3";"51,53";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,27";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,600";"11,06";"10,30";"76,3";"51,52";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,46";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,700";"11,07";"10,32";"74,8";"51,50";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,43";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,800";"11,00";"10,64";"72,6";"51,49";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,49";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"660,900";"11,07";"10,71";"71,2";"51,47";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,40";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,000";"11,09";"10,74";"69,2";"51,46";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,37";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,100";"10,96";"10,63";"66,2";"51,44";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,48";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,200";"11,12";"10,79";"65,9";"51,42";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,30";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,300";"11,31";"10,98";"65,6";"51,40";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,09";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,400";"11,50";"11,17";"65,3";"51,39";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,89";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,500";"11,45";"11,13";"63,4";"51,37";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,92";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,600";"11,15";"10,85";"60,0";"51,35";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,20";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,700";"10,98";"10,68";"59,0";"51,33";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,35";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,800";"11,10";"10,80";"59,6";"51,31";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,21";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"661,900";"11,09";"10,49";"59,5";"51,29";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,20";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,000";"11,01";"10,42";"59,0";"51,27";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,26";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,100";"10,93";"10,34";"58,5";"51,25";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,32";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,200";"11,03";"10,44";"59,0";"51,23";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,20";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,300";"11,02";"10,72";"60,2";"51,21";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,19";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,400";"11,30";"10,99";"63,0";"51,19";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,89";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,500";"10,82";"10,51";"61,2";"51,17";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,35";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,600";"10,71";"10,40";"61,5";"51,15";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,44";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,700";"10,93";"10,61";"63,8";"51,13";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,20";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,800";"11,07";"10,73";"67,4";"51,11";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,04";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"662,900";"10,90";"10,21";"68,6";"51,09";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,19";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,000";"10,85";"10,15";"70,3";"51,07";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,22";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,100";"11,00";"10,27";"73,2";"51,05";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,05";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,200";"11,04";"10,29";"75,1";"51,02";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,98";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,300";"10,96";"10,20";"76,0";"51,00";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"40,04";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,400";"11,15";"10,38";"77,1";"50,97";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,82";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,500";"11,28";"10,50";"77,7";"50,95";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,67";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,600";"11,41";"10,63";"78,3";"50,92";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,51";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,700";"11,33";"10,94";"77,4";"50,90";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,57";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,800";"10,96";"10,59";"74,3";"50,87";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,91";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"663,900";"11,02";"10,64";"75,1";"50,85";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,83";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,000";"11,26";"10,87";"77,2";"50,82";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,56";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,100";"11,50";"11,13";"74,6";"50,80";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,30";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,200";"11,75";"11,39";"72,0";"50,77";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,02";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,300";"11,39";"11,06";"65,5";"50,75";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,36";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,400";"11,79";"11,47";"63,9";"50,72";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,93";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,500";"11,56";"11,27";"58,2";"50,70";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,14";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,600";"11,54";"11,24";"61,0";"50,67";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,13";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,700";"11,72";"11,40";"64,9";"50,65";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,93";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,800";"11,80";"11,46";"68,2";"50,62";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,82";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"664,900";"11,69";"11,34";"70,3";"50,60";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,91";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,000";"11,62";"11,27";"71,0";"50,57";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,95";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,100";"11,44";"11,08";"72,7";"50,55";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,11";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,200";"11,42";"11,04";"75,5";"50,52";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,10";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,300";"11,47";"11,07";"79,1";"50,50";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,03";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,400";"11,37";"10,96";"81,7";"50,47";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,10";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,500";"11,29";"10,87";"84,6";"50,45";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,16";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,600";"11,22";"10,82";"80,4";"50,42";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,20";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,700";"11,06";"10,68";"75,5";"50,40";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,34";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,800";"10,91";"10,56";"70,7";"50,37";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,46";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"665,900";"10,87";"10,54";"66,7";"50,35";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,48";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,000";"10,74";"10,43";"62,1";"50,32";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,58";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,100";"10,78";"10,46";"63,8";"50,30";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,52";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,200";"10,86";"10,53";"65,7";"50,28";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,42";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,300";"10,97";"10,29";"67,8";"50,26";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,29";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,400";"10,96";"10,27";"69,1";"50,24";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,28";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,500";"11,09";"10,38";"71,3";"50,22";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,13";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,600";"11,36";"10,62";"74,4";"50,20";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,84";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,700";"11,32";"10,56";"75,8";"50,17";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,85";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,800";"11,41";"10,63";"78,1";"50,15";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,74";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"666,900";"11,20";"10,42";"78,0";"50,12";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,92";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,000";"11,25";"10,45";"79,7";"50,10";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,85";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,100";"11,19";"10,38";"81,5";"50,08";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,89";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,200";"11,08";"10,26";"82,1";"50,06";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,98";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,300";"11,04";"10,21";"83,2";"50,04";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,00";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,400";"11,01";"10,17";"84,4";"50,02";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,01";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,500";"11,14";"10,27";"86,9";"50,00";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,86";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,600";"10,94";"10,13";"81,1";"49,97";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"39,03";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,700";"11,02";"10,24";"77,6";"49,95";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,93";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,800";"11,07";"10,33";"74,3";"49,92";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,85";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"667,900";"11,53";"10,79";"73,8";"49,90";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,37";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,000";"11,55";"11,20";"70,1";"49,87";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,32";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,100";"11,57";"11,23";"68,9";"49,85";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,28";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,200";"11,44";"11,11";"66,7";"49,82";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,38";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,300";"11,46";"11,14";"63,0";"49,80";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,34";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,400";"11,33";"11,04";"58,1";"49,77";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,44";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,500";"11,53";"11,26";"54,5";"49,75";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,22";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,600";"11,75";"11,50";"50,5";"49,72";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,97";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,700";"11,64";"11,42";"44,3";"49,70";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,06";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,800";"11,39";"11,19";"39,4";"49,67";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,28";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"668,900";"11,28";"11,10";"35,1";"49,65";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,37";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,000";"11,23";"11,08";"30,8";"49,62";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,39";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,100";"11,39";"11,26";"26,9";"49,60";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,21";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,200";"11,19";"11,08";"21,9";"49,57";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,38";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,300";"11,15";"11,06";"17,2";"49,55";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,40";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,400";"11,22";"11,12";"19,2";"49,52";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,30";"NIEDERRHEIN_QP-2004_Epoche_NHN";"Fähre: Lülsdorf-Wesseling -Personen"
+"669,500";"11,02";"10,92";"20,6";"49,50";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,48";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,600";"11,00";"10,89";"22,1";"49,47";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,47";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,700";"11,16";"10,92";"23,9";"49,45";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,29";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,800";"11,27";"11,01";"25,6";"49,42";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,15";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"669,900";"11,39";"11,14";"24,7";"49,40";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,01";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,000";"11,33";"11,10";"23,5";"49,37";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,04";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,100";"11,37";"11,15";"22,4";"49,35";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,98";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,200";"11,40";"11,19";"21,4";"49,32";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,92";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,300";"11,26";"11,06";"20,1";"49,30";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,04";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,400";"11,18";"10,99";"18,9";"49,27";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,09";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,500";"11,25";"11,10";"15,0";"49,25";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,00";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,600";"11,34";"11,15";"19,2";"49,22";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,88";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,700";"11,37";"11,13";"23,6";"49,20";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,83";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,800";"11,37";"11,09";"28,0";"49,17";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,80";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"670,900";"11,21";"10,89";"32,2";"49,15";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,94";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,000";"11,13";"10,76";"36,5";"49,12";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,99";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,100";"11,19";"10,85";"34,0";"49,10";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,91";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,200";"11,23";"10,92";"31,2";"49,07";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,84";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,300";"11,25";"10,97";"28,2";"49,05";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,80";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,400";"11,38";"11,13";"25,3";"49,02";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,64";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,500";"11,01";"10,80";"21,0";"49,00";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,99";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,600";"11,02";"10,79";"22,7";"48,97";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,95";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,700";"10,88";"10,64";"24,0";"48,95";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,07";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,800";"11,04";"10,78";"26,2";"48,92";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,88";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"671,900";"11,10";"10,96";"28,1";"48,90";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,80";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,000";"11,09";"10,94";"30,0";"48,87";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,78";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,100";"11,53";"11,34";"37,5";"48,86";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,33";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,200";"11,40";"11,18";"43,6";"48,84";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,44";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,300";"11,00";"10,76";"48,6";"48,83";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,83";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,400";"11,16";"10,88";"56,5";"48,81";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,65";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,500";"11,16";"10,84";"64,0";"48,80";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,64";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,600";"11,16";"10,85";"62,8";"48,78";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,62";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,700";"11,12";"10,80";"63,9";"48,77";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,65";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,800";"10,98";"10,66";"64,4";"48,75";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,77";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"672,900";"11,12";"10,79";"66,5";"48,74";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,62";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,000";"10,99";"10,66";"66,9";"48,72";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,73";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,100";"10,87";"10,61";"52,9";"48,70";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,83";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,200";"10,83";"10,63";"40,3";"48,68";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,85";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,300";"10,54";"10,40";"27,7";"48,66";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,12";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,400";"10,54";"10,46";"16,7";"48,64";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"38,10";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,500";"10,68";"10,65";"6,2";"48,62";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,94";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,600";"10,69";"10,69";"0,0";"48,60";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,91";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,700";"10,69";"10,69";"0,0";"48,58";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,89";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,800";"10,64";"10,64";"0,0";"48,56";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,92";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"673,900";"10,79";"10,79";"0,0";"48,54";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,75";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,000";"10,75";"10,75";"0,0";"48,52";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,77";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,100";"10,89";"10,89";"0,0";"48,50";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,61";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,200";"11,11";"11,10";"1,5";"48,48";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,37";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,300";"11,06";"10,95";"21,4";"48,46";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,40";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,400";"11,20";"10,99";"41,2";"48,44";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,24";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,500";"11,24";"10,94";"60,4";"48,42";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,18";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,600";"11,36";"11,05";"62,2";"48,40";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"37,04";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,700";"11,60";"11,28";"64,8";"48,38";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"36,78";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,800";"11,64";"11,31";"66,1";"48,36";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"36,72";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"674,900";"11,68";"11,36";"64,3";"48,34";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"36,66";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+"675,000";"11,47";"11,17";"60,9";"48,32";"10.940";"30.01.1995";"außerh. d. Bez.pegels";"36,85";"NIEDERRHEIN_QP-2004_Epoche_NHN";""
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepthdevelopment/sinfo_fte_01.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,238 @@
+"##Ergebnisausgabe - Elbe - Fließtiefenentwicklung"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: gbelger@localdb"
+"# Datum der Erstellung: 06.06.18"
+"# Gewässer: Elbe"
+"# Höhensystem des Flusses: NHN + m "
+"# Bereich (km): 210,000 - 230,000"
+""
+"Fluss-km";"Fließtiefenentwicklung																			 [m]";"Fließtiefenent-wicklung pro Jahr [cm/a]";"?WSPL [m] (05.05.2008 - 18.03.1997)";"?MSH [m] (FP-QP-2008 - QP-1995)";"Fließtiefe h-aktuell [m] (05.05.2008 - FP-QP-2008)";"Fließtiefe h-historisch [m] (18.03.1997 - QP-1995)";"Lage"
+""
+"##METADATEN PEILUNG aktuell"
+"# Jahr der Peilung: 2008"
+"# Aufnahmeart: Flächen- u. Querprofilpeilungen"
+"# Auswerter: BfG"
+"# Lagesystem: LS 150 und LS 100"
+"# Höhensystem: müNN "
+"# ursprüngliches Höhensystem: müNN"
+""
+"##METADATEN WASSERSPIEGELLAGE aktuell"
+"# Bezeichnung der Wasserspiegellage: 05.05.2008 "
+"# Bezugspegel: Schöna"
+"# Jahr/Zeitraum der Wasserspiegellage: 2008"
+""
+"##METADATEN PEILUNG historisch"
+"# Jahr der Peilung: 1995"
+"# Aufnahmeart: Querprofile"
+"# Auswerter: BfG"
+"# Lagesystem: LS 150"
+"# Höhensystem: müNN "
+"# ursprüngliches Höhensystem: müNN"
+""
+"##METADATEN WASSERSPIEGELLAGE historisch"
+"# Bezeichnung der Wasserspiegellage: 18.03.1997 "
+"# Bezugspegel: Torgau"
+"# Jahr/Zeitraum der Wasserspiegellage: 1997"
+""
+"210,000";"-61,6";"-5,13";"-74,0";"-12,4";"3,82";"4,44";""
+"210,100";"-56,0";"-4,66";"-75,2";"-19,2";"3,64";"4,20";""
+"210,200";"-48,4";"-4,04";"-76,3";"-27,9";"3,65";"4,14";""
+"210,300";"-52,0";"-4,33";"-77,5";"-25,5";"3,58";"4,10";""
+"210,400";"-52,6";"-4,38";"-77,7";"-25,1";"3,58";"4,10";""
+"210,500";"-68,4";"-5,70";"-77,8";"-9,4";"3,54";"4,23";""
+"210,600";"-62,5";"-5,21";"-77,0";"-14,5";"3,77";"4,39";""
+"210,700";"-46,2";"-3,85";"-76,5";"-30,3";"3,98";"4,45";""
+"210,800";"-55,3";"-4,61";"-77,0";"-21,7";"3,97";"4,52";""
+"210,900";"-53,2";"-4,43";"-76,5";"-23,3";"3,99";"4,52";""
+"211,000";"-45,3";"-3,77";"-76,0";"-30,7";"3,94";"4,39";""
+"211,100";"-36,3";"-3,03";"-75,3";"-39,0";"3,84";"4,20";""
+"211,200";"-43,4";"-3,61";"-74,7";"-31,3";"3,88";"4,32";""
+"211,300";"-46,1";"-3,84";"-75,0";"-28,9";"3,93";"4,39";""
+"211,400";"-55,2";"-4,60";"-74,3";"-19,1";"3,67";"4,22";""
+"211,500";"-41,9";"-3,49";"-72,7";"-30,8";"3,71";"4,13";""
+"211,600";"-60,6";"-5,05";"-73,0";"-12,4";"3,59";"4,20";""
+"211,700";"-62,8";"-5,23";"-72,5";"-9,7";"3,58";"4,21";""
+"211,800";"-57,6";"-4,80";"-73,0";"-15,4";"3,45";"4,03";""
+"211,900";"-69,7";"-5,81";"-72,5";"-2,8";"3,38";"4,08";""
+"212,000";"-82,3";"-6,86";"-73,0";"9,3";"3,69";"4,51";""
+"212,100";"-63,1";"-5,26";"-71,0";"-7,9";"4,07";"4,70";""
+"212,200";"-60,7";"-5,06";"-70,0";"-9,3";"3,96";"4,57";""
+"212,300";"-62,9";"-5,24";"-70,0";"-7,1";"3,91";"4,54";""
+"212,400";"-79,4";"-6,62";"-70,0";"9,4";"3,82";"4,62";""
+"212,500";"-86,7";"-7,23";"-72,0";"14,7";"3,85";"4,72";""
+"212,600";"-80,9";"-6,74";"-70,0";"10,9";"3,73";"4,54";""
+"212,700";"-68,1";"-5,68";"-71,5";"-3,4";"3,69";"4,37";""
+"212,800";"-61,2";"-5,10";"-72,0";"-10,8";"3,59";"4,20";""
+"212,900";"-69,1";"-5,76";"-72,5";"-3,4";"3,49";"4,18";""
+"213,000";"-62,0";"-5,17";"-72,0";"-10,0";"3,69";"4,31";""
+"213,100";"-57,7";"-4,81";"-72,0";"-14,3";"3,67";"4,25";""
+"213,200";"-60,5";"-5,04";"-73,0";"-12,5";"3,70";"4,30";""
+"213,300";"-67,2";"-5,60";"-73,0";"-5,8";"3,70";"4,37";""
+"213,400";"-69,3";"-5,78";"-73,0";"-3,7";"3,76";"4,46";""
+"213,500";"-73,9";"-6,16";"-73,0";"0,9";"3,85";"4,59";""
+"213,600";"-77,9";"-6,49";"-72,0";"5,9";"4,02";"4,80";""
+"213,700";"-61,7";"-5,14";"-71,3";"-9,6";"4,14";"4,75";""
+"213,800";"-112,8";"-9,40";"-72,4";"40,4";"4,12";"5,25";""
+"213,900";"-96,0";"-8,00";"-72,8";"23,2";"4,04";"5,00";""
+"214,000";"-84,2";"-7,02";"-73,0";"11,2";"4,07";"4,92";""
+"214,100";"-87,2";"-7,27";"-70,5";"16,7";"4,02";"4,89";""
+"214,200";"-87,5";"-7,29";"-70,7";"16,8";"4,03";"4,90";""
+"214,300";"-76,8";"-6,40";"-70,0";"6,8";"4,04";"4,81";""
+"214,400";"-69,7";"-5,81";"-70,3";"-0,6";"4,06";"4,76";""
+"214,500";"-60,0";"-5,00";"-70,7";"-10,7";"3,96";"4,56";""
+"214,600";"-73,5";"-6,12";"-71,0";"2,5";"3,85";"4,59";""
+"214,700";"-72,3";"-6,02";"-71,0";"1,3";"3,72";"4,45";""
+"214,800";"-83,8";"-6,98";"-71,0";"12,8";"3,80";"4,64";"Schwebstoffmessstelle: Wittenberg"
+"214,900";"-73,6";"-6,13";"-70,0";"3,6";"3,83";"4,57";""
+"215,000";"-50,6";"-4,22";"-70,0";"-19,4";"3,92";"4,42";""
+"215,100";"-37,5";"-3,13";"-72,0";"-34,5";"3,97";"4,35";""
+"215,200";"-52,1";"-4,34";"-72,0";"-19,9";"3,96";"4,49";""
+"215,300";"-60,2";"-5,02";"-71,0";"-10,8";"3,82";"4,42";""
+"215,400";"-55,5";"-4,63";"-71,0";"-15,5";"3,83";"4,39";""
+"215,500";"-57,6";"-4,80";"-71,0";"-13,4";"3,84";"4,41";""
+"215,600";"-58,5";"-4,87";"-70,0";"-11,5";"3,93";"4,52";""
+"215,700";"-66,6";"-5,55";"-70,3";"-3,6";"3,86";"4,53";""
+"215,800";"-64,5";"-5,38";"-71,5";"-7,0";"3,74";"4,38";""
+"215,900";"-60,5";"-5,05";"-71,8";"-11,2";"3,80";"4,41";""
+"216,000";"-62,4";"-5,20";"-71,0";"-8,6";"3,85";"4,48";""
+"216,100";"-73,4";"-6,11";"-70,2";"3,2";"3,74";"4,48";""
+"216,200";"-71,7";"-5,98";"-70,3";"1,4";"3,84";"4,56";""
+"216,300";"-63,5";"-5,29";"-70,5";"-7,0";"3,81";"4,44";""
+"216,400";"-63,2";"-5,26";"-69,7";"-6,5";"3,72";"4,35";"Hafen: Wittenberg -Schutz- und Sicherheitshafen"
+"216,500";"-75,4";"-6,29";"-69,8";"5,6";"3,52";"4,28";""
+"216,600";"-72,9";"-6,07";"-69,0";"3,9";"3,70";"4,43";""
+"216,700";"-64,2";"-5,35";"-68,5";"-4,3";"3,84";"4,48";""
+"216,800";"-72,1";"-6,01";"-71,0";"1,1";"3,66";"4,39";""
+"216,900";"-68,5";"-5,71";"-70,5";"-2,0";"3,63";"4,32";""
+"217,000";"-66,5";"-5,54";"-70,0";"-3,5";"3,64";"4,30";""
+"217,100";"-72,3";"-6,03";"-70,3";"2,0";"3,52";"4,25";""
+"217,200";"-80,4";"-6,70";"-69,7";"10,7";"3,43";"4,23";""
+"217,300";"-68,8";"-5,73";"-70,0";"-1,2";"3,30";"3,98";""
+"217,400";"-81,1";"-6,76";"-71,3";"9,8";"3,17";"3,98";""
+"217,500";"-78,0";"-6,50";"-73,7";"4,3";"3,47";"4,25";""
+"217,600";"-87,6";"-7,30";"-74,0";"13,6";"3,56";"4,43";""
+"217,700";"-75,1";"-6,26";"-73,5";"1,6";"3,51";"4,27";""
+"217,800";"-86,7";"-7,23";"-73,0";"13,7";"3,33";"4,20";""
+"217,900";"-56,0";"-4,67";"-73,5";"-17,5";"3,71";"4,27";""
+"218,000";"-59,7";"-4,97";"-74,0";"-14,3";"4,14";"4,74";""
+"218,100";"-53,9";"-4,49";"-73,7";"-19,8";"4,16";"4,69";""
+"218,200";"-60,4";"-5,04";"-74,3";"-13,9";"4,23";"4,83";""
+"218,300";"-76,8";"-6,40";"-74,0";"2,8";"4,10";"4,87";""
+"218,400";"-72,0";"-6,00";"-73,7";"-1,7";"4,23";"4,95";""
+"218,500";"-76,5";"-6,38";"-73,3";"3,2";"4,28";"5,04";""
+"218,600";"-74,4";"-6,20";"-74,0";"0,4";"4,10";"4,84";""
+"218,700";"-69,9";"-5,82";"-72,8";"-2,9";"4,20";"4,90";""
+"218,800";"-77,5";"-6,46";"-72,5";"5,0";"4,16";"4,93";""
+"218,900";"-84,2";"-7,02";"-74,2";"10,0";"4,10";"4,94";""
+"219,000";"-82,7";"-6,89";"-76,0";"6,7";"4,04";"4,87";""
+"219,100";"-81,7";"-6,81";"-75,8";"5,9";"3,80";"4,62";""
+"219,200";"-84,0";"-7,00";"-74,7";"9,3";"3,63";"4,47";""
+"219,300";"-81,3";"-6,77";"-74,5";"6,8";"3,61";"4,43";""
+"219,400";"-73,9";"-6,16";"-74,3";"-0,4";"3,55";"4,29";""
+"219,500";"-85,9";"-7,16";"-73,2";"12,7";"3,53";"4,39";""
+"219,600";"-98,8";"-8,23";"-73,0";"25,8";"3,79";"4,78";""
+"219,700";"-99,7";"-8,31";"-72,5";"27,2";"4,02";"5,02";""
+"219,800";"-80,7";"-6,73";"-71,0";"9,7";"3,94";"4,75";""
+"219,900";"-92,9";"-7,74";"-70,5";"22,4";"3,92";"4,85";""
+"220,000";"-94,2";"-7,85";"-71,0";"23,2";"4,00";"4,94";""
+"220,100";"-113,9";"-9,49";"-70,2";"43,7";"3,90";"5,04";""
+"220,200";"-102,2";"-8,52";"-70,3";"31,9";"4,04";"5,07";""
+"220,300";"-84,5";"-7,04";"-70,5";"14,0";"4,01";"4,85";""
+"220,400";"-98,8";"-8,23";"-70,7";"28,1";"3,78";"4,77";""
+"220,500";"-107,0";"-8,92";"-70,8";"36,2";"3,59";"4,66";""
+"220,600";"-101,6";"-8,47";"-71,0";"30,6";"3,38";"4,40";""
+"220,700";"-92,5";"-7,70";"-69,8";"22,7";"3,52";"4,45";""
+"220,800";"-88,9";"-7,41";"-69,5";"19,4";"3,32";"4,21";""
+"220,900";"-85,3";"-7,10";"-69,3";"16,0";"3,23";"4,09";""
+"221,000";"-78,7";"-6,56";"-70,0";"8,7";"3,17";"3,96";""
+"221,100";"-78,6";"-6,55";"-70,0";"8,6";"3,12";"3,91";""
+"221,200";"-71,3";"-5,94";"-70,0";"1,3";"3,14";"3,86";""
+"221,300";"-59,7";"-4,97";"-71,0";"-11,3";"3,36";"3,96";""
+"221,400";"-66,3";"-5,52";"-71,0";"-4,7";"3,32";"3,99";""
+"221,500";"-65,1";"-5,42";"-72,0";"-6,9";"3,24";"3,89";""
+"221,600";"-59,4";"-4,95";"-73,0";"-13,6";"3,28";"3,87";""
+"221,700";"-45,1";"-3,76";"-73,0";"-27,9";"3,35";"3,80";""
+"221,800";"-48,4";"-4,03";"-74,0";"-25,6";"3,25";"3,73";""
+"221,900";"-53,8";"-4,48";"-74,0";"-20,2";"3,28";"3,81";""
+"222,000";"-61,4";"-5,12";"-73,0";"-11,6";"3,44";"4,05";""
+"222,100";"-82,7";"-6,89";"-73,0";"9,7";"3,78";"4,61";""
+"222,200";"-71,0";"-5,92";"-73,0";"-2,0";"3,94";"4,65";""
+"222,300";"-57,3";"-4,77";"-73,0";"-15,7";"4,13";"4,70";""
+"222,400";"-65,1";"-5,42";"-73,0";"-7,9";"4,13";"4,78";""
+"222,500";"-75,8";"-6,32";"-73,0";"2,8";"3,97";"4,72";""
+"222,600";"-111,8";"-9,32";"-72,0";"39,8";"3,84";"4,96";""
+"222,700";"-125,7";"-10,47";"-72,0";"53,7";"3,77";"5,03";""
+"222,800";"-112,3";"-9,36";"-72,0";"40,3";"3,73";"4,85";""
+"222,900";"-106,9";"-8,91";"-71,0";"35,9";"3,67";"4,74";""
+"223,000";"-98,4";"-8,20";"-71,0";"27,4";"3,59";"4,57";""
+"223,100";"-63,8";"-5,31";"-72,7";"-8,9";"3,54";"4,18";""
+"223,200";"-55,9";"-4,66";"-74,3";"-18,4";"3,76";"4,32";""
+"223,300";"-51,4";"-4,28";"-74,0";"-22,6";"3,78";"4,30";""
+"223,400";"-58,8";"-4,90";"-72,7";"-13,9";"3,74";"4,32";""
+"223,500";"-85,3";"-7,11";"-71,3";"14,0";"3,77";"4,62";""
+"223,600";"-106,9";"-8,91";"-70,0";"36,9";"3,83";"4,90";""
+"223,700";"-124,8";"-10,40";"-71,5";"53,3";"4,00";"5,25";""
+"223,800";"-127,3";"-10,61";"-73,0";"54,3";"4,05";"5,32";""
+"223,900";"-79,1";"-6,59";"-71,5";"7,6";"3,95";"4,74";""
+"224,000";"-76,6";"-6,38";"-71,0";"5,6";"3,75";"4,52";""
+"224,100";"-69,7";"-5,81";"-70,2";"-0,5";"3,66";"4,36";""
+"224,200";"-72,7";"-6,06";"-70,3";"2,4";"3,84";"4,57";""
+"224,300";"-54,8";"-4,57";"-70,5";"-15,7";"4,10";"4,65";""
+"224,400";"-26,6";"-2,21";"-69,7";"-43,1";"3,90";"4,16";""
+"224,500";"-52,3";"-4,36";"-68,8";"-16,5";"3,51";"4,03";""
+"224,600";"-83,4";"-6,95";"-68,0";"15,4";"3,27";"4,11";""
+"224,700";"-77,1";"-6,42";"-67,2";"9,8";"3,27";"4,04";""
+"224,800";"-63,0";"-5,25";"-67,5";"-4,5";"3,25";"3,87";""
+"224,900";"-75,3";"-6,28";"-67,7";"7,6";"3,45";"4,20";""
+"225,000";"-54,3";"-4,52";"-68,0";"-13,7";"3,53";"4,07";""
+"225,100";"-68,8";"-5,73";"-70,7";"-1,9";"3,35";"4,04";""
+"225,200";"-66,2";"-5,52";"-71,3";"-5,1";"3,19";"3,86";""
+"225,300";"-65,5";"-5,46";"-72,0";"-6,5";"3,25";"3,91";""
+"225,400";"-85,6";"-7,13";"-72,7";"12,9";"3,37";"4,23";""
+"225,500";"-105,4";"-8,79";"-72,3";"33,1";"3,33";"4,38";""
+"225,600";"-87,7";"-7,31";"-72,0";"15,7";"3,38";"4,25";""
+"225,700";"-102,6";"-8,55";"-71,8";"30,8";"3,20";"4,22";""
+"225,800";"-114,3";"-9,53";"-71,5";"42,8";"3,38";"4,53";""
+"225,900";"-128,6";"-10,71";"-72,3";"56,3";"3,77";"5,05";""
+"226,000";"-132,8";"-11,07";"-72,0";"60,8";"4,10";"5,43";""
+"226,100";"-135,9";"-11,33";"-70,5";"65,4";"4,14";"5,50";""
+"226,200";"-109,9";"-9,16";"-71,0";"38,9";"4,34";"5,44";""
+"226,300";"-92,7";"-7,72";"-72,5";"20,2";"4,16";"5,08";""
+"226,400";"-82,1";"-6,84";"-72,0";"10,1";"4,14";"4,96";""
+"226,500";"-109,9";"-9,16";"-72,5";"37,4";"4,16";"5,26";""
+"226,600";"-112,4";"-9,37";"-73,0";"39,4";"4,17";"5,30";""
+"226,700";"-91,6";"-7,63";"-73,5";"18,1";"3,99";"4,91";""
+"226,800";"-73,0";"-6,08";"-73,0";"0,0";"3,94";"4,67";""
+"226,900";"-78,9";"-6,57";"-74,5";"4,4";"3,83";"4,62";""
+"227,000";"-88,5";"-7,38";"-74,0";"14,5";"3,79";"4,68";""
+"227,100";"-77,3";"-6,44";"-74,7";"2,6";"3,80";"4,57";""
+"227,200";"-69,3";"-5,78";"-73,3";"-4,0";"3,74";"4,43";""
+"227,300";"-37,3";"-3,11";"-73,0";"-35,7";"3,75";"4,13";""
+"227,400";"-50,4";"-4,20";"-73,7";"-23,3";"3,75";"4,25";""
+"227,500";"-71,2";"-5,94";"-74,3";"-3,1";"3,65";"4,36";""
+"227,600";"-75,6";"-6,30";"-73,0";"2,6";"3,62";"4,38";""
+"227,700";"-73,2";"-6,10";"-74,2";"-1,0";"3,63";"4,37";""
+"227,800";"-61,5";"-5,12";"-75,5";"-14,0";"3,53";"4,14";""
+"227,900";"-88,5";"-7,38";"-74,7";"13,8";"3,42";"4,31";""
+"228,000";"-75,8";"-6,32";"-76,0";"-0,2";"3,59";"4,35";""
+"228,100";"-63,4";"-5,28";"-76,2";"-12,8";"3,55";"4,19";""
+"228,200";"-54,2";"-4,52";"-74,3";"-20,1";"3,78";"4,32";""
+"228,300";"-52,7";"-4,39";"-75,5";"-22,8";"3,95";"4,47";""
+"228,400";"-56,5";"-4,71";"-75,7";"-19,2";"4,20";"4,77";""
+"228,500";"-67,3";"-5,61";"-75,8";"-8,5";"4,03";"4,70";""
+"228,600";"-61,0";"-5,08";"-74,0";"-13,0";"4,09";"4,70";""
+"228,700";"-88,0";"-7,33";"-74,0";"14,0";"3,75";"4,63";""
+"228,800";"-84,1";"-7,01";"-72,0";"12,1";"3,92";"4,76";""
+"228,900";"-91,9";"-7,66";"-69,0";"22,9";"3,60";"4,52";""
+"229,000";"-89,7";"-7,47";"-68,0";"21,7";"3,52";"4,42";""
+"229,100";"-98,9";"-8,24";"-67,8";"31,1";"3,47";"4,46";""
+"229,200";"-73,0";"-6,08";"-66,7";"6,3";"3,86";"4,59";""
+"229,300";"-63,1";"-5,26";"-67,5";"-4,4";"4,00";"4,63";""
+"229,400";"-75,5";"-6,29";"-68,3";"7,2";"3,89";"4,64";""
+"229,500";"-86,3";"-7,19";"-69,2";"17,1";"3,55";"4,41";""
+"229,600";"-77,7";"-6,47";"-70,0";"7,7";"3,52";"4,30";""
+"229,700";"-75,1";"-6,25";"-70,8";"4,3";"3,52";"4,27";""
+"229,800";"-79,8";"-6,65";"-72,5";"7,3";"3,47";"4,26";""
+"229,900";"-79,1";"-6,59";"-73,3";"5,8";"3,54";"4,33";""
+"230,000";"-52,2";"-4,35";"-72,0";"-19,8";"3,95";"4,47";""
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepthdevelopment/sinfo_fte_02.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,138 @@
+"##Ergebnisausgabe - Rhein - Fließtiefenentwicklung"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: gbelger@localdb"
+"# Datum der Erstellung: 06.06.18"
+"# Gewässer: Rhein"
+"# Höhensystem des Flusses: NHN + m "
+"# Bereich (km): 655,000 - 665,000"
+""
+"Fluss-km";"Fließtiefenentwicklung																			 [m]";"Fließtiefenent-wicklung pro Jahr [cm/a]";"?WSPL [m] (23.09.2009-1 - 23.09.1991)";"?MSH [m] (NIEDERRHEIN_QP-2008_Epoche_NHN - NIEDERRHEIN_QP-1991_Epoche_NHN)";"Fließtiefe h-aktuell [m] (23.09.2009-1 - NIEDERRHEIN_QP-2008_Epoche_NHN)";"Fließtiefe h-historisch [m] (23.09.1991 - NIEDERRHEIN_QP-1991_Epoche_NHN)";"Lage"
+""
+"##METADATEN PEILUNG aktuell"
+"# Jahr der Peilung: 2008"
+"# Aufnahmeart: Querprofile"
+"# Auswerter: WSA Duisburg (Abel)"
+"# Lagesystem: LS unbekannt"
+"# Höhensystem: müNHN "
+"# ursprüngliches Höhensystem: müNHN"
+""
+"##METADATEN WASSERSPIEGELLAGE aktuell"
+"# Bezeichnung der Wasserspiegellage: 23.09.2009-1 "
+"# Bezugspegel: Bonn"
+"# Jahr/Zeitraum der Wasserspiegellage: 2009"
+""
+"##METADATEN PEILUNG historisch"
+"# Jahr der Peilung: 1991"
+"# Aufnahmeart: Querprofile"
+"# Auswerter: WSA Duisburg (Abel)"
+"# Lagesystem: LS unbekannt"
+"# Höhensystem: müNHN "
+"# ursprüngliches Höhensystem: müNHN"
+""
+"##METADATEN WASSERSPIEGELLAGE historisch"
+"# Bezeichnung der Wasserspiegellage: 23.09.1991 "
+"# Bezugspegel: Bonn"
+"# Jahr/Zeitraum der Wasserspiegellage: 1991"
+""
+"655,000";"36,0";"2,12";"27,0";"-9,0";"2,47";"2,11";""
+"655,100";"31,0";"1,82";"27,0";"-4,0";"2,40";"2,09";""
+"655,200";"18,0";"1,06";"26,0";"8,0";"2,20";"2,02";""
+"655,300";"8,0";"0,47";"26,0";"18,0";"2,20";"2,12";""
+"655,400";"14,0";"0,82";"25,0";"11,0";"2,25";"2,11";""
+"655,500";"12,0";"0,71";"25,0";"13,0";"2,17";"2,05";""
+"655,600";"25,0";"1,47";"25,0";"0,0";"2,19";"1,94";""
+"655,700";"40,0";"2,35";"23,0";"-17,0";"2,11";"1,71";""
+"655,800";"43,0";"2,53";"23,0";"-20,0";"2,15";"1,72";""
+"655,900";"48,0";"2,82";"22,0";"-26,0";"2,27";"1,79";""
+"656,000";"46,0";"2,71";"23,0";"-23,0";"2,38";"1,92";""
+"656,100";"45,0";"2,65";"23,0";"-22,0";"2,59";"2,14";""
+"656,200";"39,0";"2,29";"23,0";"-16,0";"2,72";"2,33";""
+"656,300";"38,0";"2,24";"23,0";"-15,0";"2,92";"2,54";""
+"656,400";"31,0";"1,82";"22,0";"-9,0";"2,91";"2,60";""
+"656,500";"23,0";"1,35";"20,0";"-3,0";"2,99";"2,76";""
+"656,600";"27,0";"1,59";"20,0";"-7,0";"2,80";"2,53";""
+"656,700";"30,0";"1,76";"20,0";"-10,0";"3,17";"2,87";""
+"656,800";"33,0";"1,94";"20,0";"-13,0";"3,29";"2,96";""
+"656,900";"36,0";"2,12";"21,0";"-15,0";"3,30";"2,94";""
+"657,000";"40,0";"2,35";"21,0";"-19,0";"3,30";"2,90";""
+"657,100";"52,0";"3,06";"23,0";"-29,0";"3,36";"2,84";""
+"657,200";"51,0";"3,00";"25,0";"-26,0";"3,52";"3,01";""
+"657,300";"61,0";"3,59";"24,0";"-37,0";"3,41";"2,80";""
+"657,400";"51,0";"3,00";"23,0";"-28,0";"3,59";"3,08";""
+"657,500";"38,0";"2,24";"24,0";"-14,0";"3,58";"3,20";""
+"657,600";"45,0";"2,65";"25,0";"-20,0";"3,32";"2,87";""
+"657,700";"58,0";"3,41";"26,0";"-32,0";"3,26";"2,68";""
+"657,800";"54,0";"3,18";"26,0";"-28,0";"3,08";"2,54";""
+"657,900";"68,0";"4,00";"26,0";"-42,0";"3,17";"2,49";""
+"658,000";"62,0";"3,65";"26,0";"-36,0";"3,12";"2,50";""
+"658,100";"62,0";"3,65";"26,0";"-36,0";"3,16";"2,54";""
+"658,200";"41,0";"2,41";"26,0";"-15,0";"3,18";"2,77";""
+"658,300";"45,0";"2,65";"27,0";"-18,0";"3,35";"2,90";""
+"658,400";"27,0";"1,59";"26,0";"-1,0";"3,35";"3,08";""
+"658,500";"24,0";"1,41";"25,0";"1,0";"3,23";"2,99";""
+"658,600";"25,0";"1,47";"25,0";"0,0";"3,55";"3,30";""
+"658,700";"17,0";"1,00";"27,0";"10,0";"3,57";"3,40";""
+"658,800";"18,0";"1,06";"27,0";"9,0";"3,78";"3,60";""
+"658,900";"5,0";"0,29";"26,0";"21,0";"4,07";"4,02";""
+"659,000";"34,0";"2,00";"24,0";"-10,0";"3,75";"3,41";""
+"659,100";"37,0";"2,18";"21,0";"-16,0";"4,01";"3,64";""
+"659,200";"35,0";"2,06";"20,0";"-15,0";"3,98";"3,63";""
+"659,300";"49,0";"2,88";"20,0";"-29,0";"3,83";"3,34";""
+"659,400";"41,0";"2,41";"19,0";"-22,0";"3,55";"3,14";""
+"659,500";"35,0";"2,06";"18,0";"-17,0";"3,40";"3,05";""
+"659,600";"6,0";"0,35";"18,0";"12,0";"3,38";"3,32";""
+"659,700";"-1,0";"-0,06";"18,0";"19,0";"3,21";"3,22";""
+"659,800";"-5,0";"-0,29";"18,0";"23,0";"2,97";"3,02";""
+"659,900";"-21,0";"-1,24";"17,0";"38,0";"2,88";"3,09";""
+"660,000";"-23,0";"-1,35";"16,0";"39,0";"3,03";"3,26";""
+"660,100";"-28,0";"-1,65";"17,0";"45,0";"3,16";"3,44";"Geschiebemessstelle: Mondorf"
+"660,200";"-6,0";"-0,35";"18,0";"24,0";"3,19";"3,25";""
+"660,300";"-13,0";"-0,76";"19,0";"32,0";"3,16";"3,29";""
+"660,400";"11,0";"0,65";"20,0";"9,0";"2,92";"2,81";""
+"660,500";"13,0";"0,76";"19,0";"6,0";"2,76";"2,63";""
+"660,600";"29,0";"1,71";"18,0";"-11,0";"2,57";"2,28";""
+"660,700";"9,0";"0,53";"17,0";"8,0";"2,55";"2,46";""
+"660,800";"17,0";"1,00";"16,0";"-1,0";"2,51";"2,34";""
+"660,900";"11,0";"0,65";"12,0";"1,0";"2,50";"2,39";""
+"661,000";"15,0";"0,88";"13,0";"-2,0";"2,56";"2,41";""
+"661,100";"19,0";"1,12";"15,0";"-4,0";"2,51";"2,32";""
+"661,200";"34,0";"2,00";"16,0";"-18,0";"2,68";"2,34";""
+"661,300";"38,0";"2,24";"17,0";"-21,0";"2,85";"2,47";""
+"661,400";"42,0";"2,47";"17,0";"-25,0";"3,02";"2,60";""
+"661,500";"46,0";"2,71";"19,0";"-27,0";"2,97";"2,51";""
+"661,600";"51,0";"3,00";"20,0";"-31,0";"2,69";"2,18";""
+"661,700";"51,0";"3,00";"21,0";"-30,0";"2,53";"2,02";""
+"661,800";"50,0";"2,94";"22,0";"-28,0";"2,62";"2,12";""
+"661,900";"51,0";"3,00";"22,0";"-29,0";"2,59";"2,08";""
+"662,000";"40,0";"2,35";"22,0";"-18,0";"2,46";"2,06";""
+"662,100";"51,0";"3,00";"24,0";"-27,0";"2,39";"1,88";""
+"662,200";"54,0";"3,18";"25,0";"-29,0";"2,49";"1,95";""
+"662,300";"58,0";"3,41";"24,0";"-34,0";"2,46";"1,88";""
+"662,400";"56,0";"3,29";"22,0";"-34,0";"2,69";"2,13";""
+"662,500";"51,0";"3,00";"24,0";"-27,0";"2,19";"1,68";""
+"662,600";"51,0";"3,00";"25,0";"-26,0";"2,13";"1,62";""
+"662,700";"62,0";"3,65";"25,0";"-37,0";"2,34";"1,72";""
+"662,800";"64,0";"3,76";"26,0";"-38,0";"2,49";"1,85";""
+"662,900";"64,0";"3,76";"28,0";"-36,0";"2,31";"1,67";""
+"663,000";"58,0";"3,41";"30,0";"-28,0";"2,25";"1,67";""
+"663,100";"49,0";"2,88";"31,0";"-18,0";"2,37";"1,88";""
+"663,200";"44,0";"2,59";"30,0";"-14,0";"2,40";"1,96";""
+"663,300";"41,0";"2,41";"29,0";"-12,0";"2,32";"1,91";""
+"663,400";"36,0";"2,12";"28,0";"-8,0";"2,49";"2,13";""
+"663,500";"29,0";"1,71";"26,0";"-3,0";"2,59";"2,30";""
+"663,600";"34,0";"2,00";"24,0";"-10,0";"2,78";"2,44";""
+"663,700";"34,0";"2,00";"23,0";"-11,0";"2,70";"2,36";""
+"663,800";"37,0";"2,18";"24,0";"-13,0";"2,32";"1,95";""
+"663,900";"34,0";"2,00";"24,0";"-10,0";"2,40";"2,06";""
+"664,000";"34,0";"2,00";"22,0";"-12,0";"2,62";"2,28";""
+"664,100";"27,0";"1,59";"22,0";"-5,0";"2,86";"2,59";""
+"664,200";"33,0";"1,94";"22,0";"-11,0";"3,14";"2,81";""
+"664,300";"34,0";"2,00";"21,0";"-13,0";"2,77";"2,43";""
+"664,400";"19,0";"1,12";"22,0";"3,0";"3,17";"2,98";""
+"664,500";"13,0";"0,76";"22,0";"9,0";"2,93";"2,80";""
+"664,600";"17,0";"1,00";"22,0";"5,0";"2,89";"2,72";""
+"664,700";"20,0";"1,18";"22,0";"2,0";"3,14";"2,94";""
+"664,800";"23,0";"1,35";"22,0";"-1,0";"3,21";"2,98";""
+"664,900";"20,0";"1,18";"22,0";"2,0";"3,03";"2,83";""
+"665,000";"28,0";"1,65";"22,0";"-6,0";"3,00";"2,72";""
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepthminmax/sinfo_minmaxft_01.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,225 @@
+"##Ergebnisausgabe - Rhein - Minimale und Maximale Fließtiefe"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: f"
+"# Datum der Erstellung: 14.06.18"
+"# Gewässer: Rhein"
+"# Höhensystem des Flusses: Wasssers[NN "
+"# Bereich (km): 430,000 - 450,000"
+""
+"Fluss-km";"Minimale Fließtiefe [m]";"Maximale Fließtiefe [m]";"Wasserstand [Wasssers[NN]";"Q [m³/s]";"Bezeichnung";"Bezugspegel";"Mittlere Sohlhöhe [Wasssers[NN]";"Peilung/Epoche";"Lage"
+""
+"##METADATEN PEILUNG"
+"# Jahr der Peilung: 2004"
+"# Aufnahmeart: DGM"
+"# Auswerter: BfG"
+"# Lagesystem: DHDN_Bessel_GK3"
+"# Höhensystem: müNHN "
+"# ursprüngliches Höhensystem: müNHN"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: Amtl.Festlegung_GlQ(2002) "
+"# Bezugspegel: außerh. d. Bez.pegels"
+"# Jahr/Zeitraum der Wasserspiegellage: 2002"
+""
+"430,000";"2,84";"3,37";"86,14";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,00";"DGM-2004_Epoche_NHN";""
+"430,100";"2,78";"3,37";"86,13";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,03";"DGM-2004_Epoche_NHN";""
+"430,200";"2,84";"3,35";"86,11";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,02";"DGM-2004_Epoche_NHN";""
+"430,300";"2,78";"3,34";"86,10";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,04";"DGM-2004_Epoche_NHN";""
+"430,400";"2,77";"3,35";"86,09";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,03";"DGM-2004_Epoche_NHN";""
+"430,500";"2,71";"3,41";"86,08";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,06";"DGM-2004_Epoche_NHN";""
+"430,600";"2,75";"3,52";"86,07";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,06";"DGM-2004_Epoche_NHN";""
+"430,700";"2,70";"3,58";"86,06";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,03";"DGM-2004_Epoche_NHN";""
+"430,800";"2,66";"3,61";"86,05";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,02";"DGM-2004_Epoche_NHN";""
+"430,900";"2,67";"3,56";"86,04";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,04";"DGM-2004_Epoche_NHN";""
+"431,000";"2,63";"3,62";"86,02";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,02";"DGM-2004_Epoche_NHN";""
+"431,100";"2,63";"3,63";"86,02";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,00";"DGM-2004_Epoche_NHN";""
+"431,200";"2,66";"3,59";"86,01";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,97";"DGM-2004_Epoche_NHN";""
+"431,300";"2,66";"3,37";"86,00";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,01";"DGM-2004_Epoche_NHN";""
+"431,400";"2,70";"3,13";"85,99";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,08";"DGM-2004_Epoche_NHN";"Hafen: Altrheinhafen 31 -Ölhafen, -Schutzhafen"
+"431,500";"2,73";"3,15";"85,98";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"83,06";"DGM-2004_Epoche_NHN";""
+"431,600";"2,75";"3,26";"85,96";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,97";"DGM-2004_Epoche_NHN";""
+"431,700";"2,87";"3,42";"85,96";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,80";"DGM-2004_Epoche_NHN";""
+"431,800";"2,85";"3,58";"85,94";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,63";"DGM-2004_Epoche_NHN";""
+"431,900";"3,24";"4,02";"85,93";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,36";"DGM-2004_Epoche_NHN";""
+"432,000";"3,20";"4,38";"85,91";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,13";"DGM-2004_Epoche_NHN";"Hafen: Handelshafen -Schutzhafen"
+"432,100";"3,37";"4,68";"85,90";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,86";"DGM-2004_Epoche_NHN";""
+"432,200";"3,61";"5,14";"85,89";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,57";"DGM-2004_Epoche_NHN";""
+"432,300";"3,62";"5,43";"85,89";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,31";"DGM-2004_Epoche_NHN";""
+"432,400";"3,45";"5,65";"85,88";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,18";"DGM-2004_Epoche_NHN";""
+"432,500";"3,29";"5,95";"85,86";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,11";"DGM-2004_Epoche_NHN";""
+"432,600";"3,00";"5,52";"85,85";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,21";"DGM-2004_Epoche_NHN";"Brücke: Theodor-Heuss-Brücke -Autobahn"
+"432,700";"2,68";"5,47";"85,84";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,34";"DGM-2004_Epoche_NHN";""
+"432,800";"2,64";"5,01";"85,84";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,55";"DGM-2004_Epoche_NHN";""
+"432,900";"2,99";"4,60";"85,83";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,71";"DGM-2004_Epoche_NHN";""
+"433,000";"2,73";"4,40";"85,82";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,84";"DGM-2004_Epoche_NHN";""
+"433,100";"3,29";"4,14";"85,81";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,95";"DGM-2004_Epoche_NHN";""
+"433,200";"3,30";"4,61";"85,80";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,82";"DGM-2004_Epoche_NHN";""
+"433,300";"2,46";"4,93";"85,79";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,58";"DGM-2004_Epoche_NHN";""
+"433,400";"2,30";"5,03";"85,78";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,48";"DGM-2004_Epoche_NHN";""
+"433,500";"2,22";"5,02";"85,77";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,45";"DGM-2004_Epoche_NHN";""
+"433,600";"1,76";"4,97";"85,76";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,45";"DGM-2004_Epoche_NHN";""
+"433,700";"1,76";"5,19";"85,75";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,29";"DGM-2004_Epoche_NHN";""
+"433,800";"2,08";"5,38";"85,73";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,05";"DGM-2004_Epoche_NHN";""
+"433,900";"1,64";"5,73";"85,73";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,80";"DGM-2004_Epoche_NHN";""
+"434,000";"0,88";"5,88";"85,71";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,99";"DGM-2004_Epoche_NHN";""
+"434,100";"1,10";"5,67";"85,70";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,98";"DGM-2004_Epoche_NHN";""
+"434,200";"2,50";"5,62";"85,69";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,95";"DGM-2004_Epoche_NHN";""
+"434,300";"2,32";"5,48";"85,68";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,02";"DGM-2004_Epoche_NHN";""
+"434,400";"2,72";"5,28";"85,67";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,11";"DGM-2004_Epoche_NHN";""
+"434,500";"2,81";"5,42";"85,66";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,02";"DGM-2004_Epoche_NHN";""
+"434,600";"2,61";"5,33";"85,65";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,08";"DGM-2004_Epoche_NHN";""
+"434,700";"2,70";"5,20";"85,64";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,14";"DGM-2004_Epoche_NHN";""
+"434,800";"2,36";"4,96";"85,63";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,32";"DGM-2004_Epoche_NHN";""
+"434,900";"2,25";"4,87";"85,62";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,56";"DGM-2004_Epoche_NHN";""
+"435,000";"2,36";"4,61";"85,61";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,81";"DGM-2004_Epoche_NHN";""
+"435,100";"2,63";"4,26";"85,60";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,96";"DGM-2004_Epoche_NHN";""
+"435,200";"3,04";"4,03";"85,59";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,94";"DGM-2004_Epoche_NHN";""
+"435,300";"3,42";"3,99";"85,58";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,91";"DGM-2004_Epoche_NHN";""
+"435,400";"3,19";"4,18";"85,57";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,88";"DGM-2004_Epoche_NHN";""
+"435,500";"2,90";"4,39";"85,56";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,88";"DGM-2004_Epoche_NHN";""
+"435,600";"2,71";"4,48";"85,55";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,84";"DGM-2004_Epoche_NHN";""
+"435,700";"2,71";"5,07";"85,55";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,60";"DGM-2004_Epoche_NHN";""
+"435,800";"2,73";"5,33";"85,53";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,34";"DGM-2004_Epoche_NHN";""
+"435,900";"2,99";"5,14";"85,52";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,21";"DGM-2004_Epoche_NHN";""
+"436,000";"2,82";"4,81";"85,51";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,25";"DGM-2004_Epoche_NHN";""
+"436,100";"3,18";"4,82";"85,51";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,33";"DGM-2004_Epoche_NHN";""
+"436,200";"3,11";"4,91";"85,50";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,32";"DGM-2004_Epoche_NHN";""
+"436,300";"2,98";"5,00";"85,49";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,40";"DGM-2004_Epoche_NHN";""
+"436,400";"2,82";"4,99";"85,48";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,32";"DGM-2004_Epoche_NHN";""
+"436,500";"2,79";"5,27";"85,47";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,21";"DGM-2004_Epoche_NHN";""
+"436,600";"2,80";"5,25";"85,47";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,18";"DGM-2004_Epoche_NHN";""
+"436,700";"2,85";"5,18";"85,47";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,21";"DGM-2004_Epoche_NHN";""
+"436,800";"2,90";"5,10";"85,46";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,23";"DGM-2004_Epoche_NHN";""
+"436,900";"2,96";"5,03";"85,46";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,25";"DGM-2004_Epoche_NHN";""
+"437,000";"3,01";"4,96";"85,46";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,26";"DGM-2004_Epoche_NHN";"Bundesland: Hessen"
+"437,100";"2,87";"5,29";"85,46";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,21";"DGM-2004_Epoche_NHN";""
+"437,200";"2,83";"5,31";"85,45";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,08";"DGM-2004_Epoche_NHN";""
+"437,300";"2,69";"5,38";"85,44";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,02";"DGM-2004_Epoche_NHN";""
+"437,400";"2,65";"6,02";"85,43";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,08";"DGM-2004_Epoche_NHN";""
+"437,500";"3,03";"6,96";"85,41";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,72";"DGM-2004_Epoche_NHN";""
+"437,600";"2,98";"6,69";"85,40";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,88";"DGM-2004_Epoche_NHN";""
+"437,700";"2,95";"6,59";"85,40";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,24";"DGM-2004_Epoche_NHN";""
+"437,800";"2,98";"6,63";"85,39";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,64";"DGM-2004_Epoche_NHN";""
+"437,900";"2,99";"5,53";"85,38";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,84";"DGM-2004_Epoche_NHN";""
+"438,000";"3,01";"4,63";"85,38";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,93";"DGM-2004_Epoche_NHN";""
+"438,100";"2,96";"4,32";"85,37";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,02";"DGM-2004_Epoche_NHN";""
+"438,200";"2,91";"3,96";"85,36";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,05";"DGM-2004_Epoche_NHN";""
+"438,300";"2,88";"3,84";"85,34";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,08";"DGM-2004_Epoche_NHN";""
+"438,400";"2,91";"3,74";"85,33";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,10";"DGM-2004_Epoche_NHN";""
+"438,500";"2,95";"3,67";"85,33";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,13";"DGM-2004_Epoche_NHN";""
+"438,600";"2,92";"3,93";"85,32";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,12";"DGM-2004_Epoche_NHN";""
+"438,700";"2,80";"4,31";"85,31";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,02";"DGM-2004_Epoche_NHN";""
+"438,800";"2,78";"4,42";"85,30";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,89";"DGM-2004_Epoche_NHN";""
+"438,900";"2,68";"4,56";"85,28";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,67";"DGM-2004_Epoche_NHN";""
+"439,000";"2,57";"4,73";"85,27";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,49";"DGM-2004_Epoche_NHN";""
+"439,100";"2,54";"4,60";"85,26";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,35";"DGM-2004_Epoche_NHN";""
+"439,200";"2,63";"4,58";"85,25";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,26";"DGM-2004_Epoche_NHN";""
+"439,300";"2,89";"4,33";"85,23";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,32";"DGM-2004_Epoche_NHN";""
+"439,400";"3,00";"4,10";"85,22";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,44";"DGM-2004_Epoche_NHN";""
+"439,500";"3,07";"4,03";"85,21";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,52";"DGM-2004_Epoche_NHN";""
+"439,600";"2,96";"3,96";"85,21";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,63";"DGM-2004_Epoche_NHN";""
+"439,700";"2,83";"3,96";"85,21";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,74";"DGM-2004_Epoche_NHN";""
+"439,800";"2,70";"4,00";"85,20";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,79";"DGM-2004_Epoche_NHN";""
+"439,900";"2,65";"4,76";"85,18";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,68";"DGM-2004_Epoche_NHN";""
+"440,000";"2,70";"5,14";"85,17";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,38";"DGM-2004_Epoche_NHN";""
+"440,100";"2,47";"5,47";"85,15";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,12";"DGM-2004_Epoche_NHN";""
+"440,200";"1,80";"6,03";"85,15";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,10";"DGM-2004_Epoche_NHN";""
+"440,300";"2,49";"5,90";"85,14";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,02";"DGM-2004_Epoche_NHN";"Altrhein: Lambertheim (4,7 km lang)"
+"440,400";"2,02";"5,80";"85,13";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,90";"DGM-2004_Epoche_NHN";""
+"440,500";"-0,54";"6,08";"85,12";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,92";"DGM-2004_Epoche_NHN";""
+"440,600";"-0,05";"5,88";"85,11";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,83";"DGM-2004_Epoche_NHN";""
+"440,700";"1,50";"5,34";"85,10";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,88";"DGM-2004_Epoche_NHN";""
+"440,800";"0,63";"5,38";"85,09";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,78";"DGM-2004_Epoche_NHN";""
+"440,900";"2,71";"5,19";"85,08";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,91";"DGM-2004_Epoche_NHN";""
+"441,000";"2,61";"4,48";"85,07";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,25";"DGM-2004_Epoche_NHN";""
+"441,100";"2,56";"4,00";"85,06";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,51";"DGM-2004_Epoche_NHN";""
+"441,200";"2,53";"3,74";"85,05";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,74";"DGM-2004_Epoche_NHN";""
+"441,300";"2,52";"3,45";"85,04";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,97";"DGM-2004_Epoche_NHN";""
+"441,400";"2,47";"3,13";"85,03";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,15";"DGM-2004_Epoche_NHN";""
+"441,500";"2,52";"3,34";"85,02";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,30";"DGM-2004_Epoche_NHN";""
+"441,600";"2,37";"4,70";"85,01";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,23";"DGM-2004_Epoche_NHN";""
+"441,700";"2,30";"4,87";"85,00";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,95";"DGM-2004_Epoche_NHN";""
+"441,800";"2,17";"4,81";"84,99";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,81";"DGM-2004_Epoche_NHN";""
+"441,900";"2,12";"5,01";"84,97";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,73";"DGM-2004_Epoche_NHN";""
+"442,000";"2,09";"5,01";"84,97";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,61";"DGM-2004_Epoche_NHN";""
+"442,100";"2,08";"4,60";"84,96";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,51";"DGM-2004_Epoche_NHN";""
+"442,200";"2,09";"5,01";"84,95";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,47";"DGM-2004_Epoche_NHN";""
+"442,300";"1,91";"4,85";"84,93";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,42";"DGM-2004_Epoche_NHN";""
+"442,400";"1,59";"5,08";"84,92";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,47";"DGM-2004_Epoche_NHN";""
+"442,500";"1,41";"4,94";"84,92";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,42";"DGM-2004_Epoche_NHN";""
+"442,600";"1,77";"4,85";"84,91";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,23";"DGM-2004_Epoche_NHN";""
+"442,700";"1,30";"5,07";"84,90";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,17";"DGM-2004_Epoche_NHN";""
+"442,800";"1,32";"4,99";"84,88";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,19";"DGM-2004_Epoche_NHN";""
+"442,900";"1,52";"4,77";"84,87";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,17";"DGM-2004_Epoche_NHN";""
+"443,000";"1,59";"5,06";"84,86";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,16";"DGM-2004_Epoche_NHN";"Hafen: Floßhafen -Schutzhafen"
+"443,100";"1,47";"4,62";"84,84";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,36";"DGM-2004_Epoche_NHN";""
+"443,200";"1,46";"4,48";"84,83";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,53";"DGM-2004_Epoche_NHN";""
+"443,300";"1,43";"5,13";"84,82";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,47";"DGM-2004_Epoche_NHN";""
+"443,400";"1,72";"4,52";"84,81";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,51";"DGM-2004_Epoche_NHN";""
+"443,500";"2,09";"4,19";"84,80";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,57";"DGM-2004_Epoche_NHN";""
+"443,600";"2,43";"3,83";"84,79";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,68";"DGM-2004_Epoche_NHN";""
+"443,700";"2,64";"3,42";"84,78";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,80";"DGM-2004_Epoche_NHN";""
+"443,800";"2,70";"3,13";"84,77";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,91";"DGM-2004_Epoche_NHN";""
+"443,900";"2,56";"2,96";"84,76";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,00";"DGM-2004_Epoche_NHN";""
+"444,000";"2,42";"2,93";"84,74";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,06";"DGM-2004_Epoche_NHN";""
+"444,100";"2,28";"3,15";"84,73";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,10";"DGM-2004_Epoche_NHN";""
+"444,200";"2,22";"3,39";"84,72";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,13";"DGM-2004_Epoche_NHN";""
+"444,300";"2,19";"3,51";"84,70";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"82,07";"DGM-2004_Epoche_NHN";""
+"444,400";"2,21";"3,52";"84,69";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,98";"DGM-2004_Epoche_NHN";"Geschiebemessstelle: Worms"
+"444,500";"2,22";"3,38";"84,68";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,96";"DGM-2004_Epoche_NHN";"Hafen: Worms Handelshafen -Schutzhafen"
+"444,600";"2,15";"3,33";"84,67";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,93";"DGM-2004_Epoche_NHN";""
+"444,700";"2,27";"3,28";"84,66";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,87";"DGM-2004_Epoche_NHN";""
+"444,800";"2,42";"3,21";"84,65";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,86";"DGM-2004_Epoche_NHN";""
+"444,900";"2,51";"3,13";"84,63";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,87";"DGM-2004_Epoche_NHN";""
+"445,000";"2,60";"3,09";"84,62";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,84";"DGM-2004_Epoche_NHN";""
+"445,100";"2,69";"3,21";"84,61";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,75";"DGM-2004_Epoche_NHN";""
+"445,200";"2,55";"3,28";"84,60";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,74";"DGM-2004_Epoche_NHN";""
+"445,300";"2,30";"3,34";"84,59";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,78";"DGM-2004_Epoche_NHN";""
+"445,400";"2,06";"3,48";"84,58";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,78";"DGM-2004_Epoche_NHN";""
+"445,500";"2,34";"3,94";"84,56";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,59";"DGM-2004_Epoche_NHN";""
+"445,600";"2,52";"3,46";"84,54";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,65";"DGM-2004_Epoche_NHN";""
+"445,700";"2,50";"3,53";"84,53";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,66";"DGM-2004_Epoche_NHN";""
+"445,800";"2,59";"3,43";"84,53";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,65";"DGM-2004_Epoche_NHN";""
+"445,900";"2,52";"3,33";"84,52";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,69";"DGM-2004_Epoche_NHN";""
+"446,000";"2,55";"3,39";"84,51";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,68";"DGM-2004_Epoche_NHN";""
+"446,100";"2,56";"3,44";"84,51";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,64";"DGM-2004_Epoche_NHN";""
+"446,200";"2,46";"3,53";"84,50";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,68";"DGM-2004_Epoche_NHN";""
+"446,300";"2,46";"3,48";"84,48";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,65";"DGM-2004_Epoche_NHN";""
+"446,400";"2,53";"3,60";"84,47";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,55";"DGM-2004_Epoche_NHN";""
+"446,500";"2,64";"3,74";"84,46";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,41";"DGM-2004_Epoche_NHN";""
+"446,600";"2,68";"3,87";"84,44";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,34";"DGM-2004_Epoche_NHN";""
+"446,700";"2,40";"3,97";"84,43";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,29";"DGM-2004_Epoche_NHN";""
+"446,800";"2,30";"3,84";"84,42";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,25";"DGM-2004_Epoche_NHN";""
+"446,900";"2,09";"3,89";"84,42";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,26";"DGM-2004_Epoche_NHN";""
+"447,000";"1,95";"3,91";"84,41";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,23";"DGM-2004_Epoche_NHN";""
+"447,100";"1,86";"3,90";"84,39";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,21";"DGM-2004_Epoche_NHN";""
+"447,200";"1,80";"3,91";"84,39";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,20";"DGM-2004_Epoche_NHN";""
+"447,300";"1,73";"3,93";"84,38";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,29";"DGM-2004_Epoche_NHN";""
+"447,400";"1,81";"3,51";"84,37";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,49";"DGM-2004_Epoche_NHN";""
+"447,500";"2,04";"3,19";"84,35";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,54";"DGM-2004_Epoche_NHN";""
+"447,600";"2,37";"3,64";"84,33";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,49";"DGM-2004_Epoche_NHN";""
+"447,700";"2,32";"4,10";"84,32";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,35";"DGM-2004_Epoche_NHN";""
+"447,800";"2,28";"4,36";"84,31";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,28";"DGM-2004_Epoche_NHN";""
+"447,900";"2,13";"4,40";"84,30";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,23";"DGM-2004_Epoche_NHN";""
+"448,000";"2,22";"4,15";"84,29";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,15";"DGM-2004_Epoche_NHN";""
+"448,100";"2,46";"4,38";"84,28";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,93";"DGM-2004_Epoche_NHN";""
+"448,200";"1,90";"4,33";"84,26";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,90";"DGM-2004_Epoche_NHN";""
+"448,300";"2,14";"4,09";"84,25";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,98";"DGM-2004_Epoche_NHN";""
+"448,400";"2,19";"3,80";"84,24";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,11";"DGM-2004_Epoche_NHN";""
+"448,500";"2,34";"3,74";"84,23";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,19";"DGM-2004_Epoche_NHN";""
+"448,600";"2,57";"3,69";"84,22";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,26";"DGM-2004_Epoche_NHN";""
+"448,700";"2,66";"3,53";"84,21";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,32";"DGM-2004_Epoche_NHN";""
+"448,800";"2,62";"3,49";"84,19";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,32";"DGM-2004_Epoche_NHN";""
+"448,900";"2,57";"3,57";"84,17";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,27";"DGM-2004_Epoche_NHN";""
+"449,000";"2,41";"3,58";"84,18";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,28";"DGM-2004_Epoche_NHN";""
+"449,100";"2,31";"3,53";"84,17";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,32";"DGM-2004_Epoche_NHN";""
+"449,200";"2,42";"3,46";"84,16";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,24";"DGM-2004_Epoche_NHN";""
+"449,300";"2,65";"3,51";"84,14";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"81,06";"DGM-2004_Epoche_NHN";""
+"449,400";"2,86";"4,20";"84,13";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,93";"DGM-2004_Epoche_NHN";""
+"449,500";"2,99";"4,64";"84,13";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,73";"DGM-2004_Epoche_NHN";""
+"449,600";"-1,79";"6,24";"84,12";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,48";"DGM-2004_Epoche_NHN";""
+"449,700";"-0,45";"7,91";"84,11";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"79,97";"DGM-2004_Epoche_NHN";""
+"449,800";"0,64";"5,88";"84,10";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,39";"DGM-2004_Epoche_NHN";""
+"449,900";"1,52";"4,13";"84,10";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,72";"DGM-2004_Epoche_NHN";""
+"450,000";"2,28";"3,71";"84,08";"670";"Amtl.Festlegung_GlQ(2002)";"außerh. d. Bez.pegels";"80,95";"DGM-2004_Epoche_NHN";""
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepthminmax/sinfo_minmaxft_02.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,965 @@
+"##Ergebnisausgabe - Elbe - Minimale und Maximale Fließtiefe"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: f"
+"# Datum der Erstellung: 14.06.18"
+"# Gewässer: Elbe"
+"# Höhensystem des Flusses: NHN + m "
+"# Bereich (km): 0,000 - 90,000"
+""
+"Fluss-km";"Minimale Fließtiefe [m]";"Maximale Fließtiefe [m]";"Wasserstand [NHN + m]";"Q [m³/s]";"Bezeichnung";"Bezugspegel";"Mittlere Sohlhöhe [NHN + m]";"Peilung/Epoche";"Lage"
+""
+"##METADATEN PEILUNG"
+"# Jahr der Peilung: 2015"
+"# Aufnahmeart: Flächenpeilung"
+"# Auswerter: BfG"
+"# Lagesystem: LS 150 oder LS 100 "
+"# Höhensystem: NHN "
+"# ursprüngliches Höhensystem: NHN"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: 02.09.2004 "
+"# Bezugspegel: Schöna"
+"# Jahr/Zeitraum der Wasserspiegellage: 2004"
+""
+"0,200";"2,54";"4,71";"117,35";"131";"02.09.2004";"Schöna";"113,93";"FP-2015_0-502";""
+"0,300";"2,52";"3,98";"117,35";"131";"02.09.2004";"Schöna";"114,17";"FP-2015_0-502";""
+"0,400";"2,63";"3,85";"117,35";"131";"02.09.2004";"Schöna";"114,13";"FP-2015_0-502";""
+"0,500";"2,02";"4,80";"117,34";"131";"02.09.2004";"Schöna";"113,63";"FP-2015_0-502";""
+"0,600";"2,36";"4,88";"117,34";"131";"02.09.2004";"Schöna";"113,27";"FP-2015_0-502";""
+"0,700";"3,50";"5,24";"117,34";"131";"02.09.2004";"Schöna";"112,98";"FP-2015_0-502";""
+"0,800";"3,16";"5,63";"117,34";"131";"02.09.2004";"Schöna";"112,60";"FP-2015_0-502";""
+"0,900";"3,46";"4,98";"117,34";"131";"02.09.2004";"Schöna";"112,91";"FP-2015_0-502";""
+"1,000";"3,03";"4,33";"117,34";"131";"02.09.2004";"Schöna";"113,64";"FP-2015_0-502";""
+"1,100";"2,91";"4,08";"117,34";"131";"02.09.2004";"Schöna";"113,90";"FP-2015_0-502";""
+"1,200";"3,20";"4,74";"117,34";"131";"02.09.2004";"Schöna";"113,49";"FP-2015_0-502";""
+"1,300";"3,69";"6,43";"117,34";"131";"02.09.2004";"Schöna";"112,61";"FP-2015_0-502";""
+"1,400";"3,63";"6,97";"117,33";"131";"02.09.2004";"Schöna";"111,87";"FP-2015_0-502";""
+"1,500";"4,06";"6,30";"117,33";"131";"02.09.2004";"Schöna";"112,01";"FP-2015_0-502";""
+"1,600";"3,38";"6,53";"117,32";"131";"02.09.2004";"Schöna";"111,91";"FP-2015_0-502";""
+"1,700";"3,77";"6,55";"117,32";"131";"02.09.2004";"Schöna";"111,71";"FP-2015_0-502";""
+"1,800";"4,27";"6,86";"117,33";"131";"02.09.2004";"Schöna";"111,55";"FP-2015_0-502";""
+"1,900";"2,28";"5,53";"117,33";"131";"02.09.2004";"Schöna";"112,80";"FP-2015_0-502";""
+"2,000";"2,19";"4,44";"117,33";"131";"02.09.2004";"Schöna";"113,77";"FP-2015_0-502";""
+"2,100";"2,61";"5,60";"117,33";"131";"02.09.2004";"Schöna";"113,54";"FP-2015_0-502";""
+"2,200";"2,13";"5,26";"117,32";"131";"02.09.2004";"Schöna";"113,68";"FP-2015_0-502";""
+"2,300";"2,09";"4,43";"117,31";"131";"02.09.2004";"Schöna";"114,39";"FP-2015_0-502";""
+"2,400";"2,35";"3,13";"117,30";"131";"02.09.2004";"Schöna";"114,58";"FP-2015_0-502";""
+"2,500";"2,07";"2,90";"117,29";"131";"02.09.2004";"Schöna";"114,75";"FP-2015_0-502";""
+"2,600";"1,82";"3,64";"117,28";"131";"02.09.2004";"Schöna";"114,71";"FP-2015_0-502";"Gemeinde: Schöna"
+"2,700";"1,78";"2,94";"117,26";"131";"02.09.2004";"Schöna";"114,83";"FP-2015_0-502";""
+"2,800";"1,83";"2,74";"117,24";"131";"02.09.2004";"Schöna";"114,99";"FP-2015_0-502";""
+"2,900";"1,72";"2,54";"117,23";"131";"02.09.2004";"Schöna";"115,10";"FP-2015_0-502";""
+"3,000";"1,64";"3,05";"117,21";"131";"02.09.2004";"Schöna";"115,22";"FP-2015_0-502";""
+"3,100";"1,70";"3,06";"117,20";"131";"02.09.2004";"Schöna";"115,05";"FP-2015_0-502";""
+"3,200";"1,67";"3,21";"117,18";"131";"02.09.2004";"Schöna";"114,64";"FP-2015_0-502";""
+"3,300";"1,62";"2,80";"117,15";"131";"02.09.2004";"Schöna";"115,12";"FP-2015_0-502";"Landkreis: Sächsische Schweiz"
+"3,400";"1,51";"2,73";"117,12";"131";"02.09.2004";"Schöna";"115,02";"FP-2015_0-502";""
+"3,500";"1,54";"2,18";"117,08";"131";"02.09.2004";"Schöna";"115,15";"FP-2015_0-502";""
+"3,600";"1,52";"2,13";"117,05";"131";"02.09.2004";"Schöna";"115,14";"FP-2015_0-502";""
+"3,700";"1,51";"2,03";"117,02";"131";"02.09.2004";"Schöna";"115,14";"FP-2015_0-502";""
+"3,800";"1,53";"2,09";"117,00";"131";"02.09.2004";"Schöna";"115,14";"FP-2015_0-502";""
+"3,900";"1,64";"3,07";"116,98";"131";"02.09.2004";"Schöna";"115,06";"FP-2015_0-502";"Fähre: Schmilka -Personen"
+"4,000";"1,69";"3,27";"116,96";"131";"02.09.2004";"Schöna";"114,83";"FP-2015_0-502";"Messstelle: -Wassergüte"
+"4,100";"1,54";"2,60";"116,94";"131";"02.09.2004";"Schöna";"114,90";"FP-2015_0-502";""
+"4,200";"1,67";"2,13";"116,90";"131";"02.09.2004";"Schöna";"114,96";"FP-2015_0-502";""
+"4,300";"1,68";"2,16";"116,86";"131";"02.09.2004";"Schöna";"114,85";"FP-2015_0-502";""
+"4,400";"1,66";"2,11";"116,82";"131";"02.09.2004";"Schöna";"114,88";"FP-2015_0-502";""
+"4,500";"1,70";"2,25";"116,78";"131";"02.09.2004";"Schöna";"114,89";"FP-2015_0-502";""
+"4,600";"1,54";"2,32";"116,74";"131";"02.09.2004";"Schöna";"114,72";"FP-2015_0-502";""
+"4,700";"1,66";"2,18";"116,71";"131";"02.09.2004";"Schöna";"114,80";"FP-2015_0-502";""
+"4,800";"1,43";"2,48";"116,69";"131";"02.09.2004";"Schöna";"114,78";"FP-2015_0-502";""
+"4,900";"1,78";"2,76";"116,67";"131";"02.09.2004";"Schöna";"114,64";"FP-2015_0-502";""
+"5,000";"1,91";"3,05";"116,65";"131";"02.09.2004";"Schöna";"114,22";"FP-2015_0-502";""
+"5,100";"1,94";"2,83";"116,63";"131";"02.09.2004";"Schöna";"114,15";"FP-2015_0-502";""
+"5,200";"2,05";"2,77";"116,61";"131";"02.09.2004";"Schöna";"114,18";"FP-2015_0-502";""
+"5,300";"1,59";"2,96";"116,60";"131";"02.09.2004";"Schöna";"114,18";"FP-2015_0-502";""
+"5,400";"1,82";"3,87";"116,58";"131";"02.09.2004";"Schöna";"113,88";"FP-2015_0-502";""
+"5,500";"2,13";"3,77";"116,57";"131";"02.09.2004";"Schöna";"113,76";"FP-2015_0-502";""
+"5,600";"1,93";"3,94";"116,55";"131";"02.09.2004";"Schöna";"113,66";"FP-2015_0-502";""
+"5,700";"1,74";"4,02";"116,53";"131";"02.09.2004";"Schöna";"113,76";"FP-2015_0-502";""
+"5,800";"1,34";"3,75";"116,51";"131";"02.09.2004";"Schöna";"113,91";"FP-2015_0-502";""
+"5,900";"1,33";"3,97";"116,48";"131";"02.09.2004";"Schöna";"113,82";"FP-2015_0-502";"Zufluss: Schönaer Bach"
+"6,000";"1,28";"3,79";"116,45";"131";"02.09.2004";"Schöna";"114,02";"FP-2015_0-502";""
+"6,100";"1,05";"3,23";"116,41";"131";"02.09.2004";"Schöna";"114,18";"FP-2015_0-502";""
+"6,200";"0,83";"2,84";"116,36";"131";"02.09.2004";"Schöna";"114,36";"FP-2015_0-502";""
+"6,300";"0,97";"2,79";"116,29";"131";"02.09.2004";"Schöna";"114,30";"FP-2015_0-502";""
+"6,400";"0,89";"2,34";"116,23";"131";"02.09.2004";"Schöna";"114,20";"FP-2015_0-502";""
+"6,500";"0,82";"2,38";"116,16";"131";"02.09.2004";"Schöna";"114,17";"FP-2015_0-502";""
+"6,600";"1,31";"2,37";"116,12";"131";"02.09.2004";"Schöna";"114,08";"FP-2015_0-502";""
+"6,700";"1,72";"2,76";"116,08";"131";"02.09.2004";"Schöna";"113,97";"FP-2015_0-502";""
+"6,800";"1,70";"2,73";"116,04";"131";"02.09.2004";"Schöna";"113,89";"FP-2015_0-502";""
+"6,900";"1,40";"2,61";"116,00";"131";"02.09.2004";"Schöna";"113,90";"FP-2015_0-502";""
+"7,000";"1,76";"2,78";"115,97";"131";"02.09.2004";"Schöna";"113,84";"FP-2015_0-502";""
+"7,100";"1,99";"3,38";"115,94";"131";"02.09.2004";"Schöna";"113,49";"FP-2015_0-502";""
+"7,200";"2,00";"2,89";"115,92";"131";"02.09.2004";"Schöna";"113,39";"FP-2015_0-502";""
+"7,300";"1,93";"2,77";"115,90";"131";"02.09.2004";"Schöna";"113,72";"FP-2015_0-502";""
+"7,400";"1,87";"3,00";"115,89";"131";"02.09.2004";"Schöna";"113,47";"FP-2015_0-502";""
+"7,500";"1,89";"2,90";"115,88";"131";"02.09.2004";"Schöna";"113,61";"FP-2015_0-502";""
+"7,600";"1,80";"2,39";"115,86";"131";"02.09.2004";"Schöna";"113,75";"FP-2015_0-502";""
+"7,700";"1,73";"2,41";"115,85";"131";"02.09.2004";"Schöna";"113,72";"FP-2015_0-502";""
+"7,800";"1,78";"2,76";"115,84";"131";"02.09.2004";"Schöna";"113,73";"FP-2015_0-502";""
+"7,900";"1,79";"3,02";"115,83";"131";"02.09.2004";"Schöna";"113,73";"FP-2015_0-502";""
+"8,000";"1,73";"2,74";"115,82";"131";"02.09.2004";"Schöna";"113,82";"FP-2015_0-502";""
+"8,100";"1,71";"2,50";"115,81";"131";"02.09.2004";"Schöna";"113,77";"FP-2015_0-502";""
+"8,200";"1,75";"2,53";"115,80";"131";"02.09.2004";"Schöna";"113,57";"FP-2015_0-502";""
+"8,300";"1,82";"2,84";"115,78";"131";"02.09.2004";"Schöna";"113,37";"FP-2015_0-502";""
+"8,400";"1,92";"2,85";"115,76";"131";"02.09.2004";"Schöna";"113,20";"FP-2015_0-502";""
+"8,500";"1,60";"2,67";"115,74";"131";"02.09.2004";"Schöna";"113,38";"FP-2015_0-502";""
+"8,600";"1,87";"2,39";"115,72";"131";"02.09.2004";"Schöna";"113,48";"FP-2015_0-502";""
+"8,700";"1,88";"2,31";"115,69";"131";"02.09.2004";"Schöna";"113,55";"FP-2015_0-502";""
+"8,800";"1,64";"2,27";"115,67";"131";"02.09.2004";"Schöna";"113,61";"FP-2015_0-502";""
+"8,900";"1,55";"2,22";"115,64";"131";"02.09.2004";"Schöna";"113,67";"FP-2015_0-502";""
+"9,000";"1,48";"2,16";"115,61";"131";"02.09.2004";"Schöna";"113,65";"FP-2015_0-502";""
+"9,100";"1,32";"2,34";"115,58";"131";"02.09.2004";"Schöna";"113,59";"FP-2015_0-502";""
+"9,200";"1,19";"2,31";"115,55";"131";"02.09.2004";"Schöna";"113,49";"FP-2015_0-502";""
+"9,300";"1,23";"2,40";"115,52";"131";"02.09.2004";"Schöna";"113,46";"FP-2015_0-502";""
+"9,400";"1,71";"2,41";"115,49";"131";"02.09.2004";"Schöna";"113,37";"FP-2015_0-502";""
+"9,500";"1,70";"2,42";"115,46";"131";"02.09.2004";"Schöna";"113,35";"FP-2015_0-502";""
+"9,600";"1,62";"2,19";"115,42";"131";"02.09.2004";"Schöna";"113,49";"FP-2015_0-502";""
+"9,700";"1,65";"1,96";"115,38";"131";"02.09.2004";"Schöna";"113,59";"FP-2015_0-502";""
+"9,800";"1,61";"2,61";"115,34";"131";"02.09.2004";"Schöna";"113,57";"FP-2015_0-502";"Zufluss: Kimitzsch"
+"9,900";"1,21";"3,27";"115,30";"131";"02.09.2004";"Schöna";"113,44";"FP-2015_0-502";""
+"10,000";"1,38";"2,84";"115,26";"131";"02.09.2004";"Schöna";"113,32";"FP-2015_0-502";""
+"10,100";"1,72";"2,09";"115,23";"131";"02.09.2004";"Schöna";"113,29";"FP-2015_0-502";""
+"10,200";"1,72";"2,31";"115,21";"131";"02.09.2004";"Schöna";"113,32";"FP-2015_0-502";""
+"10,300";"1,58";"3,74";"115,18";"131";"02.09.2004";"Schöna";"113,13";"FP-2015_0-502";""
+"10,400";"1,30";"3,50";"115,16";"131";"02.09.2004";"Schöna";"113,15";"FP-2015_0-502";""
+"10,500";"1,69";"2,51";"115,13";"131";"02.09.2004";"Schöna";"113,13";"FP-2015_0-502";""
+"10,600";"1,67";"2,38";"115,10";"131";"02.09.2004";"Schöna";"112,99";"FP-2015_0-502";""
+"10,700";"1,59";"2,70";"115,07";"131";"02.09.2004";"Schöna";"112,94";"FP-2015_0-502";""
+"10,800";"1,65";"2,77";"115,04";"131";"02.09.2004";"Schöna";"112,74";"FP-2015_0-502";""
+"10,900";"1,92";"3,47";"115,01";"131";"02.09.2004";"Schöna";"112,75";"FP-2015_0-502";""
+"11,000";"1,83";"4,26";"114,99";"131";"02.09.2004";"Schöna";"112,25";"FP-2015_0-502";""
+"11,100";"1,66";"3,29";"114,97";"131";"02.09.2004";"Schöna";"112,40";"FP-2015_0-502";""
+"11,200";"1,79";"3,26";"114,95";"131";"02.09.2004";"Schöna";"112,27";"FP-2015_0-502";""
+"11,300";"1,53";"2,93";"114,93";"131";"02.09.2004";"Schöna";"112,58";"FP-2015_0-502";""
+"11,400";"1,58";"2,63";"114,91";"131";"02.09.2004";"Schöna";"112,85";"FP-2015_0-502";""
+"11,500";"1,53";"2,38";"114,88";"131";"02.09.2004";"Schöna";"112,86";"FP-2015_0-502";""
+"11,600";"1,45";"2,39";"114,86";"131";"02.09.2004";"Schöna";"112,80";"FP-2015_0-502";""
+"11,700";"1,32";"2,30";"114,83";"131";"02.09.2004";"Schöna";"112,83";"FP-2015_0-502";""
+"11,800";"1,31";"2,46";"114,79";"131";"02.09.2004";"Schöna";"112,82";"FP-2015_0-502";""
+"11,900";"1,53";"2,85";"114,75";"131";"02.09.2004";"Schöna";"112,70";"FP-2015_0-502";""
+"12,000";"1,05";"2,08";"114,71";"131";"02.09.2004";"Schöna";"112,96";"FP-2015_0-502";"Zufluss: Lachsbach"
+"12,100";"1,17";"2,55";"114,66";"131";"02.09.2004";"Schöna";"112,71";"FP-2015_0-502";""
+"12,200";"0,87";"2,56";"114,60";"131";"02.09.2004";"Schöna";"112,46";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-1"
+"12,300";"0,94";"2,72";"114,56";"131";"02.09.2004";"Schöna";"112,37";"FP-2015_0-502";""
+"12,400";"0,95";"2,89";"114,53";"131";"02.09.2004";"Schöna";"112,21";"FP-2015_0-502";""
+"12,500";"1,42";"3,16";"114,50";"131";"02.09.2004";"Schöna";"112,02";"FP-2015_0-502";""
+"12,600";"1,28";"3,28";"114,47";"131";"02.09.2004";"Schöna";"111,97";"FP-2015_0-502";""
+"12,700";"1,38";"3,11";"114,45";"131";"02.09.2004";"Schöna";"111,88";"FP-2015_0-502";""
+"12,800";"1,45";"3,09";"114,43";"131";"02.09.2004";"Schöna";"111,88";"FP-2015_0-502";""
+"12,900";"1,81";"3,14";"114,42";"131";"02.09.2004";"Schöna";"111,81";"FP-2015_0-502";""
+"13,000";"1,99";"3,16";"114,41";"131";"02.09.2004";"Schöna";"111,80";"FP-2015_0-502";""
+"13,100";"1,74";"2,60";"114,40";"131";"02.09.2004";"Schöna";"112,11";"FP-2015_0-502";""
+"13,200";"1,72";"2,51";"114,39";"131";"02.09.2004";"Schöna";"112,34";"FP-2015_0-502";""
+"13,300";"1,38";"2,54";"114,37";"131";"02.09.2004";"Schöna";"112,36";"FP-2015_0-502";"Gemeinde: Prossen"
+"13,400";"1,34";"2,36";"114,34";"131";"02.09.2004";"Schöna";"112,29";"FP-2015_0-502";""
+"13,500";"1,43";"2,47";"114,30";"131";"02.09.2004";"Schöna";"112,22";"FP-2015_0-502";""
+"13,600";"1,58";"2,53";"114,27";"131";"02.09.2004";"Schöna";"112,10";"FP-2015_0-502";""
+"13,700";"1,58";"2,63";"114,23";"131";"02.09.2004";"Schöna";"112,09";"FP-2015_0-502";""
+"13,800";"1,49";"2,70";"114,19";"131";"02.09.2004";"Schöna";"112,09";"FP-2015_0-502";""
+"13,900";"1,48";"2,78";"114,15";"131";"02.09.2004";"Schöna";"112,04";"FP-2015_0-502";""
+"14,000";"1,27";"2,74";"114,10";"131";"02.09.2004";"Schöna";"111,96";"FP-2015_0-502";""
+"14,100";"0,96";"2,78";"114,06";"131";"02.09.2004";"Schöna";"111,96";"FP-2015_0-502";""
+"14,200";"1,11";"3,81";"114,03";"131";"02.09.2004";"Schöna";"111,59";"FP-2015_0-502";""
+"14,300";"1,38";"3,89";"114,02";"131";"02.09.2004";"Schöna";"111,45";"FP-2015_0-502";""
+"14,400";"1,47";"2,79";"114,00";"131";"02.09.2004";"Schöna";"111,67";"FP-2015_0-502";""
+"14,500";"1,21";"3,68";"113,97";"131";"02.09.2004";"Schöna";"111,38";"FP-2015_0-502";""
+"14,600";"1,32";"3,98";"113,95";"131";"02.09.2004";"Schöna";"111,23";"FP-2015_0-502";""
+"14,700";"1,30";"3,60";"113,93";"131";"02.09.2004";"Schöna";"111,33";"FP-2015_0-502";""
+"14,800";"1,38";"3,15";"113,90";"131";"02.09.2004";"Schöna";"111,60";"FP-2015_0-502";""
+"14,900";"1,46";"3,16";"113,87";"131";"02.09.2004";"Schöna";"111,43";"FP-2015_0-502";""
+"15,000";"1,67";"3,17";"113,85";"131";"02.09.2004";"Schöna";"111,35";"FP-2015_0-502";""
+"15,100";"1,84";"3,08";"113,84";"131";"02.09.2004";"Schöna";"111,42";"FP-2015_0-502";""
+"15,200";"1,75";"3,01";"113,83";"131";"02.09.2004";"Schöna";"111,47";"FP-2015_0-502";""
+"15,300";"1,92";"2,85";"113,82";"131";"02.09.2004";"Schöna";"111,47";"FP-2015_0-502";""
+"15,400";"2,00";"3,17";"113,81";"131";"02.09.2004";"Schöna";"111,39";"FP-2015_0-502";""
+"15,500";"1,92";"3,03";"113,79";"131";"02.09.2004";"Schöna";"111,37";"FP-2015_0-502";""
+"15,600";"2,03";"3,22";"113,78";"131";"02.09.2004";"Schöna";"111,21";"FP-2015_0-502";""
+"15,700";"2,04";"2,84";"113,76";"131";"02.09.2004";"Schöna";"111,33";"FP-2015_0-502";""
+"15,800";"1,89";"2,77";"113,74";"131";"02.09.2004";"Schöna";"111,29";"FP-2015_0-502";""
+"15,900";"1,68";"2,58";"113,71";"131";"02.09.2004";"Schöna";"111,50";"FP-2015_0-502";""
+"16,000";"1,48";"2,63";"113,67";"131";"02.09.2004";"Schöna";"111,54";"FP-2015_0-502";""
+"16,100";"1,26";"2,46";"113,63";"131";"02.09.2004";"Schöna";"111,60";"FP-2015_0-502";"Gemeinde: Königstein"
+"16,200";"1,23";"3,11";"113,59";"131";"02.09.2004";"Schöna";"111,56";"FP-2015_0-502";""
+"16,300";"1,12";"2,98";"113,56";"131";"02.09.2004";"Schöna";"111,59";"FP-2015_0-502";""
+"16,400";"1,12";"2,38";"113,52";"131";"02.09.2004";"Schöna";"111,66";"FP-2015_0-502";"Fähre: Königstein -Personen"
+"16,500";"1,38";"2,34";"113,47";"131";"02.09.2004";"Schöna";"111,46";"FP-2015_0-502";""
+"16,600";"1,52";"2,30";"113,42";"131";"02.09.2004";"Schöna";"111,34";"FP-2015_0-502";"Zufluss: Biela"
+"16,700";"1,02";"2,63";"113,36";"131";"02.09.2004";"Schöna";"111,45";"FP-2015_0-502";""
+"16,800";"0,86";"2,59";"113,30";"131";"02.09.2004";"Schöna";"111,44";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-2"
+"16,900";"1,12";"2,14";"113,25";"131";"02.09.2004";"Schöna";"111,49";"FP-2015_0-502";""
+"17,000";"1,23";"2,33";"113,21";"131";"02.09.2004";"Schöna";"111,47";"FP-2015_0-502";"Gemeinde: Halbestadt"
+"17,100";"1,41";"2,34";"113,18";"131";"02.09.2004";"Schöna";"111,32";"FP-2015_0-502";""
+"17,200";"1,47";"2,25";"113,15";"131";"02.09.2004";"Schöna";"111,24";"FP-2015_0-502";"Hafen: Königstein"
+"17,300";"1,38";"2,46";"113,12";"131";"02.09.2004";"Schöna";"111,12";"FP-2015_0-502";""
+"17,400";"1,42";"2,73";"113,09";"131";"02.09.2004";"Schöna";"110,90";"FP-2015_0-502";""
+"17,500";"1,42";"2,72";"113,05";"131";"02.09.2004";"Schöna";"110,92";"FP-2015_0-502";""
+"17,600";"1,42";"2,52";"113,02";"131";"02.09.2004";"Schöna";"111,03";"FP-2015_0-502";""
+"17,700";"1,26";"2,28";"112,98";"131";"02.09.2004";"Schöna";"111,11";"FP-2015_0-502";""
+"17,800";"1,19";"2,23";"112,95";"131";"02.09.2004";"Schöna";"111,10";"FP-2015_0-502";""
+"17,900";"1,20";"2,29";"112,91";"131";"02.09.2004";"Schöna";"110,99";"FP-2015_0-502";""
+"18,000";"1,40";"2,32";"112,87";"131";"02.09.2004";"Schöna";"110,93";"FP-2015_0-502";""
+"18,100";"1,38";"2,30";"112,82";"131";"02.09.2004";"Schöna";"110,83";"FP-2015_0-502";""
+"18,200";"1,45";"2,42";"112,78";"131";"02.09.2004";"Schöna";"110,71";"FP-2015_0-502";""
+"18,300";"1,29";"2,52";"112,74";"131";"02.09.2004";"Schöna";"110,65";"FP-2015_0-502";""
+"18,400";"1,24";"2,48";"112,70";"131";"02.09.2004";"Schöna";"110,61";"FP-2015_0-502";""
+"18,500";"1,29";"3,07";"112,66";"131";"02.09.2004";"Schöna";"110,37";"FP-2015_0-502";""
+"18,600";"1,30";"3,21";"112,62";"131";"02.09.2004";"Schöna";"110,29";"FP-2015_0-502";""
+"18,700";"1,07";"3,58";"112,59";"131";"02.09.2004";"Schöna";"110,28";"FP-2015_0-502";""
+"18,800";"1,24";"3,43";"112,55";"131";"02.09.2004";"Schöna";"110,16";"FP-2015_0-502";""
+"18,900";"1,28";"3,34";"112,52";"131";"02.09.2004";"Schöna";"110,26";"FP-2015_0-502";""
+"19,000";"1,31";"2,62";"112,48";"131";"02.09.2004";"Schöna";"110,35";"FP-2015_0-502";""
+"19,100";"1,48";"2,95";"112,46";"131";"02.09.2004";"Schöna";"110,22";"FP-2015_0-502";""
+"19,200";"1,82";"3,23";"112,44";"131";"02.09.2004";"Schöna";"109,95";"FP-2015_0-502";""
+"19,300";"1,65";"3,52";"112,42";"131";"02.09.2004";"Schöna";"109,74";"FP-2015_0-502";""
+"19,400";"1,74";"3,49";"112,41";"131";"02.09.2004";"Schöna";"109,72";"FP-2015_0-502";""
+"19,500";"1,75";"3,27";"112,40";"131";"02.09.2004";"Schöna";"109,60";"FP-2015_0-502";""
+"19,600";"1,61";"3,04";"112,39";"131";"02.09.2004";"Schöna";"109,93";"FP-2015_0-502";""
+"19,700";"1,46";"2,39";"112,37";"131";"02.09.2004";"Schöna";"110,39";"FP-2015_0-502";""
+"19,800";"1,46";"2,24";"112,35";"131";"02.09.2004";"Schöna";"110,62";"FP-2015_0-502";""
+"19,900";"1,52";"2,56";"112,33";"131";"02.09.2004";"Schöna";"110,56";"FP-2015_0-502";""
+"20,000";"1,46";"2,51";"112,30";"131";"02.09.2004";"Schöna";"110,46";"FP-2015_0-502";""
+"20,100";"1,36";"2,16";"112,26";"131";"02.09.2004";"Schöna";"110,39";"FP-2015_0-502";""
+"20,200";"1,24";"2,02";"112,21";"131";"02.09.2004";"Schöna";"110,44";"FP-2015_0-502";""
+"20,300";"1,27";"2,05";"112,17";"131";"02.09.2004";"Schöna";"110,39";"FP-2015_0-502";""
+"20,400";"1,54";"2,21";"112,13";"131";"02.09.2004";"Schöna";"110,32";"FP-2015_0-502";""
+"20,500";"1,58";"2,20";"112,10";"131";"02.09.2004";"Schöna";"110,16";"FP-2015_0-502";""
+"20,600";"1,55";"2,31";"112,07";"131";"02.09.2004";"Schöna";"110,09";"FP-2015_0-502";""
+"20,700";"1,73";"2,48";"112,04";"131";"02.09.2004";"Schöna";"109,96";"FP-2015_0-502";""
+"20,800";"1,79";"2,51";"112,01";"131";"02.09.2004";"Schöna";"109,92";"FP-2015_0-502";""
+"20,900";"1,98";"2,96";"111,99";"131";"02.09.2004";"Schöna";"109,69";"FP-2015_0-502";""
+"21,000";"2,17";"2,92";"111,97";"131";"02.09.2004";"Schöna";"109,47";"FP-2015_0-502";""
+"21,100";"1,92";"2,73";"111,95";"131";"02.09.2004";"Schöna";"109,59";"FP-2015_0-502";""
+"21,200";"1,57";"2,82";"111,93";"131";"02.09.2004";"Schöna";"109,69";"FP-2015_0-502";""
+"21,300";"1,46";"2,57";"111,90";"131";"02.09.2004";"Schöna";"109,73";"FP-2015_0-502";""
+"21,400";"1,34";"2,41";"111,86";"131";"02.09.2004";"Schöna";"109,77";"FP-2015_0-502";""
+"21,500";"1,18";"2,45";"111,83";"131";"02.09.2004";"Schöna";"109,80";"FP-2015_0-502";""
+"21,600";"1,13";"2,54";"111,78";"131";"02.09.2004";"Schöna";"109,72";"FP-2015_0-502";""
+"21,700";"1,18";"2,72";"111,74";"131";"02.09.2004";"Schöna";"109,63";"FP-2015_0-502";""
+"21,800";"1,26";"2,94";"111,70";"131";"02.09.2004";"Schöna";"109,48";"FP-2015_0-502";""
+"21,900";"1,18";"2,67";"111,66";"131";"02.09.2004";"Schöna";"109,56";"FP-2015_0-502";""
+"22,000";"1,14";"2,48";"111,62";"131";"02.09.2004";"Schöna";"109,59";"FP-2015_0-502";""
+"22,100";"1,38";"2,34";"111,58";"131";"02.09.2004";"Schöna";"109,55";"FP-2015_0-502";""
+"22,200";"1,36";"2,59";"111,54";"131";"02.09.2004";"Schöna";"109,47";"FP-2015_0-502";""
+"22,300";"1,28";"2,37";"111,49";"131";"02.09.2004";"Schöna";"109,52";"FP-2015_0-502";""
+"22,400";"1,48";"2,13";"111,44";"131";"02.09.2004";"Schöna";"109,52";"FP-2015_0-502";""
+"22,500";"1,41";"2,12";"111,40";"131";"02.09.2004";"Schöna";"109,52";"FP-2015_0-502";""
+"22,600";"1,53";"1,98";"111,36";"131";"02.09.2004";"Schöna";"109,56";"FP-2015_0-502";""
+"22,700";"1,59";"2,58";"111,33";"131";"02.09.2004";"Schöna";"109,42";"FP-2015_0-502";""
+"22,800";"1,74";"2,60";"111,30";"131";"02.09.2004";"Schöna";"109,23";"FP-2015_0-502";""
+"22,900";"1,37";"2,20";"111,26";"131";"02.09.2004";"Schöna";"109,36";"FP-2015_0-502";""
+"23,000";"1,23";"2,22";"111,22";"131";"02.09.2004";"Schöna";"109,33";"FP-2015_0-502";""
+"23,100";"1,31";"2,30";"111,17";"131";"02.09.2004";"Schöna";"109,24";"FP-2015_0-502";""
+"23,200";"1,33";"2,37";"111,12";"131";"02.09.2004";"Schöna";"109,14";"FP-2015_0-502";""
+"23,300";"1,27";"2,34";"111,07";"131";"02.09.2004";"Schöna";"109,09";"FP-2015_0-502";""
+"23,400";"1,31";"2,29";"111,03";"131";"02.09.2004";"Schöna";"109,04";"FP-2015_0-502";""
+"23,500";"1,26";"2,68";"110,99";"131";"02.09.2004";"Schöna";"108,92";"FP-2015_0-502";""
+"23,600";"1,42";"2,63";"110,96";"131";"02.09.2004";"Schöna";"108,82";"FP-2015_0-502";""
+"23,700";"1,33";"2,62";"110,93";"131";"02.09.2004";"Schöna";"108,90";"FP-2015_0-502";""
+"23,800";"1,46";"2,36";"110,90";"131";"02.09.2004";"Schöna";"108,93";"FP-2015_0-502";""
+"23,900";"1,54";"2,29";"110,87";"131";"02.09.2004";"Schöna";"108,88";"FP-2015_0-502";""
+"24,000";"1,60";"2,70";"110,84";"131";"02.09.2004";"Schöna";"108,72";"FP-2015_0-502";""
+"24,100";"1,61";"2,72";"110,82";"131";"02.09.2004";"Schöna";"108,48";"FP-2015_0-502";""
+"24,200";"1,76";"2,65";"110,80";"131";"02.09.2004";"Schöna";"108,55";"FP-2015_0-502";""
+"24,300";"1,74";"2,59";"110,78";"131";"02.09.2004";"Schöna";"108,64";"FP-2015_0-502";""
+"24,400";"1,78";"2,69";"110,76";"131";"02.09.2004";"Schöna";"108,50";"FP-2015_0-502";""
+"24,500";"1,85";"2,85";"110,74";"131";"02.09.2004";"Schöna";"108,43";"FP-2015_0-502";""
+"24,600";"1,48";"2,64";"110,72";"131";"02.09.2004";"Schöna";"108,39";"FP-2015_0-502";""
+"24,700";"1,58";"110,70";"110,70";"131";"02.09.2004";"Schöna";"108,38";"FP-2015_0-502";""
+"24,800";"1,84";"110,69";"110,69";"131";"02.09.2004";"Schöna";"108,11";"FP-2015_0-502";""
+"24,900";"1,85";"3,19";"110,67";"131";"02.09.2004";"Schöna";"108,00";"FP-2015_0-502";""
+"25,000";"1,81";"3,08";"110,66";"131";"02.09.2004";"Schöna";"108,01";"FP-2015_0-502";""
+"25,100";"1,80";"2,89";"110,65";"131";"02.09.2004";"Schöna";"108,14";"FP-2015_0-502";""
+"25,200";"1,99";"2,80";"110,63";"131";"02.09.2004";"Schöna";"108,11";"FP-2015_0-502";""
+"25,300";"1,88";"2,81";"110,62";"131";"02.09.2004";"Schöna";"108,24";"FP-2015_0-502";""
+"25,400";"1,78";"3,00";"110,61";"131";"02.09.2004";"Schöna";"108,32";"FP-2015_0-502";""
+"25,500";"1,73";"3,29";"110,60";"131";"02.09.2004";"Schöna";"108,07";"FP-2015_0-502";""
+"25,600";"2,02";"3,04";"110,59";"131";"02.09.2004";"Schöna";"107,97";"FP-2015_0-502";"Gemeinde: Stadt Wehlen"
+"25,700";"1,88";"3,37";"110,57";"131";"02.09.2004";"Schöna";"108,02";"FP-2015_0-502";""
+"25,800";"1,83";"3,51";"110,56";"131";"02.09.2004";"Schöna";"107,96";"FP-2015_0-502";""
+"25,900";"1,93";"3,74";"110,55";"131";"02.09.2004";"Schöna";"107,91";"FP-2015_0-502";""
+"26,000";"1,52";"2,86";"110,53";"131";"02.09.2004";"Schöna";"108,27";"FP-2015_0-502";"Fähre: Pötzscha -Personen"
+"26,100";"1,27";"2,82";"110,51";"131";"02.09.2004";"Schöna";"108,54";"FP-2015_0-502";""
+"26,200";"1,64";"2,66";"110,49";"131";"02.09.2004";"Schöna";"108,45";"FP-2015_0-502";""
+"26,300";"1,93";"2,58";"110,47";"131";"02.09.2004";"Schöna";"108,24";"FP-2015_0-502";""
+"26,400";"1,93";"2,71";"110,45";"131";"02.09.2004";"Schöna";"108,02";"FP-2015_0-502";""
+"26,500";"1,81";"2,67";"110,44";"131";"02.09.2004";"Schöna";"108,14";"FP-2015_0-502";""
+"26,600";"1,79";"2,56";"110,41";"131";"02.09.2004";"Schöna";"108,19";"FP-2015_0-502";""
+"26,700";"1,96";"2,71";"110,40";"131";"02.09.2004";"Schöna";"107,98";"FP-2015_0-502";""
+"26,800";"2,11";"2,71";"110,38";"131";"02.09.2004";"Schöna";"107,92";"FP-2015_0-502";""
+"26,900";"2,00";"3,59";"110,37";"131";"02.09.2004";"Schöna";"107,77";"FP-2015_0-502";""
+"27,000";"1,88";"4,11";"110,35";"131";"02.09.2004";"Schöna";"107,46";"FP-2015_0-502";"Gemeinde: Naundorf"
+"27,100";"1,77";"3,69";"110,33";"131";"02.09.2004";"Schöna";"107,55";"FP-2015_0-502";""
+"27,200";"1,45";"3,28";"110,31";"131";"02.09.2004";"Schöna";"107,88";"FP-2015_0-502";""
+"27,300";"1,36";"3,25";"110,28";"131";"02.09.2004";"Schöna";"108,02";"FP-2015_0-502";""
+"27,400";"1,47";"3,07";"110,26";"131";"02.09.2004";"Schöna";"108,09";"FP-2015_0-502";""
+"27,500";"1,58";"2,66";"110,23";"131";"02.09.2004";"Schöna";"108,08";"FP-2015_0-502";""
+"27,600";"1,63";"2,74";"110,20";"131";"02.09.2004";"Schöna";"108,04";"FP-2015_0-502";""
+"27,700";"1,67";"2,74";"110,19";"131";"02.09.2004";"Schöna";"107,95";"FP-2015_0-502";""
+"27,800";"1,84";"2,97";"110,17";"131";"02.09.2004";"Schöna";"107,82";"FP-2015_0-502";""
+"27,900";"2,08";"2,53";"110,16";"131";"02.09.2004";"Schöna";"107,80";"FP-2015_0-502";""
+"28,000";"1,93";"2,51";"110,15";"131";"02.09.2004";"Schöna";"107,84";"FP-2015_0-502";""
+"28,100";"1,90";"2,86";"110,14";"131";"02.09.2004";"Schöna";"107,74";"FP-2015_0-502";""
+"28,200";"1,97";"3,32";"110,13";"131";"02.09.2004";"Schöna";"107,48";"FP-2015_0-502";""
+"28,300";"1,90";"3,63";"110,12";"131";"02.09.2004";"Schöna";"107,21";"FP-2015_0-502";""
+"28,400";"1,69";"4,39";"110,10";"131";"02.09.2004";"Schöna";"107,09";"FP-2015_0-502";""
+"28,500";"1,54";"4,32";"110,09";"131";"02.09.2004";"Schöna";"107,20";"FP-2015_0-502";""
+"28,600";"1,51";"4,20";"110,07";"131";"02.09.2004";"Schöna";"107,15";"FP-2015_0-502";""
+"28,700";"1,55";"4,52";"110,05";"131";"02.09.2004";"Schöna";"107,09";"FP-2015_0-502";""
+"28,800";"1,67";"5,35";"110,03";"131";"02.09.2004";"Schöna";"106,90";"FP-2015_0-502";""
+"28,900";"1,37";"5,43";"110,01";"131";"02.09.2004";"Schöna";"107,02";"FP-2015_0-502";""
+"29,000";"1,20";"4,46";"109,99";"131";"02.09.2004";"Schöna";"107,33";"FP-2015_0-502";""
+"29,100";"1,43";"3,58";"109,98";"131";"02.09.2004";"Schöna";"107,40";"FP-2015_0-502";""
+"29,200";"1,46";"4,08";"109,97";"131";"02.09.2004";"Schöna";"107,30";"FP-2015_0-502";""
+"29,300";"1,30";"4,61";"109,96";"131";"02.09.2004";"Schöna";"107,33";"FP-2015_0-502";""
+"29,400";"1,63";"3,75";"109,96";"131";"02.09.2004";"Schöna";"107,24";"FP-2015_0-502";""
+"29,500";"2,21";"2,96";"109,96";"131";"02.09.2004";"Schöna";"107,36";"FP-2015_0-502";""
+"29,600";"2,22";"3,18";"109,96";"131";"02.09.2004";"Schöna";"107,37";"FP-2015_0-502";""
+"29,700";"2,45";"3,63";"109,96";"131";"02.09.2004";"Schöna";"106,93";"FP-2015_0-502";""
+"29,800";"2,46";"3,59";"109,96";"131";"02.09.2004";"Schöna";"106,81";"FP-2015_0-502";""
+"29,900";"2,67";"4,13";"109,96";"131";"02.09.2004";"Schöna";"106,61";"FP-2015_0-502";""
+"30,000";"2,59";"3,82";"109,96";"131";"02.09.2004";"Schöna";"106,74";"FP-2015_0-502";""
+"30,100";"2,66";"3,73";"109,95";"131";"02.09.2004";"Schöna";"106,59";"FP-2015_0-502";""
+"30,200";"2,78";"3,69";"109,95";"131";"02.09.2004";"Schöna";"106,60";"FP-2015_0-502";""
+"30,300";"2,56";"4,54";"109,95";"131";"02.09.2004";"Schöna";"106,80";"FP-2015_0-502";""
+"30,400";"2,68";"4,51";"109,94";"131";"02.09.2004";"Schöna";"106,54";"FP-2015_0-502";""
+"30,500";"1,68";"4,59";"109,93";"131";"02.09.2004";"Schöna";"106,43";"FP-2015_0-502";""
+"30,600";"1,41";"4,10";"109,92";"131";"02.09.2004";"Schöna";"107,09";"FP-2015_0-502";""
+"30,700";"1,70";"3,27";"109,92";"131";"02.09.2004";"Schöna";"107,51";"FP-2015_0-502";""
+"30,800";"1,68";"3,14";"109,92";"131";"02.09.2004";"Schöna";"107,50";"FP-2015_0-502";""
+"30,900";"1,57";"3,04";"109,93";"131";"02.09.2004";"Schöna";"107,70";"FP-2015_0-502";""
+"31,000";"1,80";"2,86";"109,92";"131";"02.09.2004";"Schöna";"107,64";"FP-2015_0-502";"Gemeinde: Ober-Posta"
+"31,100";"1,71";"3,16";"109,92";"131";"02.09.2004";"Schöna";"107,44";"FP-2015_0-502";""
+"31,200";"2,02";"3,39";"109,91";"131";"02.09.2004";"Schöna";"107,09";"FP-2015_0-502";""
+"31,300";"2,37";"3,58";"109,90";"131";"02.09.2004";"Schöna";"106,85";"FP-2015_0-502";""
+"31,400";"2,31";"3,75";"109,90";"131";"02.09.2004";"Schöna";"106,79";"FP-2015_0-502";""
+"31,500";"2,22";"3,65";"109,89";"131";"02.09.2004";"Schöna";"106,80";"FP-2015_0-502";""
+"31,600";"1,70";"3,40";"109,89";"131";"02.09.2004";"Schöna";"107,10";"FP-2015_0-502";""
+"31,700";"1,66";"3,18";"109,88";"131";"02.09.2004";"Schöna";"107,36";"FP-2015_0-502";""
+"31,800";"1,75";"2,78";"109,87";"131";"02.09.2004";"Schöna";"107,52";"FP-2015_0-502";""
+"31,900";"1,67";"2,47";"109,86";"131";"02.09.2004";"Schöna";"107,72";"FP-2015_0-502";""
+"32,000";"1,57";"2,75";"109,86";"131";"02.09.2004";"Schöna";"107,79";"FP-2015_0-502";"Gemeinde: Cunnersdorf"
+"32,100";"1,57";"2,69";"109,86";"131";"02.09.2004";"Schöna";"107,70";"FP-2015_0-502";""
+"32,200";"1,62";"2,60";"109,85";"131";"02.09.2004";"Schöna";"107,74";"FP-2015_0-502";""
+"32,300";"1,85";"2,52";"109,85";"131";"02.09.2004";"Schöna";"107,78";"FP-2015_0-502";""
+"32,400";"1,85";"2,36";"109,85";"131";"02.09.2004";"Schöna";"107,78";"FP-2015_0-502";""
+"32,500";"1,82";"2,24";"109,84";"131";"02.09.2004";"Schöna";"107,83";"FP-2015_0-502";""
+"32,600";"1,81";"2,13";"109,83";"131";"02.09.2004";"Schöna";"107,86";"FP-2015_0-502";""
+"32,700";"1,76";"2,12";"109,81";"131";"02.09.2004";"Schöna";"107,85";"FP-2015_0-502";""
+"32,800";"1,86";"2,16";"109,80";"131";"02.09.2004";"Schöna";"107,83";"FP-2015_0-502";""
+"32,900";"1,81";"2,17";"109,78";"131";"02.09.2004";"Schöna";"107,81";"FP-2015_0-502";""
+"33,000";"1,74";"2,21";"109,76";"131";"02.09.2004";"Schöna";"107,76";"FP-2015_0-502";"Gemeinde: Nieder-Posta"
+"33,100";"1,89";"2,30";"109,75";"131";"02.09.2004";"Schöna";"107,64";"FP-2015_0-502";""
+"33,200";"1,94";"2,48";"109,74";"131";"02.09.2004";"Schöna";"107,61";"FP-2015_0-502";""
+"33,300";"1,98";"2,47";"109,73";"131";"02.09.2004";"Schöna";"107,53";"FP-2015_0-502";""
+"33,400";"1,98";"2,38";"109,71";"131";"02.09.2004";"Schöna";"107,48";"FP-2015_0-502";""
+"33,500";"1,78";"2,27";"109,70";"131";"02.09.2004";"Schöna";"107,67";"FP-2015_0-502";"Hafen: Pirna-Copitz"
+"33,600";"1,77";"2,24";"109,68";"131";"02.09.2004";"Schöna";"107,72";"FP-2015_0-502";""
+"33,700";"1,73";"2,31";"109,66";"131";"02.09.2004";"Schöna";"107,55";"FP-2015_0-502";""
+"33,800";"1,75";"2,79";"109,64";"131";"02.09.2004";"Schöna";"107,35";"FP-2015_0-502";""
+"33,900";"1,76";"2,87";"109,63";"131";"02.09.2004";"Schöna";"107,29";"FP-2015_0-502";""
+"34,000";"1,82";"2,92";"109,62";"131";"02.09.2004";"Schöna";"107,14";"FP-2015_0-502";""
+"34,100";"1,77";"2,68";"109,61";"131";"02.09.2004";"Schöna";"107,28";"FP-2015_0-502";""
+"34,200";"1,96";"2,64";"109,59";"131";"02.09.2004";"Schöna";"107,24";"FP-2015_0-502";""
+"34,300";"1,62";"3,06";"109,55";"131";"02.09.2004";"Schöna";"107,26";"FP-2015_0-502";""
+"34,400";"1,85";"3,10";"109,49";"131";"02.09.2004";"Schöna";"107,11";"FP-2015_0-502";""
+"34,500";"1,91";"2,58";"109,44";"131";"02.09.2004";"Schöna";"107,19";"FP-2015_0-502";""
+"34,600";"1,96";"2,42";"109,40";"131";"02.09.2004";"Schöna";"107,19";"FP-2015_0-502";""
+"34,700";"1,79";"2,25";"109,37";"131";"02.09.2004";"Schöna";"107,32";"FP-2015_0-502";""
+"34,800";"1,69";"2,48";"109,34";"131";"02.09.2004";"Schöna";"107,36";"FP-2015_0-502";"Schwebstoffmessstelle: Pirna (seit 03/2002 a.B.)"
+"34,900";"1,57";"2,73";"109,31";"131";"02.09.2004";"Schöna";"107,25";"FP-2015_0-502";""
+"35,000";"1,47";"2,89";"109,28";"131";"02.09.2004";"Schöna";"107,11";"FP-2015_0-502";""
+"35,100";"1,74";"2,79";"109,26";"131";"02.09.2004";"Schöna";"107,08";"FP-2015_0-502";""
+"35,200";"1,81";"2,71";"109,24";"131";"02.09.2004";"Schöna";"107,10";"FP-2015_0-502";""
+"35,300";"1,73";"2,97";"109,22";"131";"02.09.2004";"Schöna";"106,77";"FP-2015_0-502";""
+"35,400";"1,74";"2,90";"109,21";"131";"02.09.2004";"Schöna";"106,79";"FP-2015_0-502";"Zufluss: Gottleuba"
+"35,500";"1,97";"2,76";"109,20";"131";"02.09.2004";"Schöna";"106,89";"FP-2015_0-502";""
+"35,600";"2,10";"2,66";"109,19";"131";"02.09.2004";"Schöna";"106,87";"FP-2015_0-502";""
+"35,700";"2,02";"2,65";"109,18";"131";"02.09.2004";"Schöna";"106,81";"FP-2015_0-502";""
+"35,800";"1,71";"2,47";"109,15";"131";"02.09.2004";"Schöna";"106,98";"FP-2015_0-502";""
+"35,900";"1,66";"2,28";"109,13";"131";"02.09.2004";"Schöna";"107,05";"FP-2015_0-502";""
+"36,000";"1,64";"2,12";"109,09";"131";"02.09.2004";"Schöna";"107,15";"FP-2015_0-502";"Brücke: Sachsenbrücke"
+"36,100";"1,35";"2,16";"109,05";"131";"02.09.2004";"Schöna";"107,17";"FP-2015_0-502";""
+"36,200";"1,23";"2,39";"109,01";"131";"02.09.2004";"Schöna";"107,14";"FP-2015_0-502";""
+"36,300";"1,25";"2,50";"108,97";"131";"02.09.2004";"Schöna";"107,01";"FP-2015_0-502";""
+"36,400";"1,52";"2,55";"108,94";"131";"02.09.2004";"Schöna";"106,73";"FP-2015_0-502";""
+"36,500";"1,70";"2,75";"108,91";"131";"02.09.2004";"Schöna";"106,68";"FP-2015_0-502";""
+"36,600";"1,78";"3,09";"108,89";"131";"02.09.2004";"Schöna";"106,50";"FP-2015_0-502";""
+"36,700";"1,67";"3,11";"108,86";"131";"02.09.2004";"Schöna";"106,44";"FP-2015_0-502";""
+"36,800";"1,33";"2,75";"108,83";"131";"02.09.2004";"Schöna";"106,79";"FP-2015_0-502";""
+"36,900";"1,52";"2,38";"108,80";"131";"02.09.2004";"Schöna";"106,90";"FP-2015_0-502";""
+"37,000";"1,52";"2,22";"108,76";"131";"02.09.2004";"Schöna";"106,86";"FP-2015_0-502";""
+"37,100";"1,55";"2,18";"108,73";"131";"02.09.2004";"Schöna";"106,81";"FP-2015_0-502";""
+"37,200";"1,47";"2,98";"108,69";"131";"02.09.2004";"Schöna";"106,76";"FP-2015_0-502";""
+"37,300";"1,19";"2,29";"108,66";"131";"02.09.2004";"Schöna";"106,80";"FP-2015_0-502";""
+"37,400";"1,21";"2,26";"108,64";"131";"02.09.2004";"Schöna";"106,75";"FP-2015_0-502";"Zufluss: Wesenitz"
+"37,500";"1,31";"2,36";"108,61";"131";"02.09.2004";"Schöna";"106,67";"FP-2015_0-502";""
+"37,600";"1,29";"2,23";"108,57";"131";"02.09.2004";"Schöna";"106,64";"FP-2015_0-502";""
+"37,700";"1,29";"2,13";"108,54";"131";"02.09.2004";"Schöna";"106,66";"FP-2015_0-502";""
+"37,800";"1,47";"2,05";"108,50";"131";"02.09.2004";"Schöna";"106,68";"FP-2015_0-502";""
+"37,900";"1,59";"1,92";"108,46";"131";"02.09.2004";"Schöna";"106,66";"FP-2015_0-502";""
+"38,000";"1,61";"1,92";"108,43";"131";"02.09.2004";"Schöna";"106,66";"FP-2015_0-502";""
+"38,100";"1,53";"1,92";"108,40";"131";"02.09.2004";"Schöna";"106,62";"FP-2015_0-502";""
+"38,200";"1,54";"2,24";"108,37";"131";"02.09.2004";"Schöna";"106,52";"FP-2015_0-502";""
+"38,300";"1,49";"2,22";"108,35";"131";"02.09.2004";"Schöna";"106,44";"FP-2015_0-502";""
+"38,400";"1,52";"2,25";"108,33";"131";"02.09.2004";"Schöna";"106,35";"FP-2015_0-502";"Gemeinde: Heidenau"
+"38,500";"1,66";"2,30";"108,32";"131";"02.09.2004";"Schöna";"106,28";"FP-2015_0-502";""
+"38,600";"1,57";"2,35";"108,30";"131";"02.09.2004";"Schöna";"106,29";"FP-2015_0-502";""
+"38,700";"1,44";"2,44";"108,28";"131";"02.09.2004";"Schöna";"106,34";"FP-2015_0-502";""
+"38,800";"1,43";"2,36";"108,26";"131";"02.09.2004";"Schöna";"106,23";"FP-2015_0-502";""
+"38,900";"1,32";"2,86";"108,24";"131";"02.09.2004";"Schöna";"106,06";"FP-2015_0-502";""
+"39,000";"1,24";"2,95";"108,22";"131";"02.09.2004";"Schöna";"105,93";"FP-2015_0-502";""
+"39,100";"1,46";"2,31";"108,20";"131";"02.09.2004";"Schöna";"106,27";"FP-2015_0-502";""
+"39,200";"1,19";"2,07";"108,16";"131";"02.09.2004";"Schöna";"106,38";"FP-2015_0-502";"Zufluss: Müglitz"
+"39,300";"1,49";"2,29";"108,12";"138";"02.09.2004";"außerh. d. Bez.pegels";"106,20";"FP-2015_0-502";""
+"39,400";"1,21";"2,28";"108,08";"138";"02.09.2004";"außerh. d. Bez.pegels";"106,08";"FP-2015_0-502";""
+"39,500";"1,67";"2,19";"108,05";"138";"02.09.2004";"außerh. d. Bez.pegels";"106,08";"FP-2015_0-502";""
+"39,600";"1,74";"2,46";"108,02";"138";"02.09.2004";"außerh. d. Bez.pegels";"106,02";"FP-2015_0-502";""
+"39,700";"1,46";"2,58";"108,00";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,76";"FP-2015_0-502";""
+"39,800";"1,51";"2,56";"107,98";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,74";"FP-2015_0-502";""
+"39,900";"1,45";"2,61";"107,95";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,69";"FP-2015_0-502";""
+"40,000";"1,27";"3,06";"107,92";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,63";"FP-2015_0-502";""
+"40,100";"1,36";"2,98";"107,89";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,52";"FP-2015_0-502";""
+"40,200";"1,26";"2,54";"107,85";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,78";"FP-2015_0-502";""
+"40,300";"1,11";"2,37";"107,82";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,83";"FP-2015_0-502";"Gemeinde: Stadt Dresden"
+"40,400";"1,19";"2,28";"107,79";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,80";"FP-2015_0-502";""
+"40,500";"1,32";"2,30";"107,75";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,73";"FP-2015_0-502";""
+"40,600";"1,44";"2,32";"107,73";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,74";"FP-2015_0-502";""
+"40,700";"1,53";"2,31";"107,70";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,70";"FP-2015_0-502";""
+"40,800";"1,56";"2,11";"107,67";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,71";"FP-2015_0-502";""
+"40,900";"1,53";"2,07";"107,64";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,75";"FP-2015_0-502";""
+"41,000";"1,66";"2,12";"107,62";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,75";"FP-2015_0-502";"Gemeinde: Zschieren"
+"41,100";"1,66";"2,08";"107,60";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,76";"FP-2015_0-502";""
+"41,200";"1,70";"2,38";"107,59";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,65";"FP-2015_0-502";"Gemeinde: Söbringen"
+"41,300";"1,84";"2,54";"107,58";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,47";"FP-2015_0-502";""
+"41,400";"1,92";"2,64";"107,56";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,18";"FP-2015_0-502";""
+"41,500";"1,74";"2,64";"107,54";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,19";"FP-2015_0-502";""
+"41,600";"1,64";"2,45";"107,52";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,34";"FP-2015_0-502";""
+"41,700";"1,61";"2,35";"107,49";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,33";"FP-2015_0-502";""
+"41,800";"1,78";"2,27";"107,46";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,37";"FP-2015_0-502";""
+"41,900";"1,66";"2,81";"107,43";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,50";"FP-2015_0-502";""
+"42,000";"1,65";"2,75";"107,40";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,29";"FP-2015_0-502";"Insel Pillnitz"
+"42,100";"1,54";"2,49";"107,36";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,35";"FP-2015_0-502";""
+"42,200";"1,56";"2,40";"107,33";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,28";"FP-2015_0-502";""
+"42,300";"1,76";"2,39";"107,31";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,15";"FP-2015_0-502";""
+"42,400";"1,50";"2,43";"107,28";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,08";"FP-2015_0-502";""
+"42,500";"1,58";"3,09";"107,25";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,86";"FP-2015_0-502";""
+"42,600";"1,78";"3,41";"107,22";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,79";"FP-2015_0-502";"Gemeinde: Pillnitz"
+"42,700";"1,27";"3,07";"107,18";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,76";"FP-2015_0-502";""
+"42,800";"0,94";"3,02";"107,14";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,89";"FP-2015_0-502";""
+"42,900";"0,98";"3,37";"107,09";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,60";"FP-2015_0-502";""
+"43,000";"1,22";"3,05";"107,05";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,80";"FP-2015_0-502";""
+"43,100";"1,20";"2,68";"107,02";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,12";"FP-2015_0-502";""
+"43,200";"1,45";"2,39";"107,00";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,99";"FP-2015_0-502";""
+"43,300";"1,89";"2,45";"106,98";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,78";"FP-2015_0-502";""
+"43,400";"1,60";"2,44";"106,95";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,83";"FP-2015_0-502";""
+"43,500";"1,54";"2,00";"106,93";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,14";"FP-2015_0-502";"Fähre: -Auto+Personen"
+"43,600";"1,66";"2,27";"106,89";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,97";"FP-2015_0-502";"Gemeinde: Kleinzschachwitz"
+"43,700";"1,37";"2,15";"106,86";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,98";"FP-2015_0-502";""
+"43,800";"1,55";"1,98";"106,83";"138";"02.09.2004";"außerh. d. Bez.pegels";"105,01";"FP-2015_0-502";""
+"43,900";"1,64";"2,09";"106,80";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,94";"FP-2015_0-502";""
+"44,000";"1,56";"2,14";"106,76";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,84";"FP-2015_0-502";""
+"44,100";"1,54";"2,12";"106,73";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,81";"FP-2015_0-502";""
+"44,200";"1,51";"2,10";"106,70";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,82";"FP-2015_0-502";""
+"44,300";"1,58";"2,06";"106,66";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,83";"FP-2015_0-502";""
+"44,400";"1,62";"1,96";"106,64";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,87";"FP-2015_0-502";""
+"44,500";"1,62";"1,98";"106,62";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,81";"FP-2015_0-502";""
+"44,600";"1,59";"1,96";"106,59";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,82";"FP-2015_0-502";""
+"44,700";"1,62";"1,99";"106,56";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,79";"FP-2015_0-502";"Zufluss: Lockwitzbach"
+"44,800";"1,63";"2,21";"106,53";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,65";"FP-2015_0-502";""
+"44,900";"1,61";"2,24";"106,49";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,47";"FP-2015_0-502";""
+"45,000";"1,50";"2,13";"106,46";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,61";"FP-2015_0-502";""
+"45,100";"1,50";"2,09";"106,42";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,61";"FP-2015_0-502";""
+"45,200";"1,57";"2,21";"106,39";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,57";"FP-2015_0-502";""
+"45,300";"1,59";"2,08";"106,36";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,50";"FP-2015_0-502";""
+"45,400";"1,61";"2,10";"106,32";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,42";"FP-2015_0-502";""
+"45,500";"1,58";"2,09";"106,29";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,46";"FP-2015_0-502";""
+"45,600";"1,55";"2,19";"106,26";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,41";"FP-2015_0-502";""
+"45,700";"1,51";"2,28";"106,23";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,24";"FP-2015_0-502";""
+"45,800";"1,57";"2,50";"106,20";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,07";"FP-2015_0-502";""
+"45,900";"1,74";"2,48";"106,17";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,02";"FP-2015_0-502";""
+"46,000";"1,81";"2,32";"106,14";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,02";"FP-2015_0-502";""
+"46,100";"1,91";"2,27";"106,12";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,01";"FP-2015_0-502";""
+"46,200";"1,77";"2,41";"106,10";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,08";"FP-2015_0-502";""
+"46,300";"1,77";"2,35";"106,08";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,06";"FP-2015_0-502";""
+"46,400";"1,87";"2,50";"106,06";"138";"02.09.2004";"außerh. d. Bez.pegels";"104,00";"FP-2015_0-502";""
+"46,500";"1,64";"2,51";"106,04";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,92";"FP-2015_0-502";""
+"46,600";"1,59";"2,54";"106,02";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,91";"FP-2015_0-502";"Fähre: Niederpoyritz -Personen"
+"46,700";"1,84";"2,41";"105,99";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,84";"FP-2015_0-502";""
+"46,800";"1,40";"2,78";"105,97";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,66";"FP-2015_0-502";""
+"46,900";"1,91";"2,85";"105,94";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,52";"FP-2015_0-502";""
+"47,000";"1,92";"2,69";"105,92";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,60";"FP-2015_0-502";""
+"47,100";"1,55";"3,27";"105,90";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,50";"FP-2015_0-502";"Gemeinde: Wachwitz"
+"47,200";"1,43";"3,15";"105,87";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,49";"FP-2015_0-502";"Zufluss: Tolkewitzer Landgraben"
+"47,300";"1,57";"3,29";"105,85";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,38";"FP-2015_0-502";""
+"47,400";"1,84";"3,33";"105,83";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,39";"FP-2015_0-502";""
+"47,500";"1,88";"3,43";"105,82";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,39";"FP-2015_0-502";""
+"47,600";"2,23";"2,73";"105,81";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,32";"FP-2015_0-502";""
+"47,700";"2,22";"2,61";"105,80";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,35";"FP-2015_0-502";""
+"47,800";"2,04";"2,72";"105,78";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,44";"FP-2015_0-502";""
+"47,900";"1,73";"2,70";"105,76";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,53";"FP-2015_0-502";""
+"48,000";"1,67";"2,57";"105,74";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,66";"FP-2015_0-502";""
+"48,100";"1,68";"2,25";"105,72";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,75";"FP-2015_0-502";""
+"48,200";"1,75";"2,18";"105,71";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,77";"FP-2015_0-502";""
+"48,300";"1,74";"2,28";"105,68";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,66";"FP-2015_0-502";""
+"48,400";"1,62";"2,26";"105,66";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,60";"FP-2015_0-502";""
+"48,500";"1,69";"2,22";"105,62";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,66";"FP-2015_0-502";""
+"48,600";"1,72";"2,23";"105,59";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,58";"FP-2015_0-502";""
+"48,700";"1,70";"2,16";"105,55";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,54";"FP-2015_0-502";""
+"48,800";"1,81";"2,42";"105,52";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,43";"FP-2015_0-502";""
+"48,900";"1,56";"2,24";"105,50";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,41";"FP-2015_0-502";""
+"49,000";"1,69";"2,15";"105,47";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,49";"FP-2015_0-502";""
+"49,100";"1,72";"2,13";"105,45";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,57";"FP-2015_0-502";""
+"49,200";"1,71";"2,21";"105,43";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,52";"FP-2015_0-502";""
+"49,300";"1,52";"2,18";"105,41";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,46";"FP-2015_0-502";""
+"49,400";"1,51";"2,24";"105,38";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,28";"FP-2015_0-502";""
+"49,500";"1,64";"2,21";"105,36";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,35";"FP-2015_0-502";""
+"49,600";"1,58";"2,62";"105,34";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,40";"FP-2015_0-502";"Gemeinde: Loschwitz"
+"49,700";"1,88";"2,87";"105,33";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,88";"FP-2015_0-502";"Gemeinde: Blasewitz"
+"49,800";"2,17";"2,91";"105,32";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,67";"FP-2015_0-502";""
+"49,900";"2,02";"2,67";"105,31";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,03";"FP-2015_0-502";""
+"50,000";"1,76";"2,24";"105,30";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,31";"FP-2015_0-502";""
+"50,100";"1,72";"2,16";"105,29";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,33";"FP-2015_0-502";""
+"50,200";"1,70";"2,06";"105,26";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,37";"FP-2015_0-502";""
+"50,300";"1,54";"2,18";"105,24";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,29";"FP-2015_0-502";""
+"50,400";"1,72";"2,68";"105,20";"138";"02.09.2004";"außerh. d. Bez.pegels";"103,06";"FP-2015_0-502";"Hafen: Loschwitz -Sportboot"
+"50,500";"1,68";"2,67";"105,15";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,95";"FP-2015_0-502";""
+"50,600";"1,76";"2,95";"105,12";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,76";"FP-2015_0-502";""
+"50,700";"1,92";"2,93";"105,10";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,67";"FP-2015_0-502";""
+"50,800";"1,78";"2,93";"105,09";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,74";"FP-2015_0-502";""
+"50,900";"1,77";"2,86";"105,08";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,81";"FP-2015_0-502";""
+"51,000";"1,70";"2,88";"105,06";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,73";"FP-2015_0-502";""
+"51,100";"1,56";"2,48";"105,04";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,88";"FP-2015_0-502";""
+"51,200";"1,53";"2,62";"105,01";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,87";"FP-2015_0-502";""
+"51,300";"1,52";"2,49";"104,98";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,91";"FP-2015_0-502";""
+"51,400";"1,48";"2,48";"104,95";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,96";"FP-2015_0-502";""
+"51,500";"1,59";"2,34";"104,93";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,91";"FP-2015_0-502";""
+"51,600";"1,72";"2,62";"104,90";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,80";"FP-2015_0-502";""
+"51,700";"1,72";"2,24";"104,87";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,87";"FP-2015_0-502";""
+"51,800";"1,64";"2,29";"104,84";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,82";"FP-2015_0-502";""
+"51,900";"1,77";"2,16";"104,81";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,82";"FP-2015_0-502";"Gemeinde: Saloppe"
+"52,000";"1,70";"2,08";"104,78";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,85";"FP-2015_0-502";""
+"52,100";"1,59";"2,28";"104,74";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,78";"FP-2015_0-502";""
+"52,200";"1,50";"2,36";"104,70";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,62";"FP-2015_0-502";""
+"52,300";"1,51";"2,31";"104,67";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,56";"FP-2015_0-502";""
+"52,400";"1,65";"2,33";"104,64";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,49";"FP-2015_0-502";""
+"52,500";"1,59";"2,50";"104,62";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,49";"FP-2015_0-502";""
+"52,600";"1,59";"2,54";"104,59";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,39";"FP-2015_0-502";""
+"52,700";"1,67";"2,41";"104,55";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,42";"FP-2015_0-502";""
+"52,800";"1,74";"2,47";"104,51";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,43";"FP-2015_0-502";""
+"52,900";"1,62";"2,38";"104,48";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,40";"FP-2015_0-502";""
+"53,000";"1,59";"2,41";"104,46";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,47";"FP-2015_0-502";""
+"53,100";"1,17";"2,69";"104,43";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,43";"FP-2015_0-502";""
+"53,200";"1,71";"2,43";"104,40";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,45";"FP-2015_0-502";""
+"53,300";"1,63";"2,26";"104,37";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,36";"FP-2015_0-502";""
+"53,400";"1,84";"2,86";"104,35";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,23";"FP-2015_0-502";""
+"53,500";"1,79";"3,19";"104,33";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,77";"FP-2015_0-502";"Fähre: Dresden-Johannstadt -Personen"
+"53,600";"2,03";"3,18";"104,32";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,64";"FP-2015_0-502";""
+"53,700";"1,32";"2,98";"104,31";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,76";"FP-2015_0-502";"Zufluss: Prießnitz"
+"53,800";"1,32";"2,97";"104,30";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,83";"FP-2015_0-502";""
+"53,900";"1,73";"2,67";"104,28";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,04";"FP-2015_0-502";""
+"54,000";"1,73";"2,52";"104,26";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,02";"FP-2015_0-502";""
+"54,100";"1,72";"2,41";"104,24";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,01";"FP-2015_0-502";""
+"54,200";"1,61";"2,19";"104,21";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,23";"FP-2015_0-502";""
+"54,300";"1,56";"2,08";"104,18";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,35";"FP-2015_0-502";""
+"54,400";"1,13";"2,73";"104,13";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,19";"FP-2015_0-502";""
+"54,500";"1,45";"2,55";"104,09";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,99";"FP-2015_0-502";""
+"54,600";"1,49";"2,29";"104,06";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,18";"FP-2015_0-502";""
+"54,700";"1,53";"2,38";"104,03";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,09";"FP-2015_0-502";""
+"54,800";"1,60";"2,43";"104,01";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,08";"FP-2015_0-502";""
+"54,900";"1,41";"2,42";"103,98";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,11";"FP-2015_0-502";""
+"55,000";"1,38";"2,52";"103,96";"138";"02.09.2004";"außerh. d. Bez.pegels";"102,03";"FP-2015_0-502";""
+"55,100";"1,25";"2,58";"103,93";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,93";"FP-2015_0-502";""
+"55,200";"1,51";"2,80";"103,91";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,74";"FP-2015_0-502";""
+"55,300";"1,59";"2,64";"103,88";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,71";"FP-2015_0-502";""
+"55,400";"1,47";"2,70";"103,85";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,74";"FP-2015_0-502";""
+"55,500";"1,57";"2,69";"103,81";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,76";"FP-2015_0-502";""
+"55,600";"1,32";"2,58";"103,77";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,77";"FP-2015_0-502";""
+"55,700";"1,59";"2,59";"103,73";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,75";"FP-2015_0-502";""
+"55,800";"1,70";"3,14";"103,70";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,38";"FP-2015_0-502";""
+"55,900";"1,89";"2,54";"103,68";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,47";"FP-2015_0-502";""
+"56,000";"1,69";"2,42";"103,65";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,54";"FP-2015_0-502";""
+"56,100";"1,70";"2,35";"103,62";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,57";"FP-2015_0-502";""
+"56,200";"1,70";"2,33";"103,59";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,54";"FP-2015_0-502";""
+"56,300";"1,67";"2,22";"103,56";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,55";"FP-2015_0-502";""
+"56,400";"1,64";"2,04";"103,53";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,70";"FP-2015_0-502";""
+"56,500";"1,46";"2,91";"103,48";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,38";"FP-2015_0-502";""
+"56,600";"1,39";"2,33";"103,44";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,37";"FP-2015_0-502";""
+"56,700";"1,62";"2,22";"103,39";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,37";"FP-2015_0-502";""
+"56,800";"1,76";"2,24";"103,36";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,30";"FP-2015_0-502";""
+"56,900";"1,75";"2,19";"103,33";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,29";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-3"
+"57,000";"1,77";"2,19";"103,30";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,31";"FP-2015_0-502";""
+"57,100";"1,71";"2,33";"103,28";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,22";"FP-2015_0-502";""
+"57,200";"1,85";"2,30";"103,25";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,15";"FP-2015_0-502";""
+"57,300";"1,61";"2,53";"103,23";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,11";"FP-2015_0-502";"Hafen: Dresden-Neustadt"
+"57,400";"1,57";"2,63";"103,21";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,02";"FP-2015_0-502";""
+"57,500";"1,69";"2,36";"103,18";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,12";"FP-2015_0-502";""
+"57,600";"1,78";"2,56";"103,16";"138";"02.09.2004";"außerh. d. Bez.pegels";"101,15";"FP-2015_0-502";""
+"57,700";"1,89";"2,69";"103,15";"138";"02.09.2004";"außerh. d. Bez.pegels";"100,86";"FP-2015_0-502";""
+"57,800";"2,00";"2,84";"103,14";"138";"02.09.2004";"außerh. d. Bez.pegels";"100,56";"FP-2015_0-502";"Geschiebemessstelle: Dresden"
+"57,900";"2,00";"2,71";"103,14";"138";"02.09.2004";"außerh. d. Bez.pegels";"100,75";"FP-2015_0-502";""
+"58,000";"2,02";"2,61";"103,13";"138";"02.09.2004";"außerh. d. Bez.pegels";"100,82";"FP-2015_0-502";""
+""
+"##METADATEN PEILUNG"
+"# Jahr der Peilung: 2015"
+"# Aufnahmeart: Flächenpeilung"
+"# Auswerter: BfG"
+"# Lagesystem: LS 150 oder LS 100 "
+"# Höhensystem: NHN "
+"# ursprüngliches Höhensystem: NHN"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: 03.09.2004 "
+"# Bezugspegel: Dresden"
+"# Jahr/Zeitraum der Wasserspiegellage: 2004"
+""
+"55,300";"1,53";"2,58";"103,82";"138";"03.09.2004";"Dresden";"101,71";"FP-2015_0-502";""
+"55,400";"1,40";"2,63";"103,78";"138";"03.09.2004";"Dresden";"101,74";"FP-2015_0-502";""
+"55,500";"1,50";"2,62";"103,74";"138";"03.09.2004";"Dresden";"101,76";"FP-2015_0-502";""
+"55,600";"1,26";"2,52";"103,71";"138";"03.09.2004";"Dresden";"101,77";"FP-2015_0-502";""
+"55,700";"1,53";"2,53";"103,67";"138";"03.09.2004";"Dresden";"101,75";"FP-2015_0-502";""
+"55,800";"1,64";"3,08";"103,64";"138";"03.09.2004";"Dresden";"101,38";"FP-2015_0-502";""
+"55,900";"1,83";"2,48";"103,62";"138";"03.09.2004";"Dresden";"101,47";"FP-2015_0-502";""
+"56,000";"1,63";"2,36";"103,59";"138";"03.09.2004";"Dresden";"101,54";"FP-2015_0-502";""
+"56,100";"1,63";"2,28";"103,55";"138";"03.09.2004";"Dresden";"101,57";"FP-2015_0-502";""
+"56,200";"1,63";"2,26";"103,52";"138";"03.09.2004";"Dresden";"101,54";"FP-2015_0-502";""
+"56,300";"1,60";"2,15";"103,49";"138";"03.09.2004";"Dresden";"101,55";"FP-2015_0-502";""
+"56,400";"1,56";"1,96";"103,45";"138";"03.09.2004";"Dresden";"101,70";"FP-2015_0-502";""
+"56,500";"1,39";"2,84";"103,41";"138";"03.09.2004";"Dresden";"101,38";"FP-2015_0-502";""
+"56,600";"1,31";"2,25";"103,36";"138";"03.09.2004";"Dresden";"101,37";"FP-2015_0-502";""
+"56,700";"1,55";"2,15";"103,32";"138";"03.09.2004";"Dresden";"101,37";"FP-2015_0-502";""
+"56,800";"1,68";"2,16";"103,28";"138";"03.09.2004";"Dresden";"101,30";"FP-2015_0-502";""
+"56,900";"1,67";"2,11";"103,25";"138";"03.09.2004";"Dresden";"101,29";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-3"
+"57,000";"1,70";"2,12";"103,23";"138";"03.09.2004";"Dresden";"101,31";"FP-2015_0-502";""
+"57,100";"1,63";"2,25";"103,20";"138";"03.09.2004";"Dresden";"101,22";"FP-2015_0-502";""
+"57,200";"1,78";"2,23";"103,18";"138";"03.09.2004";"Dresden";"101,15";"FP-2015_0-502";""
+"57,300";"1,53";"2,45";"103,15";"138";"03.09.2004";"Dresden";"101,11";"FP-2015_0-502";"Hafen: Dresden-Neustadt"
+"57,400";"1,49";"2,55";"103,13";"138";"03.09.2004";"Dresden";"101,02";"FP-2015_0-502";""
+"57,500";"1,62";"2,29";"103,11";"138";"03.09.2004";"Dresden";"101,12";"FP-2015_0-502";""
+"57,600";"1,71";"2,49";"103,09";"138";"03.09.2004";"Dresden";"101,15";"FP-2015_0-502";""
+"57,700";"1,82";"2,62";"103,08";"138";"03.09.2004";"Dresden";"100,86";"FP-2015_0-502";""
+"57,800";"1,93";"2,77";"103,07";"138";"03.09.2004";"Dresden";"100,56";"FP-2015_0-502";"Geschiebemessstelle: Dresden"
+"57,900";"1,92";"2,63";"103,06";"138";"03.09.2004";"Dresden";"100,75";"FP-2015_0-502";""
+"58,000";"1,94";"2,53";"103,05";"138";"03.09.2004";"Dresden";"100,82";"FP-2015_0-502";""
+"58,100";"1,75";"2,81";"103,04";"138";"03.09.2004";"Dresden";"100,66";"FP-2015_0-502";""
+"58,200";"1,84";"2,48";"103,03";"138";"03.09.2004";"Dresden";"100,83";"FP-2015_0-502";""
+"58,300";"1,72";"2,36";"103,01";"138";"03.09.2004";"Dresden";"100,86";"FP-2015_0-502";""
+"58,400";"1,62";"2,36";"103,00";"138";"03.09.2004";"Dresden";"100,84";"FP-2015_0-502";""
+"58,500";"1,84";"2,51";"102,98";"138";"03.09.2004";"Dresden";"100,72";"FP-2015_0-502";"ABz: Dresden"
+"58,600";"1,83";"2,88";"102,96";"138";"03.09.2004";"Dresden";"100,53";"FP-2015_0-502";""
+"58,700";"1,70";"2,79";"102,94";"138";"03.09.2004";"Dresden";"100,58";"FP-2015_0-502";""
+"58,800";"1,67";"2,73";"102,91";"138";"03.09.2004";"Dresden";"100,55";"FP-2015_0-502";""
+"58,900";"1,39";"2,92";"102,88";"138";"03.09.2004";"Dresden";"100,53";"FP-2015_0-502";""
+"59,000";"1,22";"2,74";"102,85";"138";"03.09.2004";"Dresden";"100,63";"FP-2015_0-502";""
+"59,100";"1,23";"2,72";"102,82";"138";"03.09.2004";"Dresden";"100,66";"FP-2015_0-502";""
+"59,200";"1,36";"2,64";"102,79";"138";"03.09.2004";"Dresden";"100,62";"FP-2015_0-502";""
+"59,300";"1,41";"2,87";"102,76";"138";"03.09.2004";"Dresden";"100,48";"FP-2015_0-502";""
+"59,400";"1,45";"2,63";"102,73";"138";"03.09.2004";"Dresden";"100,59";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-4"
+"59,500";"1,42";"2,26";"102,70";"138";"03.09.2004";"Dresden";"100,81";"FP-2015_0-502";""
+"59,600";"1,38";"2,17";"102,66";"138";"03.09.2004";"Dresden";"100,78";"FP-2015_0-502";""
+"59,700";"1,47";"2,26";"102,62";"138";"03.09.2004";"Dresden";"100,68";"FP-2015_0-502";""
+"59,800";"1,47";"2,31";"102,59";"138";"03.09.2004";"Dresden";"100,62";"FP-2015_0-502";""
+"59,900";"1,33";"2,37";"102,54";"138";"03.09.2004";"Dresden";"100,54";"FP-2015_0-502";""
+"60,000";"1,27";"2,45";"102,50";"138";"03.09.2004";"Dresden";"100,53";"FP-2015_0-502";""
+"60,100";"1,49";"2,66";"102,47";"138";"03.09.2004";"Dresden";"100,41";"FP-2015_0-502";""
+"60,200";"1,66";"2,59";"102,45";"138";"03.09.2004";"Dresden";"100,47";"FP-2015_0-502";""
+"60,300";"1,63";"2,09";"102,43";"138";"03.09.2004";"Dresden";"100,60";"FP-2015_0-502";""
+"60,400";"1,66";"2,24";"102,42";"138";"03.09.2004";"Dresden";"100,45";"FP-2015_0-502";""
+"60,500";"1,52";"2,27";"102,40";"138";"03.09.2004";"Dresden";"100,36";"FP-2015_0-502";""
+"60,600";"1,80";"2,67";"102,39";"138";"03.09.2004";"Dresden";"100,24";"FP-2015_0-502";""
+"60,700";"1,94";"2,81";"102,38";"138";"03.09.2004";"Dresden";"100,09";"FP-2015_0-502";""
+"60,800";"1,77";"2,59";"102,36";"138";"03.09.2004";"Dresden";"100,17";"FP-2015_0-502";"Gemeinde: Micken-uibigau"
+"60,900";"1,82";"2,54";"102,34";"138";"03.09.2004";"Dresden";"100,18";"FP-2015_0-502";""
+"61,000";"1,47";"2,67";"102,32";"138";"03.09.2004";"Dresden";"100,24";"FP-2015_0-502";""
+"61,100";"1,46";"2,86";"102,29";"138";"03.09.2004";"Dresden";"100,26";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-5"
+"61,200";"1,63";"2,49";"102,27";"138";"03.09.2004";"Dresden";"100,12";"FP-2015_0-502";""
+"61,300";"1,72";"2,54";"102,25";"138";"03.09.2004";"Dresden";"100,11";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-6"
+"61,400";"1,79";"2,34";"102,23";"138";"03.09.2004";"Dresden";"100,10";"FP-2015_0-502";""
+"61,500";"1,62";"2,39";"102,21";"138";"03.09.2004";"Dresden";"100,03";"FP-2015_0-502";""
+"61,600";"1,80";"2,59";"102,19";"138";"03.09.2004";"Dresden";"99,97";"FP-2015_0-502";""
+"61,700";"1,79";"2,54";"102,17";"138";"03.09.2004";"Dresden";"100,03";"FP-2015_0-502";""
+"61,800";"1,62";"2,53";"102,15";"138";"03.09.2004";"Dresden";"99,99";"FP-2015_0-502";""
+"61,900";"1,51";"2,54";"102,12";"138";"03.09.2004";"Dresden";"100,02";"FP-2015_0-502";""
+"62,000";"1,36";"2,44";"102,09";"138";"03.09.2004";"Dresden";"100,04";"FP-2015_0-502";""
+"62,100";"1,16";"2,34";"102,05";"138";"03.09.2004";"Dresden";"100,09";"FP-2015_0-502";""
+"62,200";"1,18";"2,29";"102,02";"138";"03.09.2004";"Dresden";"100,11";"FP-2015_0-502";""
+"62,300";"1,28";"2,40";"101,99";"138";"03.09.2004";"Dresden";"100,05";"FP-2015_0-502";""
+"62,400";"1,38";"2,44";"101,95";"138";"03.09.2004";"Dresden";"99,91";"FP-2015_0-502";""
+"62,500";"1,38";"2,92";"101,93";"138";"03.09.2004";"Dresden";"99,82";"FP-2015_0-502";""
+"62,600";"1,63";"2,40";"101,90";"138";"03.09.2004";"Dresden";"99,89";"FP-2015_0-502";""
+"62,700";"1,51";"2,25";"101,87";"138";"03.09.2004";"Dresden";"99,99";"FP-2015_0-502";""
+"62,800";"1,48";"2,31";"101,84";"138";"03.09.2004";"Dresden";"99,93";"FP-2015_0-502";""
+"62,900";"1,62";"2,41";"101,79";"138";"03.09.2004";"Dresden";"99,80";"FP-2015_0-502";""
+"63,000";"1,21";"2,20";"101,75";"138";"03.09.2004";"Dresden";"99,75";"FP-2015_0-502";"Gemeinde: Kaditz"
+"63,100";"1,35";"2,18";"101,71";"138";"03.09.2004";"Dresden";"99,70";"FP-2015_0-502";""
+"63,200";"1,40";"2,19";"101,68";"138";"03.09.2004";"Dresden";"99,66";"FP-2015_0-502";""
+"63,300";"1,57";"2,17";"101,64";"138";"03.09.2004";"Dresden";"99,66";"FP-2015_0-502";""
+"63,400";"1,61";"2,17";"101,61";"138";"03.09.2004";"Dresden";"99,58";"FP-2015_0-502";""
+"63,500";"1,56";"2,24";"101,58";"138";"03.09.2004";"Dresden";"99,63";"FP-2015_0-502";""
+"63,600";"1,08";"2,56";"101,55";"138";"03.09.2004";"Dresden";"99,48";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-7"
+"63,700";"1,59";"2,52";"101,52";"138";"03.09.2004";"Dresden";"99,44";"FP-2015_0-502";""
+"63,800";"1,28";"2,30";"101,49";"138";"03.09.2004";"Dresden";"99,40";"FP-2015_0-502";""
+"63,900";"1,73";"2,27";"101,46";"138";"03.09.2004";"Dresden";"99,34";"FP-2015_0-502";""
+"64,000";"1,50";"2,34";"101,43";"138";"03.09.2004";"Dresden";"99,34";"FP-2015_0-502";""
+"64,100";"1,50";"2,26";"101,40";"138";"03.09.2004";"Dresden";"99,34";"FP-2015_0-502";""
+"64,200";"1,61";"2,19";"101,37";"138";"03.09.2004";"Dresden";"99,34";"FP-2015_0-502";""
+"64,300";"1,55";"2,29";"101,34";"138";"03.09.2004";"Dresden";"99,31";"FP-2015_0-502";""
+"64,400";"1,72";"2,29";"101,31";"138";"03.09.2004";"Dresden";"99,21";"FP-2015_0-502";""
+"64,500";"1,73";"2,26";"101,28";"138";"03.09.2004";"Dresden";"99,19";"FP-2015_0-502";""
+"64,600";"1,66";"2,17";"101,26";"138";"03.09.2004";"Dresden";"99,20";"FP-2015_0-502";""
+"64,700";"1,68";"2,18";"101,23";"138";"03.09.2004";"Dresden";"99,19";"FP-2015_0-502";""
+"64,800";"1,65";"2,18";"101,20";"138";"03.09.2004";"Dresden";"99,20";"FP-2015_0-502";""
+"64,900";"1,49";"2,28";"101,16";"138";"03.09.2004";"Dresden";"99,15";"FP-2015_0-502";""
+"65,000";"1,64";"2,54";"101,13";"138";"03.09.2004";"Dresden";"99,12";"FP-2015_0-502";""
+"65,100";"1,61";"2,64";"101,10";"138";"03.09.2004";"Dresden";"99,12";"FP-2015_0-502";"Landkreis: Meißen"
+"65,200";"1,53";"2,27";"101,07";"138";"03.09.2004";"Dresden";"99,13";"FP-2015_0-502";""
+"65,300";"1,61";"2,59";"101,03";"138";"03.09.2004";"Dresden";"99,13";"FP-2015_0-502";""
+"65,400";"1,66";"2,55";"101,01";"138";"03.09.2004";"Dresden";"99,06";"FP-2015_0-502";"Gemeinde: Serkowitz"
+"65,500";"1,74";"2,41";"100,98";"138";"03.09.2004";"Dresden";"98,94";"FP-2015_0-502";""
+"65,600";"1,76";"2,48";"100,96";"138";"03.09.2004";"Dresden";"98,92";"FP-2015_0-502";""
+"65,700";"1,69";"2,49";"100,93";"138";"03.09.2004";"Dresden";"99,02";"FP-2015_0-502";""
+"65,800";"1,59";"2,19";"100,90";"138";"03.09.2004";"Dresden";"99,07";"FP-2015_0-502";""
+"65,900";"1,59";"2,40";"100,86";"138";"03.09.2004";"Dresden";"98,92";"FP-2015_0-502";""
+"66,000";"1,64";"2,20";"100,82";"138";"03.09.2004";"Dresden";"98,77";"FP-2015_0-502";""
+"66,100";"1,63";"2,23";"100,79";"138";"03.09.2004";"Dresden";"98,82";"FP-2015_0-502";""
+"66,200";"1,58";"2,12";"100,75";"138";"03.09.2004";"Dresden";"98,80";"FP-2015_0-502";""
+"66,300";"1,64";"2,10";"100,72";"138";"03.09.2004";"Dresden";"98,76";"FP-2015_0-502";""
+"66,400";"1,66";"2,04";"100,70";"138";"03.09.2004";"Dresden";"98,79";"FP-2015_0-502";""
+"66,500";"1,71";"2,20";"100,68";"138";"03.09.2004";"Dresden";"98,77";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-8"
+"66,600";"1,78";"2,22";"100,66";"138";"03.09.2004";"Dresden";"98,68";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-9"
+"66,700";"1,83";"2,62";"100,65";"138";"03.09.2004";"Dresden";"98,43";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-10"
+"66,800";"1,52";"2,72";"100,63";"138";"03.09.2004";"Dresden";"98,30";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-11"
+"66,900";"1,51";"2,57";"100,61";"138";"03.09.2004";"Dresden";"98,40";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-12"
+"67,000";"1,79";"2,44";"100,59";"138";"03.09.2004";"Dresden";"98,56";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-13"
+"67,100";"1,70";"2,04";"100,57";"138";"03.09.2004";"Dresden";"98,71";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-14"
+"67,200";"1,73";"2,41";"100,56";"138";"03.09.2004";"Dresden";"98,55";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-15"
+"67,300";"1,90";"2,61";"100,54";"138";"03.09.2004";"Dresden";"98,19";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-16"
+"67,400";"1,67";"2,62";"100,52";"138";"03.09.2004";"Dresden";"98,12";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-17"
+"67,500";"1,83";"2,53";"100,49";"138";"03.09.2004";"Dresden";"98,13";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-18"
+"67,600";"1,73";"2,46";"100,47";"138";"03.09.2004";"Dresden";"98,24";"FP-2015_0-502";""
+"67,700";"1,72";"2,19";"100,44";"138";"03.09.2004";"Dresden";"98,52";"FP-2015_0-502";""
+"67,800";"1,69";"1,94";"100,42";"138";"03.09.2004";"Dresden";"98,57";"FP-2015_0-502";""
+"67,900";"1,78";"2,20";"100,39";"138";"03.09.2004";"Dresden";"98,39";"FP-2015_0-502";""
+"68,000";"1,96";"2,34";"100,38";"138";"03.09.2004";"Dresden";"98,21";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-19"
+"68,100";"1,97";"2,49";"100,36";"138";"03.09.2004";"Dresden";"98,11";"FP-2015_0-502";"Hafen: Seglerhafen Kötzschenbroda"
+"68,200";"1,95";"2,62";"100,35";"138";"03.09.2004";"Dresden";"98,04";"FP-2015_0-502";""
+"68,300";"1,88";"2,74";"100,34";"138";"03.09.2004";"Dresden";"97,95";"FP-2015_0-502";""
+"68,400";"1,85";"3,02";"100,32";"138";"03.09.2004";"Dresden";"97,88";"FP-2015_0-502";""
+"68,500";"1,87";"3,00";"100,31";"138";"03.09.2004";"Dresden";"97,83";"FP-2015_0-502";""
+"68,600";"1,89";"3,33";"100,29";"138";"03.09.2004";"Dresden";"97,75";"FP-2015_0-502";""
+"68,700";"2,05";"3,46";"100,27";"138";"03.09.2004";"Dresden";"97,60";"FP-2015_0-502";""
+"68,800";"1,91";"2,88";"100,25";"138";"03.09.2004";"Dresden";"97,76";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-20"
+"68,900";"1,74";"3,24";"100,23";"138";"03.09.2004";"Dresden";"97,78";"FP-2015_0-502";""
+"69,000";"1,56";"3,11";"100,21";"138";"03.09.2004";"Dresden";"97,80";"FP-2015_0-502";""
+"69,100";"1,45";"3,13";"100,19";"138";"03.09.2004";"Dresden";"97,86";"FP-2015_0-502";""
+"69,200";"1,46";"3,05";"100,17";"138";"03.09.2004";"Dresden";"97,91";"FP-2015_0-502";""
+"69,300";"1,50";"2,72";"100,15";"138";"03.09.2004";"Dresden";"98,08";"FP-2015_0-502";""
+"69,400";"1,50";"2,23";"100,13";"138";"03.09.2004";"Dresden";"98,31";"FP-2015_0-502";""
+"69,500";"1,54";"2,54";"100,11";"138";"03.09.2004";"Dresden";"98,20";"FP-2015_0-502";""
+"69,600";"1,80";"2,56";"100,10";"138";"03.09.2004";"Dresden";"98,07";"FP-2015_0-502";""
+"69,700";"0,64";"3,08";"100,09";"138";"03.09.2004";"Dresden";"98,03";"FP-2015_0-502";""
+"69,800";"1,20";"3,30";"100,08";"138";"03.09.2004";"Dresden";"97,91";"FP-2015_0-502";""
+"69,900";"1,80";"3,07";"100,07";"138";"03.09.2004";"Dresden";"97,70";"FP-2015_0-502";""
+"70,000";"1,78";"2,88";"100,05";"138";"03.09.2004";"Dresden";"97,72";"FP-2015_0-502";""
+"70,100";"1,41";"2,78";"100,03";"138";"03.09.2004";"Dresden";"97,70";"FP-2015_0-502";""
+"70,200";"1,81";"2,65";"100,01";"138";"03.09.2004";"Dresden";"97,70";"FP-2015_0-502";""
+"70,300";"1,85";"2,48";"99,98";"138";"03.09.2004";"Dresden";"97,70";"FP-2015_0-502";""
+"70,400";"1,68";"2,48";"99,94";"138";"03.09.2004";"Dresden";"97,72";"FP-2015_0-502";""
+"70,500";"1,71";"2,42";"99,92";"138";"03.09.2004";"Dresden";"97,81";"FP-2015_0-502";""
+"70,600";"1,73";"2,30";"99,89";"138";"03.09.2004";"Dresden";"97,83";"FP-2015_0-502";""
+"70,700";"1,70";"2,79";"99,86";"138";"03.09.2004";"Dresden";"97,77";"FP-2015_0-502";""
+"70,800";"1,71";"2,76";"99,83";"138";"03.09.2004";"Dresden";"97,65";"FP-2015_0-502";""
+"70,900";"1,72";"2,55";"99,81";"138";"03.09.2004";"Dresden";"97,65";"FP-2015_0-502";""
+"71,000";"1,80";"2,37";"99,79";"138";"03.09.2004";"Dresden";"97,67";"FP-2015_0-502";"Gemeinde: Coswig"
+"71,100";"1,82";"2,53";"99,77";"138";"03.09.2004";"Dresden";"97,49";"FP-2015_0-502";""
+"71,200";"1,98";"2,51";"99,75";"138";"03.09.2004";"Dresden";"97,49";"FP-2015_0-502";""
+"71,300";"1,89";"2,50";"99,73";"138";"03.09.2004";"Dresden";"97,47";"FP-2015_0-502";""
+"71,400";"1,99";"3,48";"99,71";"138";"03.09.2004";"Dresden";"97,34";"FP-2015_0-502";""
+"71,500";"2,20";"3,74";"99,70";"138";"03.09.2004";"Dresden";"96,81";"FP-2015_0-502";""
+"71,600";"1,96";"3,21";"99,68";"138";"03.09.2004";"Dresden";"97,03";"FP-2015_0-502";""
+"71,700";"1,83";"3,00";"99,66";"138";"03.09.2004";"Dresden";"97,22";"FP-2015_0-502";""
+"71,800";"1,78";"2,58";"99,64";"138";"03.09.2004";"Dresden";"97,46";"FP-2015_0-502";""
+"71,900";"1,74";"2,30";"99,61";"138";"03.09.2004";"Dresden";"97,57";"FP-2015_0-502";""
+"72,000";"1,79";"2,23";"99,58";"138";"03.09.2004";"Dresden";"97,62";"FP-2015_0-502";""
+"72,100";"1,79";"2,16";"99,54";"138";"03.09.2004";"Dresden";"97,55";"FP-2015_0-502";""
+"72,200";"1,68";"2,26";"99,50";"138";"03.09.2004";"Dresden";"97,43";"FP-2015_0-502";""
+"72,300";"1,70";"99,48";"99,48";"138";"03.09.2004";"Dresden";"97,33";"FP-2015_0-502";""
+"72,400";"1,78";"2,98";"99,46";"138";"03.09.2004";"Dresden";"97,12";"FP-2015_0-502";""
+"72,500";"2,00";"3,36";"99,44";"138";"03.09.2004";"Dresden";"96,96";"FP-2015_0-502";""
+"72,600";"1,64";"2,65";"99,42";"138";"03.09.2004";"Dresden";"97,19";"FP-2015_0-502";""
+"72,700";"1,47";"2,49";"99,39";"138";"03.09.2004";"Dresden";"97,28";"FP-2015_0-502";""
+"72,800";"1,62";"2,23";"99,36";"138";"03.09.2004";"Dresden";"97,33";"FP-2015_0-502";""
+"72,900";"1,78";"2,17";"99,32";"138";"03.09.2004";"Dresden";"97,34";"FP-2015_0-502";""
+"73,000";"1,80";"2,16";"99,28";"138";"03.09.2004";"Dresden";"97,31";"FP-2015_0-502";"Hafen: Seglerhafen Coswig-Kötitz"
+"73,100";"1,69";"2,32";"99,25";"138";"03.09.2004";"Dresden";"97,17";"FP-2015_0-502";""
+"73,200";"1,66";"2,30";"99,22";"138";"03.09.2004";"Dresden";"97,15";"FP-2015_0-502";""
+"73,300";"1,82";"2,13";"99,18";"138";"03.09.2004";"Dresden";"97,21";"FP-2015_0-502";""
+"73,400";"1,86";"2,19";"99,14";"138";"03.09.2004";"Dresden";"97,11";"FP-2015_0-502";""
+"73,500";"1,72";"2,30";"99,09";"138";"03.09.2004";"Dresden";"97,13";"FP-2015_0-502";""
+"73,600";"1,71";"2,11";"99,06";"138";"03.09.2004";"Dresden";"97,16";"FP-2015_0-502";""
+"73,700";"1,65";"2,35";"99,02";"138";"03.09.2004";"Dresden";"96,96";"FP-2015_0-502";""
+"73,800";"1,77";"2,84";"98,98";"138";"03.09.2004";"Dresden";"96,68";"FP-2015_0-502";""
+"73,900";"1,65";"2,88";"98,94";"138";"03.09.2004";"Dresden";"96,49";"FP-2015_0-502";""
+"74,000";"1,73";"2,68";"98,91";"138";"03.09.2004";"Dresden";"96,62";"FP-2015_0-502";"Gemeinde: Gauernitz"
+"74,100";"1,48";"2,66";"98,88";"138";"03.09.2004";"Dresden";"96,58";"FP-2015_0-502";""
+"74,200";"1,27";"2,69";"98,85";"138";"03.09.2004";"Dresden";"96,52";"FP-2015_0-502";""
+"74,300";"1,82";"2,64";"98,82";"138";"03.09.2004";"Dresden";"96,61";"FP-2015_0-502";""
+"74,400";"1,74";"2,85";"98,79";"138";"03.09.2004";"Dresden";"96,52";"FP-2015_0-502";""
+"74,500";"1,73";"2,43";"98,75";"138";"03.09.2004";"Dresden";"96,74";"FP-2015_0-502";"Gemeinde: Bockwitz"
+"74,600";"1,50";"2,33";"98,71";"138";"03.09.2004";"Dresden";"96,68";"FP-2015_0-502";""
+"74,700";"1,53";"2,33";"98,67";"138";"03.09.2004";"Dresden";"96,61";"FP-2015_0-502";""
+"74,800";"1,55";"2,34";"98,63";"138";"03.09.2004";"Dresden";"96,54";"FP-2015_0-502";""
+"74,900";"1,54";"2,48";"98,59";"138";"03.09.2004";"Dresden";"96,51";"FP-2015_0-502";""
+"75,000";"1,53";"2,44";"98,55";"138";"03.09.2004";"Dresden";"96,48";"FP-2015_0-502";""
+"75,100";"1,57";"2,25";"98,51";"138";"03.09.2004";"Dresden";"96,50";"FP-2015_0-502";""
+"75,200";"1,62";"2,23";"98,48";"138";"03.09.2004";"Dresden";"96,52";"FP-2015_0-502";""
+"75,300";"1,74";"2,32";"98,44";"138";"03.09.2004";"Dresden";"96,48";"FP-2015_0-502";""
+"75,400";"1,84";"2,21";"98,40";"138";"03.09.2004";"Dresden";"96,41";"FP-2015_0-502";""
+"75,500";"1,90";"2,25";"98,37";"138";"03.09.2004";"Dresden";"96,30";"FP-2015_0-502";""
+"75,600";"1,83";"2,23";"98,33";"138";"03.09.2004";"Dresden";"96,23";"FP-2015_0-502";""
+"75,700";"1,79";"2,33";"98,29";"138";"03.09.2004";"Dresden";"96,22";"FP-2015_0-502";""
+"75,800";"1,60";"2,38";"98,24";"138";"03.09.2004";"Dresden";"96,16";"FP-2015_0-502";""
+"75,900";"1,46";"2,24";"98,20";"138";"03.09.2004";"Dresden";"96,16";"FP-2015_0-502";""
+"76,000";"1,46";"2,35";"98,15";"138";"03.09.2004";"Dresden";"96,14";"FP-2015_0-502";""
+"76,100";"1,67";"2,33";"98,11";"138";"03.09.2004";"Dresden";"96,07";"FP-2015_0-502";""
+"76,200";"1,82";"2,19";"98,06";"138";"03.09.2004";"Dresden";"96,01";"FP-2015_0-502";"Fähre: -Personen"
+"76,300";"1,82";"2,36";"98,02";"138";"03.09.2004";"Dresden";"95,89";"FP-2015_0-502";""
+"76,400";"1,77";"2,52";"97,98";"138";"03.09.2004";"Dresden";"95,78";"FP-2015_0-502";""
+"76,500";"1,68";"2,30";"97,95";"138";"03.09.2004";"Dresden";"95,90";"FP-2015_0-502";""
+"76,600";"1,73";"2,48";"97,91";"138";"03.09.2004";"Dresden";"95,83";"FP-2015_0-502";""
+"76,700";"1,59";"2,36";"97,89";"138";"03.09.2004";"Dresden";"95,80";"FP-2015_0-502";""
+"76,800";"1,66";"2,37";"97,86";"138";"03.09.2004";"Dresden";"95,75";"FP-2015_0-502";""
+"76,900";"1,34";"2,35";"97,83";"138";"03.09.2004";"Dresden";"95,74";"FP-2015_0-502";""
+"77,000";"1,75";"2,43";"97,80";"138";"03.09.2004";"Dresden";"95,70";"FP-2015_0-502";""
+"77,100";"1,59";"2,36";"97,78";"138";"03.09.2004";"Dresden";"95,72";"FP-2015_0-502";""
+"77,200";"1,71";"2,49";"97,76";"138";"03.09.2004";"Dresden";"95,70";"FP-2015_0-502";""
+"77,300";"1,51";"2,36";"97,74";"138";"03.09.2004";"Dresden";"95,69";"FP-2015_0-502";""
+"77,400";"1,51";"2,51";"97,72";"138";"03.09.2004";"Dresden";"95,73";"FP-2015_0-502";""
+"77,500";"1,46";"2,44";"97,69";"138";"03.09.2004";"Dresden";"95,74";"FP-2015_0-502";""
+"77,600";"1,58";"2,38";"97,67";"138";"03.09.2004";"Dresden";"95,66";"FP-2015_0-502";""
+"77,700";"1,76";"2,35";"97,64";"138";"03.09.2004";"Dresden";"95,49";"FP-2015_0-502";""
+"77,800";"1,62";"2,33";"97,61";"138";"03.09.2004";"Dresden";"95,55";"FP-2015_0-502";""
+"77,900";"1,67";"2,06";"97,57";"138";"03.09.2004";"Dresden";"95,70";"FP-2015_0-502";""
+"78,000";"1,67";"1,93";"97,53";"138";"03.09.2004";"Dresden";"95,73";"FP-2015_0-502";""
+"78,100";"1,65";"2,45";"97,50";"138";"03.09.2004";"Dresden";"95,60";"FP-2015_0-502";""
+"78,200";"1,65";"2,41";"97,47";"138";"03.09.2004";"Dresden";"95,42";"FP-2015_0-502";""
+"78,300";"1,49";"2,47";"97,44";"138";"03.09.2004";"Dresden";"95,30";"FP-2015_0-502";""
+"78,400";"1,39";"2,27";"97,41";"138";"03.09.2004";"Dresden";"95,39";"FP-2015_0-502";""
+"78,500";"1,35";"2,38";"97,36";"138";"03.09.2004";"Dresden";"95,38";"FP-2015_0-502";""
+"78,600";"1,30";"2,46";"97,31";"138";"03.09.2004";"Dresden";"95,30";"FP-2015_0-502";""
+"78,700";"1,28";"2,40";"97,26";"138";"03.09.2004";"Dresden";"95,24";"FP-2015_0-502";""
+"78,800";"1,33";"2,31";"97,21";"138";"03.09.2004";"Dresden";"95,26";"FP-2015_0-502";""
+"78,900";"1,53";"2,44";"97,16";"138";"03.09.2004";"Dresden";"95,21";"FP-2015_0-502";""
+"79,000";"1,55";"2,28";"97,11";"138";"03.09.2004";"Dresden";"95,07";"FP-2015_0-502";"Gemeinde: Ober-Spaar"
+"79,100";"1,62";"2,39";"97,07";"138";"03.09.2004";"Dresden";"94,98";"FP-2015_0-502";""
+"79,200";"1,92";"2,39";"97,03";"138";"03.09.2004";"Dresden";"94,86";"FP-2015_0-502";""
+"79,300";"1,81";"2,52";"96,99";"138";"03.09.2004";"Dresden";"94,80";"FP-2015_0-502";""
+"79,400";"1,45";"2,48";"96,96";"138";"03.09.2004";"Dresden";"94,86";"FP-2015_0-502";""
+"79,500";"1,54";"2,68";"96,93";"138";"03.09.2004";"Dresden";"94,76";"FP-2015_0-502";""
+"79,600";"1,88";"2,69";"96,91";"138";"03.09.2004";"Dresden";"94,56";"FP-2015_0-502";""
+"79,700";"1,36";"2,74";"96,90";"138";"03.09.2004";"Dresden";"94,46";"FP-2015_0-502";"Gemeinde: Nieder-Spaar"
+"79,800";"2,14";"2,71";"96,88";"138";"03.09.2004";"Dresden";"94,46";"FP-2015_0-502";""
+"79,900";"2,18";"2,83";"96,87";"138";"03.09.2004";"Dresden";"94,38";"FP-2015_0-502";""
+"80,000";"2,02";"2,99";"96,85";"138";"03.09.2004";"Dresden";"94,18";"FP-2015_0-502";""
+"80,100";"2,23";"2,92";"96,84";"138";"03.09.2004";"Dresden";"94,20";"FP-2015_0-502";""
+"80,200";"1,54";"3,34";"96,82";"138";"03.09.2004";"Dresden";"94,29";"FP-2015_0-502";""
+"80,300";"1,70";"3,10";"96,81";"138";"03.09.2004";"Dresden";"94,37";"FP-2015_0-502";""
+"80,400";"1,29";"3,30";"96,79";"138";"03.09.2004";"Dresden";"94,11";"FP-2015_0-502";""
+"80,500";"1,40";"2,97";"96,77";"138";"03.09.2004";"Dresden";"94,34";"FP-2015_0-502";"Gemeinde: Stadt Meißen"
+"80,600";"1,70";"3,06";"96,74";"138";"03.09.2004";"Dresden";"94,46";"FP-2015_0-502";""
+"80,700";"1,62";"2,45";"96,72";"138";"03.09.2004";"Dresden";"94,80";"FP-2015_0-502";""
+"80,800";"1,61";"2,15";"96,69";"138";"03.09.2004";"Dresden";"94,90";"FP-2015_0-502";""
+"80,900";"1,64";"3,05";"96,66";"138";"03.09.2004";"Dresden";"94,66";"FP-2015_0-502";""
+"81,000";"1,63";"3,19";"96,63";"138";"03.09.2004";"Dresden";"94,33";"FP-2015_0-502";"Gemeinde: Neudörfchen"
+"81,100";"1,76";"3,60";"96,61";"138";"03.09.2004";"Dresden";"94,16";"FP-2015_0-502";""
+"81,200";"1,73";"3,08";"96,58";"138";"03.09.2004";"Dresden";"94,20";"FP-2015_0-502";""
+"81,300";"1,45";"2,83";"96,55";"138";"03.09.2004";"Dresden";"94,26";"FP-2015_0-502";""
+"81,400";"1,45";"2,58";"96,51";"138";"03.09.2004";"Dresden";"94,36";"FP-2015_0-502";""
+"81,500";"1,40";"2,57";"96,47";"138";"03.09.2004";"Dresden";"94,52";"FP-2015_0-502";""
+"81,600";"1,45";"3,15";"96,43";"138";"03.09.2004";"Dresden";"94,41";"FP-2015_0-502";""
+"81,700";"1,58";"2,81";"96,40";"138";"03.09.2004";"Dresden";"94,12";"FP-2015_0-502";""
+"81,800";"1,51";"2,51";"96,38";"138";"03.09.2004";"Dresden";"94,16";"FP-2015_0-502";""
+"81,900";"1,38";"2,56";"96,35";"138";"03.09.2004";"Dresden";"94,41";"FP-2015_0-502";""
+"82,000";"1,53";"3,29";"96,33";"138";"03.09.2004";"Dresden";"94,40";"FP-2015_0-502";""
+"82,100";"1,80";"2,65";"96,30";"138";"03.09.2004";"Dresden";"94,19";"FP-2015_0-502";"Zufluss: Triebisch"
+"82,200";"1,60";"2,63";"96,28";"138";"03.09.2004";"Dresden";"94,25";"FP-2015_0-502";"Pegel: Meißen"
+"82,300";"1,54";"2,45";"96,26";"138";"03.09.2004";"Dresden";"94,33";"FP-2015_0-502";""
+"82,400";"1,71";"2,65";"96,24";"138";"03.09.2004";"Dresden";"94,11";"FP-2015_0-502";"Geschiebemessstelle: Meissen (seit 10/1998 a.B.)"
+"82,500";"1,73";"2,86";"96,22";"138";"03.09.2004";"Dresden";"94,02";"FP-2015_0-502";""
+"82,600";"1,60";"2,34";"96,19";"138";"03.09.2004";"Dresden";"94,11";"FP-2015_0-502";""
+"82,700";"1,66";"2,40";"96,15";"138";"03.09.2004";"Dresden";"94,09";"FP-2015_0-502";""
+"82,800";"1,65";"2,40";"96,11";"138";"03.09.2004";"Dresden";"94,10";"FP-2015_0-502";"HW-Schutz: Deich-Sachsen-21"
+"82,900";"1,62";"2,63";"96,08";"138";"03.09.2004";"Dresden";"93,84";"FP-2015_0-502";"Brücke: Elbtalbrücke"
+"83,000";"1,64";"2,49";"96,05";"138";"03.09.2004";"Dresden";"93,82";"FP-2015_0-502";""
+"83,100";"1,35";"2,43";"96,00";"138";"03.09.2004";"Dresden";"93,92";"FP-2015_0-502";""
+"83,200";"1,23";"2,39";"95,95";"138";"03.09.2004";"Dresden";"93,97";"FP-2015_0-502";""
+"83,300";"1,16";"2,65";"95,90";"138";"03.09.2004";"Dresden";"94,00";"FP-2015_0-502";"Hafen: Meißen -Schutz- und Sicherheitshafen"
+"83,400";"0,99";"2,75";"95,85";"138";"03.09.2004";"Dresden";"93,84";"FP-2015_0-502";""
+"83,500";"1,07";"2,74";"95,81";"138";"03.09.2004";"Dresden";"93,70";"FP-2015_0-502";""
+"83,600";"1,70";"2,47";"95,77";"138";"03.09.2004";"Dresden";"93,66";"FP-2015_0-502";""
+"83,700";"1,82";"2,54";"95,74";"138";"03.09.2004";"Dresden";"93,67";"FP-2015_0-502";""
+"83,800";"1,67";"2,56";"95,71";"138";"03.09.2004";"Dresden";"93,46";"FP-2015_0-502";""
+"83,900";"1,57";"2,65";"95,68";"138";"03.09.2004";"Dresden";"93,46";"FP-2015_0-502";""
+"84,000";"1,63";"2,44";"95,64";"138";"03.09.2004";"Dresden";"93,52";"FP-2015_0-502";""
+"84,100";"1,62";"2,51";"95,59";"138";"03.09.2004";"Dresden";"93,44";"FP-2015_0-502";""
+"84,200";"1,53";"2,44";"95,55";"138";"03.09.2004";"Dresden";"93,43";"FP-2015_0-502";""
+"84,300";"1,61";"2,31";"95,51";"138";"03.09.2004";"Dresden";"93,47";"FP-2015_0-502";""
+"84,400";"1,85";"2,33";"95,48";"138";"03.09.2004";"Dresden";"93,43";"FP-2015_0-502";""
+"84,500";"1,81";"2,61";"95,46";"138";"03.09.2004";"Dresden";"93,18";"FP-2015_0-502";""
+"84,600";"1,90";"2,86";"95,44";"138";"03.09.2004";"Dresden";"93,02";"FP-2015_0-502";""
+"84,700";"2,02";"2,88";"95,43";"138";"03.09.2004";"Dresden";"92,98";"FP-2015_0-502";""
+"84,800";"1,84";"2,60";"95,41";"138";"03.09.2004";"Dresden";"93,07";"FP-2015_0-502";""
+"84,900";"1,75";"2,66";"95,39";"138";"03.09.2004";"Dresden";"93,18";"FP-2015_0-502";""
+"85,000";"1,62";"2,29";"95,37";"138";"03.09.2004";"Dresden";"93,41";"FP-2015_0-502";"Gemeinde: Rottewitz"
+"85,100";"1,77";"2,24";"95,35";"138";"03.09.2004";"Dresden";"93,31";"FP-2015_0-502";""
+"85,200";"1,79";"2,55";"95,33";"138";"03.09.2004";"Dresden";"93,23";"FP-2015_0-502";""
+"85,300";"1,77";"3,14";"95,31";"138";"03.09.2004";"Dresden";"93,06";"FP-2015_0-502";""
+"85,400";"1,96";"3,30";"95,29";"138";"03.09.2004";"Dresden";"92,84";"FP-2015_0-502";""
+"85,500";"2,13";"3,15";"95,28";"138";"03.09.2004";"Dresden";"92,61";"FP-2015_0-502";""
+"85,600";"2,33";"3,11";"95,27";"138";"03.09.2004";"Dresden";"92,48";"FP-2015_0-502";""
+"85,700";"2,34";"3,19";"95,26";"138";"03.09.2004";"Dresden";"92,45";"FP-2015_0-502";""
+"85,800";"2,28";"3,04";"95,25";"138";"03.09.2004";"Dresden";"92,64";"FP-2015_0-502";""
+"85,900";"2,13";"2,81";"95,24";"138";"03.09.2004";"Dresden";"92,67";"FP-2015_0-502";""
+"86,000";"1,72";"2,75";"95,22";"138";"03.09.2004";"Dresden";"92,92";"FP-2015_0-502";""
+"86,100";"1,70";"2,93";"95,20";"138";"03.09.2004";"Dresden";"93,06";"FP-2015_0-502";""
+"86,200";"1,68";"2,44";"95,18";"138";"03.09.2004";"Dresden";"93,06";"FP-2015_0-502";""
+"86,300";"1,67";"2,34";"95,16";"138";"03.09.2004";"Dresden";"93,08";"FP-2015_0-502";""
+"86,400";"1,68";"2,30";"95,13";"138";"03.09.2004";"Dresden";"93,15";"FP-2015_0-502";""
+"86,500";"1,70";"2,37";"95,11";"138";"03.09.2004";"Dresden";"93,24";"FP-2015_0-502";""
+"86,600";"1,82";"2,26";"95,09";"138";"03.09.2004";"Dresden";"93,10";"FP-2015_0-502";""
+"86,700";"1,75";"2,15";"95,06";"138";"03.09.2004";"Dresden";"93,08";"FP-2015_0-502";""
+"86,800";"1,65";"2,23";"95,04";"138";"03.09.2004";"Dresden";"93,08";"FP-2015_0-502";""
+"86,900";"1,63";"2,25";"95,02";"138";"03.09.2004";"Dresden";"93,08";"FP-2015_0-502";""
+"87,000";"1,71";"2,51";"95,00";"138";"03.09.2004";"Dresden";"93,02";"FP-2015_0-502";"Gemeinde: Mischewitz"
+"87,100";"1,68";"2,42";"94,98";"138";"03.09.2004";"Dresden";"93,08";"FP-2015_0-502";""
+"87,200";"1,71";"2,64";"94,97";"138";"03.09.2004";"Dresden";"93,00";"FP-2015_0-502";""
+"87,300";"1,93";"2,60";"94,95";"138";"03.09.2004";"Dresden";"92,76";"FP-2015_0-502";""
+"87,400";"1,98";"2,49";"94,93";"138";"03.09.2004";"Dresden";"92,62";"FP-2015_0-502";""
+"87,500";"1,94";"2,49";"94,90";"138";"03.09.2004";"Dresden";"92,60";"FP-2015_0-502";""
+"87,600";"1,83";"2,71";"94,87";"138";"03.09.2004";"Dresden";"92,55";"FP-2015_0-502";""
+"87,700";"1,72";"2,51";"94,84";"138";"03.09.2004";"Dresden";"92,65";"FP-2015_0-502";""
+"87,800";"1,72";"2,29";"94,81";"138";"03.09.2004";"Dresden";"92,77";"FP-2015_0-502";""
+"87,900";"1,88";"2,28";"94,78";"138";"03.09.2004";"Dresden";"92,75";"FP-2015_0-502";""
+"88,000";"1,85";"2,40";"94,75";"138";"03.09.2004";"Dresden";"92,64";"FP-2015_0-502";""
+"88,100";"1,68";"2,49";"94,72";"138";"03.09.2004";"Dresden";"92,63";"FP-2015_0-502";""
+"88,200";"1,62";"2,23";"94,69";"138";"03.09.2004";"Dresden";"92,63";"FP-2015_0-502";""
+"88,300";"1,54";"2,19";"94,66";"138";"03.09.2004";"Dresden";"92,73";"FP-2015_0-502";""
+"88,400";"1,78";"2,32";"94,63";"138";"03.09.2004";"Dresden";"92,68";"FP-2015_0-502";""
+"88,500";"1,77";"2,57";"94,61";"138";"03.09.2004";"Dresden";"92,58";"FP-2015_0-502";""
+"88,600";"1,78";"2,92";"94,59";"138";"03.09.2004";"Dresden";"92,40";"FP-2015_0-502";""
+"88,700";"1,85";"2,90";"94,57";"138";"03.09.2004";"Dresden";"92,31";"FP-2015_0-502";""
+"88,800";"1,75";"2,45";"94,54";"138";"03.09.2004";"Dresden";"92,47";"FP-2015_0-502";""
+"88,900";"1,77";"2,28";"94,51";"138";"03.09.2004";"Dresden";"92,47";"FP-2015_0-502";""
+"89,000";"1,73";"2,46";"94,48";"138";"03.09.2004";"Dresden";"92,49";"FP-2015_0-502";"Gemeinde: Zehren"
+"89,100";"1,78";"2,68";"94,46";"138";"03.09.2004";"Dresden";"92,38";"FP-2015_0-502";""
+"89,200";"1,86";"2,71";"94,45";"138";"03.09.2004";"Dresden";"92,26";"FP-2015_0-502";""
+"89,300";"1,79";"3,36";"94,44";"138";"03.09.2004";"Dresden";"91,93";"FP-2015_0-502";""
+"89,400";"1,91";"3,85";"94,42";"138";"03.09.2004";"Dresden";"91,53";"FP-2015_0-502";""
+"89,500";"1,97";"3,24";"94,40";"138";"03.09.2004";"Dresden";"91,70";"FP-2015_0-502";""
+"89,600";"1,93";"3,07";"94,38";"138";"03.09.2004";"Dresden";"91,89";"FP-2015_0-502";""
+"89,700";"1,71";"2,65";"94,35";"138";"03.09.2004";"Dresden";"92,02";"FP-2015_0-502";"Gemeinde: Niedermuschütz"
+"89,800";"1,48";"2,64";"94,32";"138";"03.09.2004";"Dresden";"92,32";"FP-2015_0-502";""
+"89,900";"1,61";"2,30";"94,29";"138";"03.09.2004";"Dresden";"92,42";"FP-2015_0-502";""
+"90,000";"1,63";"2,01";"94,26";"138";"03.09.2004";"Dresden";"92,39";"FP-2015_0-502";""
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepthtkh/sinfo_tkh_01.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,69 @@
+"##Ergebnisausgabe - Elbe - Transportkörperhöhen"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: f"
+"# Datum der Erstellung: 14.06.18"
+"# Gewässer: Elbe"
+"# Höhensystem des Flusses: NHN + m "
+"# Bereich (km): 150,000 - 160,000"
+"# Berechnungsgrundlage: Gleichung nach GILL (1971)"
+""
+"Fluss-km";"Transportkörperhöhe [cm]";"Einteilung der Gewässersohle";"Mittlere Sohlhöhe [NHN + m]";"Wasserstand [NHN + m]";"Q [m³/s]";"Bezeichnung";"Bezugspegel";"Lage"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: Q=1520.0 "
+"# Bezugspegel: Torgau"
+""
+"150,000";"51,1";"Starr";"74,24";"82,14";"1.520";"MHQ";"Torgau";""
+"150,100";"51,4";"Starr";"74,20";"82,12";"1.520";"MHQ";"Torgau";""
+"150,200";"49,8";"Starr";"74,40";"82,10";"1.520";"MHQ";"Torgau";""
+"150,300";"48,7";"Starr";"74,54";"82,07";"1.520";"MHQ";"Torgau";""
+"150,400";"51,4";"Starr";"74,56";"82,05";"1.520";"MHQ";"Torgau";""
+"150,500";"54,0";"Starr";"74,54";"82,02";"1.520";"MHQ";"Torgau";""
+"150,600";"53,1";"Starr";"74,45";"81,99";"1.520";"MHQ";"Torgau";""
+"150,700";"53,1";"Starr";"74,23";"81,98";"1.520";"MHQ";"Torgau";""
+"150,800";"54,6";"Starr";"74,16";"81,97";"1.520";"MHQ";"Torgau";""
+"150,900";"56,7";"Starr";"74,01";"81,94";"1.520";"MHQ";"Torgau";""
+"151,000";"56,7";"Starr";"73,98";"81,92";"1.520";"MHQ";"Torgau";""
+"151,100";"57,2";"Starr";"73,87";"81,90";"1.520";"MHQ";"Torgau";""
+"151,200";"58,8";"Starr";"73,83";"81,89";"1.520";"MHQ";"Torgau";""
+"151,300";"61,5";"Starr";"73,62";"81,87";"1.520";"MHQ";"Torgau";""
+"151,400";"62,4";"Starr";"73,59";"81,85";"1.520";"MHQ";"Torgau";""
+"151,500";"60,1";"Starr";"73,96";"81,83";"1.520";"MHQ";"Torgau";""
+"151,600";"62,0";"Starr";"73,83";"81,81";"1.520";"MHQ";"Torgau";""
+"151,700";"61,8";"Starr";"73,97";"81,79";"1.520";"MHQ";"Torgau";""
+"151,800";"62,4";"Starr";"74,06";"81,77";"1.520";"MHQ";"Torgau";""
+"151,900";"65,2";"Starr";"73,89";"81,75";"1.520";"MHQ";"Torgau";""
+"152,000";"64,8";"Starr";"73,92";"81,73";"1.520";"MHQ";"Torgau";""
+"152,100";"63,4";"Starr";"74,06";"81,72";"1.520";"MHQ";"Torgau";""
+"152,200";"63,7";"Starr";"73,84";"81,71";"1.520";"MHQ";"Torgau";""
+"152,300";"63,0";"Starr";"73,67";"81,70";"1.520";"MHQ";"Torgau";""
+"152,400";"65,0";"Starr";"73,90";"81,70";"1.520";"MHQ";"Torgau";""
+"152,500";"67,1";"Starr";"73,96";"81,66";"1.520";"MHQ";"Torgau";""
+"152,600";"68,3";"Starr";"73,79";"81,62";"1.520";"MHQ";"Torgau";""
+"152,700";"69,3";"Starr";"73,66";"81,62";"1.520";"MHQ";"Torgau";""
+"152,800";"72,0";"Starr";"73,56";"81,62";"1.520";"MHQ";"Torgau";""
+"152,900";"76,4";"Starr";"73,24";"81,60";"1.520";"MHQ";"Torgau";""
+"153,000";"78,9";"Starr";"73,14";"81,57";"1.520";"MHQ";"Torgau";""
+"153,100";"80,2";"Starr";"73,13";"81,54";"1.520";"MHQ";"Torgau";""
+"153,200";"81,1";"Starr";"73,11";"81,51";"1.520";"MHQ";"Torgau";""
+"153,300";"82,8";"Starr";"73,01";"81,49";"1.520";"MHQ";"Torgau";""
+"153,400";"84,6";"Starr";"72,83";"81,47";"1.520";"MHQ";"Torgau";""
+"153,500";"84,7";"Starr";"72,84";"81,46";"1.520";"MHQ";"Torgau";""
+"153,600";"85,4";"Starr";"72,95";"81,45";"1.520";"MHQ";"Torgau";""
+"153,700";"86,4";"Starr";"72,96";"81,42";"1.520";"MHQ";"Torgau";""
+"153,800";"87,3";"Starr";"72,87";"81,38";"1.520";"MHQ";"Torgau";""
+"153,900";"87,5";"Mobil";"72,88";"81,38";"1.520";"MHQ";"Torgau";""
+"154,000";"88,3";"Mobil";"72,94";"81,37";"1.520";"MHQ";"Torgau";""
+"154,100";"85,5";"Mobil";"73,06";"81,33";"1.520";"MHQ";"Torgau";""
+"154,200";"81,9";"Mobil";"73,22";"81,29";"1.520";"MHQ";"Torgau";"Hafen: Torgau"
+"154,300";"82,8";"Starr";"72,96";"81,28";"1.520";"MHQ";"Torgau";""
+"154,400";"80,3";"Starr";"73,05";"81,28";"1.520";"MHQ";"Torgau";""
+"154,500";"76,7";"Starr";"73,24";"81,26";"1.520";"MHQ";"Torgau";"Brücke: Torgau -Straße B87"
+"154,600";"69,5";"Starr";"73,92";"81,24";"1.520";"MHQ";"Torgau";""
+"154,700";"71,6";"Starr";"73,66";"81,21";"1.520";"MHQ";"Torgau";""
+"154,800";"71,0";"Starr";"73,56";"81,18";"1.520";"MHQ";"Torgau";""
+"154,900";"68,2";"Starr";"73,69";"81,15";"1.520";"MHQ";"Torgau";""
+"155,000";"66,6";"Starr";"73,66";"81,12";"1.520";"MHQ";"Torgau";""
+"155,100";"65,7";"Starr";"73,57";"81,10";"1.520";"MHQ";"Torgau";""
+"155,200";"67,4";"Starr";"73,07";"81,08";"1.520";"MHQ";"Torgau";"Geschiebemessstelle: Torgau"
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/flowdepthtkh/sinfo_tkh_02.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,183 @@
+"##Ergebnisausgabe - Rhein - Transportkörperhöhen"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: f"
+"# Datum der Erstellung: 14.06.18"
+"# Gewässer: Rhein"
+"# Höhensystem des Flusses: Wasssers[NN "
+"# Bereich (km): 600,000 - 610,000"
+"# Berechnungsgrundlage: Gleichung nach GILL (1971)"
+""
+"Fluss-km";"Transportkörperhöhe [cm]";"Einteilung der Gewässersohle";"Mittlere Sohlhöhe [Wasssers[NN]";"Wasserstand [Wasssers[NN]";"Q [m³/s]";"Bezeichnung";"Bezugspegel";"Lage"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: Q=6125.0 "
+"# Bezugspegel: Andernach"
+""
+"600,100";"0,0";"Starr";"52,82";"61,51";"6.095";"MHQ";"Andernach";""
+"600,200";"0,0";"Starr";"52,87";"61,49";"6.095";"MHQ";"Andernach";""
+"600,300";"0,0";"Starr";"52,85";"61,48";"6.095";"MHQ";"Andernach";""
+"600,400";"0,0";"Starr";"52,81";"61,44";"6.095";"MHQ";"Andernach";""
+"600,500";"0,0";"Starr";"52,75";"61,41";"6.095";"MHQ";"Andernach";""
+"600,600";"2,5";"Starr";"52,72";"61,38";"6.095";"MHQ";"Andernach";""
+"600,700";"10,0";"Starr";"52,65";"61,34";"6.095";"MHQ";"Andernach";""
+"600,800";"17,3";"Starr";"52,54";"61,32";"6.095";"MHQ";"Andernach";""
+"600,900";"24,2";"Starr";"52,51";"61,29";"6.095";"MHQ";"Andernach";""
+"601,000";"30,7";"Mobil";"52,49";"61,25";"6.095";"MHQ";"Andernach";""
+"601,100";"34,5";"Mobil";"52,47";"61,21";"6.095";"MHQ";"Andernach";""
+"601,200";"35,8";"Mobil";"52,47";"61,20";"6.095";"MHQ";"Andernach";""
+"601,300";"37,0";"Mobil";"52,51";"61,19";"6.095";"MHQ";"Andernach";""
+"601,400";"38,3";"Mobil";"52,51";"61,18";"6.095";"MHQ";"Andernach";""
+"601,500";"39,8";"Mobil";"52,50";"61,16";"6.095";"MHQ";"Andernach";""
+"601,600";"38,3";"Starr";"52,48";"61,12";"6.095";"MHQ";"Andernach";""
+"601,700";"37,8";"Starr";"52,38";"61,08";"6.095";"MHQ";"Andernach";""
+"601,800";"37,4";"Starr";"52,26";"61,05";"6.095";"MHQ";"Andernach";""
+"601,900";"36,6";"Starr";"52,20";"61,02";"6.095";"MHQ";"Andernach";""
+"602,000";"36,1";"Starr";"52,11";"61,02";"6.095";"MHQ";"Andernach";""
+"602,200";"35,2";"Starr";"51,83";"60,98";"6.095";"MHQ";"Andernach";""
+"602,300";"32,4";"Starr";"51,84";"60,95";"6.095";"MHQ";"Andernach";""
+"602,400";"29,1";"Starr";"51,92";"60,94";"6.095";"MHQ";"Andernach";""
+"602,500";"25,8";"Starr";"51,96";"60,93";"6.095";"MHQ";"Andernach";""
+"602,600";"22,6";"Starr";"51,81";"60,92";"6.095";"MHQ";"Andernach";""
+"602,700";"18,8";"Starr";"51,71";"60,90";"6.095";"MHQ";"Andernach";""
+"602,800";"23,1";"Starr";"51,54";"60,88";"6.095";"MHQ";"Andernach";""
+"602,900";"27,0";"Starr";"51,42";"60,85";"6.095";"MHQ";"Andernach";""
+"603,000";"30,3";"Starr";"51,39";"60,82";"6.095";"MHQ";"Andernach";""
+"603,100";"33,3";"Starr";"51,37";"60,78";"6.095";"MHQ";"Andernach";""
+"603,200";"35,9";"Starr";"51,37";"60,73";"6.095";"MHQ";"Andernach";""
+"603,300";"38,3";"Starr";"51,36";"60,69";"6.095";"MHQ";"Andernach";""
+"603,400";"38,1";"Starr";"51,32";"60,66";"6.095";"MHQ";"Andernach";""
+"603,500";"37,8";"Starr";"51,32";"60,62";"6.095";"MHQ";"Andernach";""
+"603,600";"37,7";"Starr";"51,28";"60,61";"6.095";"MHQ";"Andernach";""
+"603,700";"37,7";"Starr";"51,24";"60,61";"6.095";"MHQ";"Andernach";""
+"603,800";"37,5";"Starr";"51,23";"60,59";"6.095";"MHQ";"Andernach";""
+"603,900";"39,1";"Starr";"51,15";"60,56";"6.095";"MHQ";"Andernach";""
+"604,000";"40,8";"Starr";"51,03";"60,53";"6.095";"MHQ";"Andernach";""
+"604,100";"42,1";"Starr";"50,99";"60,50";"6.095";"MHQ";"Andernach";""
+"604,200";"43,2";"Starr";"50,96";"60,46";"6.095";"MHQ";"Andernach";""
+"604,300";"44,6";"Starr";"50,89";"60,43";"6.095";"MHQ";"Andernach";""
+"604,400";"45,8";"Starr";"50,82";"60,40";"6.095";"MHQ";"Andernach";""
+"604,500";"45,2";"Starr";"50,80";"60,37";"6.095";"MHQ";"Andernach";""
+"604,600";"44,5";"Starr";"50,80";"60,36";"6.095";"MHQ";"Andernach";""
+"604,700";"43,9";"Starr";"50,79";"60,34";"6.095";"MHQ";"Andernach";""
+"604,800";"43,0";"Starr";"50,80";"60,32";"6.095";"MHQ";"Andernach";""
+"604,900";"42,2";"Starr";"50,82";"60,29";"6.095";"MHQ";"Andernach";""
+"605,000";"41,2";"Starr";"50,87";"60,26";"6.095";"MHQ";"Andernach";""
+"605,100";"40,7";"Starr";"50,90";"60,24";"6.095";"MHQ";"Andernach";""
+"605,200";"40,4";"Starr";"50,91";"60,22";"6.095";"MHQ";"Andernach";""
+"605,300";"40,3";"Starr";"50,89";"60,20";"6.095";"MHQ";"Andernach";""
+"605,400";"40,1";"Starr";"50,88";"60,18";"6.095";"MHQ";"Andernach";""
+"605,500";"39,5";"Starr";"50,94";"60,16";"6.095";"MHQ";"Andernach";"Hafen: Neuwied MYC -Sportboot"
+"605,600";"37,9";"Starr";"51,00";"60,15";"6.095";"MHQ";"Andernach";""
+"605,700";"36,1";"Starr";"51,09";"60,14";"6.095";"MHQ";"Andernach";""
+"605,800";"45,1";"Mobil";"51,16";"60,12";"6.095";"MHQ";"Andernach";""
+"605,900";"18,6";"Mobil";"51,07";"60,09";"6.095";"MHQ";"Andernach";""
+"606,000";"49,2";"Starr";"50,96";"60,08";"6.095";"MHQ";"Andernach";"Insel: Weißenthurmer Werth"
+"606,100";"64,1";"Starr";"50,84";"60,06";"6.095";"MHQ";"Andernach";""
+"606,200";"54,1";"Starr";"50,84";"60,06";"6.095";"MHQ";"Andernach";""
+"606,300";"56,0";"Starr";"50,91";"60,05";"6.095";"MHQ";"Andernach";""
+"606,400";"45,3";"Mobil";"50,86";"60,03";"6.095";"MHQ";"Andernach";""
+"606,500";"46,9";"Mobil";"50,79";"60,01";"6.095";"MHQ";"Andernach";""
+"606,600";"61,9";"Mobil";"50,70";"59,97";"6.095";"MHQ";"Andernach";""
+"606,700";"46,4";"Starr";"50,59";"59,94";"6.095";"MHQ";"Andernach";"Hafen: Neuwied -Städt. Hafen"
+"606,800";"25,9";"Starr";"50,53";"59,90";"6.095";"MHQ";"Andernach";""
+"606,900";"62,7";"Starr";"50,49";"59,86";"6.095";"MHQ";"Andernach";""
+"607,000";"41,5";"Starr";"50,48";"59,82";"6.095";"MHQ";"Andernach";""
+"607,100";"0,0";"Starr";"50,48";"59,79";"6.095";"MHQ";"Andernach";""
+"607,200";"45,3";"Mobil";"50,45";"59,77";"6.095";"MHQ";"Andernach";""
+"607,300";"0,5";"Mobil";"50,49";"59,75";"6.095";"MHQ";"Andernach";""
+"607,400";"101,2";"Starr";"50,51";"59,75";"6.095";"MHQ";"Andernach";""
+"607,500";"41,4";"Starr";"50,46";"59,74";"6.095";"MHQ";"Andernach";""
+"607,600";"22,8";"Starr";"50,42";"59,72";"6.095";"MHQ";"Andernach";""
+"607,700";"3,0";"Starr";"50,37";"59,70";"6.095";"MHQ";"Andernach";""
+"607,800";"51,3";"Starr";"50,44";"59,69";"6.095";"MHQ";"Andernach";""
+"607,900";"0,0";"Starr";"50,50";"59,68";"6.095";"MHQ";"Andernach";""
+"608,000";"55,8";"Starr";"50,55";"59,68";"6.095";"MHQ";"Andernach";""
+"608,100";"46,6";"Starr";"50,58";"59,65";"6.095";"MHQ";"Andernach";""
+"608,200";"45,2";"Starr";"50,54";"59,62";"6.095";"MHQ";"Andernach";"Schwebstoffmessstelle: Weißenthurm"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: Q=6526.0 "
+"# Bezugspegel: Andernach"
+""
+"600,100";"0,0";"Starr";"52,82";"61,84";"6.496";"HQ2";"Andernach";""
+"600,200";"0,0";"Starr";"52,87";"61,82";"6.496";"HQ2";"Andernach";""
+"600,300";"0,0";"Starr";"52,85";"61,81";"6.496";"HQ2";"Andernach";""
+"600,400";"0,0";"Starr";"52,81";"61,78";"6.496";"HQ2";"Andernach";""
+"600,500";"0,0";"Starr";"52,75";"61,74";"6.496";"HQ2";"Andernach";""
+"600,600";"6,0";"Starr";"52,72";"61,70";"6.496";"HQ2";"Andernach";""
+"600,700";"13,4";"Starr";"52,65";"61,67";"6.496";"HQ2";"Andernach";""
+"600,800";"20,7";"Starr";"52,54";"61,65";"6.496";"HQ2";"Andernach";""
+"600,900";"27,6";"Starr";"52,51";"61,62";"6.496";"HQ2";"Andernach";""
+"601,000";"34,1";"Mobil";"52,49";"61,58";"6.496";"HQ2";"Andernach";""
+"601,100";"37,8";"Mobil";"52,47";"61,54";"6.496";"HQ2";"Andernach";""
+"601,200";"39,3";"Mobil";"52,47";"61,53";"6.496";"HQ2";"Andernach";""
+"601,300";"40,6";"Mobil";"52,51";"61,52";"6.496";"HQ2";"Andernach";""
+"601,400";"42,1";"Mobil";"52,51";"61,50";"6.496";"HQ2";"Andernach";""
+"601,500";"43,7";"Mobil";"52,50";"61,49";"6.496";"HQ2";"Andernach";""
+"601,600";"42,3";"Starr";"52,48";"61,45";"6.496";"HQ2";"Andernach";""
+"601,700";"41,8";"Starr";"52,38";"61,41";"6.496";"HQ2";"Andernach";""
+"601,800";"41,4";"Starr";"52,26";"61,38";"6.496";"HQ2";"Andernach";""
+"601,900";"40,6";"Starr";"52,20";"61,35";"6.496";"HQ2";"Andernach";""
+"602,000";"40,1";"Starr";"52,11";"61,34";"6.496";"HQ2";"Andernach";""
+"602,200";"39,2";"Starr";"51,83";"61,31";"6.496";"HQ2";"Andernach";""
+"602,300";"36,3";"Starr";"51,84";"61,28";"6.496";"HQ2";"Andernach";""
+"602,400";"32,8";"Starr";"51,92";"61,27";"6.496";"HQ2";"Andernach";""
+"602,500";"29,3";"Starr";"51,96";"61,26";"6.496";"HQ2";"Andernach";""
+"602,600";"26,0";"Starr";"51,81";"61,25";"6.496";"HQ2";"Andernach";""
+"602,700";"22,0";"Starr";"51,71";"61,24";"6.496";"HQ2";"Andernach";""
+"602,800";"26,3";"Starr";"51,54";"61,21";"6.496";"HQ2";"Andernach";""
+"602,900";"30,2";"Starr";"51,42";"61,18";"6.496";"HQ2";"Andernach";""
+"603,000";"33,5";"Starr";"51,39";"61,14";"6.496";"HQ2";"Andernach";""
+"603,100";"36,4";"Starr";"51,37";"61,11";"6.496";"HQ2";"Andernach";""
+"603,200";"39,0";"Starr";"51,37";"61,07";"6.496";"HQ2";"Andernach";""
+"603,300";"41,4";"Starr";"51,36";"61,03";"6.496";"HQ2";"Andernach";""
+"603,400";"41,3";"Starr";"51,32";"61,00";"6.496";"HQ2";"Andernach";""
+"603,500";"41,2";"Starr";"51,32";"60,96";"6.496";"HQ2";"Andernach";""
+"603,600";"41,3";"Starr";"51,28";"60,96";"6.496";"HQ2";"Andernach";""
+"603,700";"41,4";"Starr";"51,24";"60,95";"6.496";"HQ2";"Andernach";""
+"603,800";"41,3";"Starr";"51,23";"60,93";"6.496";"HQ2";"Andernach";""
+"603,900";"43,0";"Starr";"51,15";"60,90";"6.496";"HQ2";"Andernach";""
+"604,000";"44,8";"Starr";"51,03";"60,86";"6.496";"HQ2";"Andernach";""
+"604,100";"46,2";"Starr";"50,99";"60,83";"6.496";"HQ2";"Andernach";""
+"604,200";"47,4";"Starr";"50,96";"60,79";"6.496";"HQ2";"Andernach";""
+"604,300";"48,8";"Starr";"50,89";"60,76";"6.496";"HQ2";"Andernach";""
+"604,400";"50,2";"Starr";"50,82";"60,74";"6.496";"HQ2";"Andernach";""
+"604,500";"49,6";"Starr";"50,80";"60,71";"6.496";"HQ2";"Andernach";""
+"604,600";"48,9";"Starr";"50,80";"60,69";"6.496";"HQ2";"Andernach";""
+"604,700";"48,3";"Starr";"50,79";"60,67";"6.496";"HQ2";"Andernach";""
+"604,800";"47,6";"Starr";"50,80";"60,65";"6.496";"HQ2";"Andernach";""
+"604,900";"46,7";"Starr";"50,82";"60,62";"6.496";"HQ2";"Andernach";""
+"605,000";"45,8";"Starr";"50,87";"60,60";"6.496";"HQ2";"Andernach";""
+"605,100";"45,3";"Starr";"50,90";"60,57";"6.496";"HQ2";"Andernach";""
+"605,200";"45,0";"Starr";"50,91";"60,55";"6.496";"HQ2";"Andernach";""
+"605,300";"44,9";"Starr";"50,89";"60,53";"6.496";"HQ2";"Andernach";""
+"605,400";"44,7";"Starr";"50,88";"60,51";"6.496";"HQ2";"Andernach";""
+"605,500";"44,2";"Starr";"50,94";"60,49";"6.496";"HQ2";"Andernach";"Hafen: Neuwied MYC -Sportboot"
+"605,600";"42,5";"Starr";"51,00";"60,48";"6.496";"HQ2";"Andernach";""
+"605,700";"40,7";"Starr";"51,09";"60,47";"6.496";"HQ2";"Andernach";""
+"605,800";"49,5";"Mobil";"51,16";"60,45";"6.496";"HQ2";"Andernach";""
+"605,900";"23,4";"Mobil";"51,07";"60,42";"6.496";"HQ2";"Andernach";""
+"606,000";"53,6";"Starr";"50,96";"60,40";"6.496";"HQ2";"Andernach";"Insel: Weißenthurmer Werth"
+"606,100";"68,3";"Starr";"50,84";"60,39";"6.496";"HQ2";"Andernach";""
+"606,200";"58,3";"Starr";"50,84";"60,38";"6.496";"HQ2";"Andernach";""
+"606,300";"60,2";"Starr";"50,91";"60,38";"6.496";"HQ2";"Andernach";""
+"606,400";"49,4";"Mobil";"50,86";"60,36";"6.496";"HQ2";"Andernach";""
+"606,500";"51,0";"Mobil";"50,79";"60,35";"6.496";"HQ2";"Andernach";""
+"606,600";"65,9";"Mobil";"50,70";"60,32";"6.496";"HQ2";"Andernach";""
+"606,700";"50,4";"Starr";"50,59";"60,28";"6.496";"HQ2";"Andernach";"Hafen: Neuwied -Städt. Hafen"
+"606,800";"30,0";"Starr";"50,53";"60,24";"6.496";"HQ2";"Andernach";""
+"606,900";"66,7";"Starr";"50,49";"60,19";"6.496";"HQ2";"Andernach";""
+"607,000";"45,6";"Starr";"50,48";"60,16";"6.496";"HQ2";"Andernach";""
+"607,100";"0,0";"Starr";"50,48";"60,12";"6.496";"HQ2";"Andernach";""
+"607,200";"49,4";"Mobil";"50,45";"60,10";"6.496";"HQ2";"Andernach";""
+"607,300";"4,9";"Mobil";"50,49";"60,08";"6.496";"HQ2";"Andernach";""
+"607,400";"104,9";"Starr";"50,51";"60,08";"6.496";"HQ2";"Andernach";""
+"607,500";"45,5";"Starr";"50,46";"60,07";"6.496";"HQ2";"Andernach";""
+"607,600";"27,1";"Starr";"50,42";"60,05";"6.496";"HQ2";"Andernach";""
+"607,700";"7,4";"Starr";"50,37";"60,03";"6.496";"HQ2";"Andernach";""
+"607,800";"55,5";"Starr";"50,44";"60,02";"6.496";"HQ2";"Andernach";""
+"607,900";"0,0";"Starr";"50,50";"60,01";"6.496";"HQ2";"Andernach";""
+"608,000";"60,1";"Starr";"50,55";"60,01";"6.496";"HQ2";"Andernach";""
+"608,100";"51,0";"Starr";"50,58";"59,98";"6.496";"HQ2";"Andernach";""
+"608,200";"49,7";"Starr";"50,54";"59,95";"6.496";"HQ2";"Andernach";"Schwebstoffmessstelle: Weißenthurm"
+""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/test/resources/sinfo/tkh/sinfo_tkh_export.csv	Fri Jul 13 11:56:22 2018 +0200
@@ -0,0 +1,1797 @@
+"##Ergebnisausgabe - Beispielfluss - Transportkörperhöhen"
+"# FLYS-Version: 3.3.0"
+"# Bearbeiter: belger"
+"# Datum der Erstellung: 12.06.18"
+"# Gewässer: Beispielfluss"
+"# Höhensystem des Flusses: NHN + m "
+"# Bereich (km): 0,000 - 182,400"
+"# Berechnungsgrundlage: Gleichung nach GILL (1971)"
+""
+"Fluss-km";"Transportkörperhöhe [cm]";"Einteilung der Gewässersohle";"Mittlere Sohlhöhe [NHN + m]";"Wasserstand [NHN + m]";"Q [m³/s]";"Bezeichnung";"Bezugspegel";"Lage"
+""
+"##METADATEN WASSERSPIEGELLAGE"
+"# Bezeichnung der Wasserspiegellage: Q=1059.446 "
+"# Bezugspegel: Torgau"
+""
+"1,600";"0,0";"Starr";"87,83";"94,28";"1.075";"1.059,45";"Torgau";""
+"1,700";"0,0";"Starr";"87,76";"94,26";"1.075";"1.059,45";"Torgau";""
+"1,800";"0,0";"Starr";"87,78";"94,24";"1.075";"1.059,45";"Torgau";""
+"1,900";"0,0";"Starr";"87,78";"94,22";"1.075";"1.059,45";"Torgau";""
+"2,000";"0,0";"Starr";"87,75";"94,19";"1.075";"1.059,45";"Torgau";""
+"2,100";"0,0";"Starr";"87,72";"94,17";"1.075";"1.059,45";"Torgau";""
+"2,200";"0,6";"Starr";"87,67";"94,14";"1.075";"1.059,45";"Torgau";""
+"2,300";"1,7";"Starr";"87,62";"94,11";"1.075";"1.059,45";"Torgau";""
+"2,400";"0,9";"Starr";"87,25";"94,08";"1.075";"1.059,45";"Torgau";""
+"2,500";"0,0";"Starr";"87,02";"94,06";"1.075";"1.059,45";"Torgau";""
+"2,600";"0,0";"Starr";"86,94";"94,03";"1.075";"1.059,45";"Torgau";"Gemeinde: Forberge"
+"2,700";"0,0";"Starr";"86,83";"94,01";"1.075";"1.059,45";"Torgau";""
+"2,800";"0,0";"Starr";"86,68";"93,98";"1.075";"1.059,45";"Torgau";""
+"2,900";"0,0";"Starr";"86,85";"93,97";"1.075";"1.059,45";"Torgau";""
+"3,000";"0,0";"Starr";"87,00";"93,96";"1.075";"1.059,45";"Torgau";""
+"3,100";"0,0";"Starr";"86,89";"93,93";"1.075";"1.059,45";"Torgau";""
+"3,200";"0,0";"Starr";"87,09";"93,90";"1.075";"1.059,45";"Torgau";""
+"3,300";"0,0";"Starr";"87,12";"93,88";"1.075";"1.059,45";"Torgau";""
+"3,400";"0,0";"Starr";"87,12";"93,85";"1.075";"1.059,45";"Torgau";""
+"3,500";"3,0";"Starr";"87,18";"93,83";"1.075";"1.059,45";"Torgau";""
+"3,600";"2,2";"Starr";"87,23";"93,80";"1.075";"1.059,45";"Torgau";""
+"3,700";"1,4";"Starr";"87,22";"93,78";"1.075";"1.059,45";"Torgau";""
+"3,800";"2,7";"Starr";"87,22";"93,75";"1.075";"1.059,45";"Torgau";""
+"3,900";"4,0";"Starr";"87,29";"93,73";"1.075";"1.059,45";"Torgau";""
+"4,000";"0,0";"Starr";"87,33";"93,70";"1.075";"1.059,45";"Torgau";""
+"4,100";"0,0";"Starr";"87,32";"93,68";"1.075";"1.059,45";"Torgau";""
+"4,200";"0,0";"Starr";"87,29";"93,66";"1.075";"1.059,45";"Torgau";""
+"4,300";"0,0";"Starr";"87,28";"93,64";"1.075";"1.059,45";"Torgau";""
+"4,400";"0,0";"Starr";"87,32";"93,61";"1.075";"1.059,45";"Torgau";""
+"4,500";"1,3";"Starr";"87,28";"93,58";"1.075";"1.059,45";"Torgau";""
+"4,600";"3,0";"Starr";"87,19";"93,55";"1.075";"1.059,45";"Torgau";"Gemeinde: Klein-Zschepa"
+"4,700";"4,8";"Starr";"87,07";"93,52";"1.075";"1.059,45";"Torgau";""
+"4,800";"6,8";"Starr";"86,96";"93,49";"1.075";"1.059,45";"Torgau";""
+"4,900";"8,9";"Starr";"86,78";"93,46";"1.075";"1.059,45";"Torgau";""
+"5,000";"14,3";"Starr";"86,45";"93,43";"1.075";"1.059,45";"Torgau";""
+"5,100";"18,4";"Starr";"86,46";"93,40";"1.075";"1.059,45";"Torgau";""
+"5,200";"17,6";"Starr";"86,55";"93,36";"1.075";"1.059,45";"Torgau";""
+"5,300";"17,1";"Starr";"86,50";"93,34";"1.075";"1.059,45";"Torgau";""
+"5,400";"17,2";"Starr";"86,58";"93,31";"1.075";"1.059,45";"Torgau";""
+"5,500";"17,3";"Starr";"86,63";"93,29";"1.075";"1.059,45";"Torgau";""
+"5,600";"16,3";"Starr";"86,65";"93,27";"1.075";"1.059,45";"Torgau";"Gemeinde: Groß-Zschepa"
+"5,700";"14,4";"Starr";"86,71";"93,25";"1.075";"1.059,45";"Torgau";""
+"5,800";"12,8";"Starr";"86,74";"93,23";"1.075";"1.059,45";"Torgau";""
+"5,900";"11,2";"Starr";"86,72";"93,22";"1.075";"1.059,45";"Torgau";""
+"6,000";"13,0";"Starr";"86,64";"93,20";"1.075";"1.059,45";"Torgau";""
+"6,100";"14,7";"Starr";"86,56";"93,18";"1.075";"1.059,45";"Torgau";""
+"6,200";"15,5";"Starr";"86,55";"93,15";"1.075";"1.059,45";"Torgau";""
+"6,300";"16,2";"Starr";"86,52";"93,12";"1.075";"1.059,45";"Torgau";""
+"6,400";"15,3";"Starr";"86,53";"93,09";"1.075";"1.059,45";"Torgau";""
+"6,500";"14,4";"Starr";"86,47";"93,06";"1.075";"1.059,45";"Torgau";""
+"6,600";"16,3";"Starr";"86,10";"93,03";"1.075";"1.059,45";"Torgau";"Gemeinde: Strehla"
+"6,700";"18,1";"Starr";"85,78";"93,01";"1.075";"1.059,45";"Torgau";""
+"6,800";"10,9";"Starr";"86,24";"92,98";"1.075";"1.059,45";"Torgau";""
+"6,900";"3,3";"Starr";"86,19";"92,98";"1.075";"1.059,45";"Torgau";""
+"7,000";"0,3";"Starr";"86,21";"92,97";"1.075";"1.059,45";"Torgau";""
+"7,100";"0,0";"Starr";"86,10";"92,96";"1.075";"1.059,45";"Torgau";""
+"7,200";"5,1";"Starr";"86,06";"92,94";"1.075";"1.059,45";"Torgau";""
+"7,300";"11,3";"Starr";"86,20";"92,91";"1.075";"1.059,45";"Torgau";""
+"7,400";"11,5";"Starr";"86,27";"92,88";"1.075";"1.059,45";"Torgau";""
+"7,500";"11,9";"Starr";"86,25";"92,86";"1.075";"1.059,45";"Torgau";""
+"7,600";"10,6";"Starr";"86,21";"92,83";"1.075";"1.059,45";"Torgau";""
+"7,700";"9,3";"Starr";"86,15";"92,81";"1.075";"1.059,45";"Torgau";""
+"7,800";"19,8";"Starr";"86,16";"92,79";"1.075";"1.059,45";"Torgau";""
+"7,900";"26,2";"Starr";"86,18";"92,73";"1.075";"1.059,45";"Torgau";""
+"8,000";"28,0";"Starr";"86,14";"92,67";"1.075";"1.059,45";"Torgau";""
+"8,100";"29,6";"Starr";"86,09";"92,62";"1.075";"1.059,45";"Torgau";""
+"8,200";"32,2";"Starr";"86,07";"92,57";"1.075";"1.059,45";"Torgau";""
+"8,300";"34,5";"Starr";"85,94";"92,50";"1.075";"1.059,45";"Torgau";""
+"8,400";"30,5";"Starr";"85,54";"92,43";"1.075";"1.059,45";"Torgau";""
+"8,500";"15,7";"Starr";"85,56";"92,47";"1.075";"1.059,45";"Torgau";""
+"8,600";"21,5";"Starr";"85,65";"92,50";"1.075";"1.059,45";"Torgau";"Gemeinde: Nixstein"
+"8,700";"25,8";"Starr";"85,65";"92,45";"1.075";"1.059,45";"Torgau";""
+"8,800";"25,9";"Starr";"85,61";"92,39";"1.075";"1.059,45";"Torgau";""
+"8,900";"25,3";"Starr";"85,72";"92,36";"1.075";"1.059,45";"Torgau";""
+"9,000";"25,9";"Starr";"85,69";"92,33";"1.075";"1.059,45";"Torgau";""
+"9,100";"26,3";"Starr";"85,69";"92,31";"1.075";"1.059,45";"Torgau";""
+"9,200";"29,2";"Starr";"85,68";"92,29";"1.075";"1.059,45";"Torgau";""
+"9,300";"31,1";"Starr";"85,73";"92,25";"1.075";"1.059,45";"Torgau";""
+"9,400";"31,5";"Starr";"85,55";"92,21";"1.075";"1.059,45";"Torgau";""
+"9,500";"34,0";"Starr";"85,00";"92,18";"1.075";"1.059,45";"Torgau";""
+"9,600";"33,8";"Starr";"85,04";"92,14";"1.075";"1.059,45";"Torgau";"Gemeinde: Görzig,Trebnitz"
+"9,700";"32,0";"Starr";"85,35";"92,11";"1.075";"1.059,45";"Torgau";""
+"9,800";"25,9";"Starr";"85,76";"92,08";"1.075";"1.059,45";"Torgau";""
+"9,900";"20,0";"Starr";"85,88";"92,07";"1.075";"1.059,45";"Torgau";""
+"10,000";"20,9";"Starr";"85,50";"92,05";"1.075";"1.059,45";"Torgau";""
+"10,100";"20,5";"Starr";"85,41";"92,03";"1.075";"1.059,45";"Torgau";""
+"10,200";"22,1";"Starr";"85,29";"92,00";"1.075";"1.059,45";"Torgau";""
+"10,300";"23,6";"Starr";"85,20";"91,98";"1.075";"1.059,45";"Torgau";""
+"10,400";"27,9";"Starr";"85,20";"91,95";"1.075";"1.059,45";"Torgau";""
+"10,500";"30,9";"Starr";"85,21";"91,92";"1.075";"1.059,45";"Torgau";""
+"10,600";"27,8";"Starr";"85,25";"91,89";"1.075";"1.059,45";"Torgau";""
+"10,700";"23,9";"Starr";"85,32";"91,88";"1.075";"1.059,45";"Torgau";""
+"10,800";"22,9";"Starr";"85,38";"91,86";"1.075";"1.059,45";"Torgau";"Gemeinde: Kreinitz"
+"10,900";"22,1";"Starr";"85,39";"91,83";"1.075";"1.059,45";"Torgau";""
+"11,000";"19,9";"Starr";"85,39";"91,80";"1.075";"1.059,45";"Torgau";""
+"11,100";"18,0";"Starr";"85,23";"91,77";"1.075";"1.059,45";"Torgau";""
+"11,200";"20,3";"Starr";"85,17";"91,74";"1.075";"1.059,45";"Torgau";""
+"11,300";"21,7";"Starr";"85,27";"91,71";"1.075";"1.059,45";"Torgau";""
+"11,400";"22,8";"Starr";"85,28";"91,68";"1.075";"1.059,45";"Torgau";""
+"11,500";"23,9";"Starr";"85,28";"91,66";"1.075";"1.059,45";"Torgau";""
+"11,600";"23,5";"Starr";"85,27";"91,63";"1.075";"1.059,45";"Torgau";""
+"11,700";"23,2";"Starr";"85,24";"91,60";"1.075";"1.059,45";"Torgau";""
+"11,800";"23,4";"Starr";"85,22";"91,57";"1.075";"1.059,45";"Torgau";""
+"11,900";"23,9";"Starr";"85,12";"91,54";"1.075";"1.059,45";"Torgau";""
+"12,000";"23,6";"Starr";"85,02";"91,51";"1.075";"1.059,45";"Torgau";""
+"12,100";"23,0";"Starr";"84,98";"91,49";"1.075";"1.059,45";"Torgau";""
+"12,200";"21,8";"Starr";"85,05";"91,46";"1.075";"1.059,45";"Torgau";""
+"12,300";"21,0";"Starr";"85,04";"91,44";"1.075";"1.059,45";"Torgau";""
+"12,400";"24,7";"Starr";"84,88";"91,42";"1.075";"1.059,45";"Torgau";""
+"12,500";"27,1";"Starr";"84,89";"91,38";"1.075";"1.059,45";"Torgau";""
+"12,600";"27,7";"Starr";"84,93";"91,34";"1.075";"1.059,45";"Torgau";""
+"12,700";"32,3";"Starr";"84,20";"91,32";"1.075";"1.059,45";"Torgau";""
+"12,800";"32,4";"Starr";"84,32";"91,30";"1.075";"1.059,45";"Torgau";""
+"12,900";"33,7";"Starr";"84,22";"91,27";"1.075";"1.059,45";"Torgau";""
+"13,000";"27,3";"Starr";"84,18";"91,24";"1.075";"1.059,45";"Torgau";""
+"13,100";"31,1";"Starr";"83,97";"91,19";"1.075";"1.059,45";"Torgau";""
+"13,200";"33,1";"Starr";"83,94";"91,14";"1.075";"1.059,45";"Torgau";""
+"13,300";"35,0";"Starr";"83,88";"91,10";"1.075";"1.059,45";"Torgau";""
+"13,400";"33,1";"Starr";"83,81";"91,06";"1.075";"1.059,45";"Torgau";""
+"13,500";"30,1";"Starr";"83,80";"90,95";"1.075";"1.059,45";"Torgau";""
+"13,600";"30,7";"Starr";"83,86";"90,84";"1.075";"1.059,45";"Torgau";""
+"13,700";"31,9";"Starr";"83,82";"90,73";"1.075";"1.059,45";"Torgau";""
+"13,800";"29,2";"Starr";"83,90";"90,62";"1.075";"1.059,45";"Torgau";""
+"13,900";"27,0";"Starr";"83,89";"90,59";"1.075";"1.059,45";"Torgau";""
+"14,000";"26,4";"Starr";"83,84";"90,56";"1.075";"1.059,45";"Torgau";""
+"14,100";"26,0";"Starr";"83,74";"90,55";"1.075";"1.059,45";"Torgau";""
+"14,200";"29,0";"Starr";"83,67";"90,53";"1.075";"1.059,45";"Torgau";""
+"14,300";"31,1";"Starr";"83,68";"90,49";"1.075";"1.059,45";"Torgau";""
+"14,400";"29,4";"Starr";"83,74";"90,44";"1.075";"1.059,45";"Torgau";""
+"14,500";"27,4";"Starr";"83,83";"90,42";"1.075";"1.059,45";"Torgau";""
+"14,600";"30,3";"Starr";"83,72";"90,39";"1.075";"1.059,45";"Torgau";""
+"14,700";"34,5";"Starr";"83,31";"90,35";"1.075";"1.059,45";"Torgau";""
+"14,800";"40,7";"Starr";"82,68";"90,31";"1.075";"1.059,45";"Torgau";""
+"14,900";"43,4";"Starr";"82,55";"90,26";"1.075";"1.059,45";"Torgau";""
+"15,000";"40,1";"Starr";"82,88";"90,21";"1.075";"1.059,45";"Torgau";""
+"15,100";"36,8";"Starr";"83,23";"90,19";"1.075";"1.059,45";"Torgau";""
+"15,200";"33,5";"Starr";"83,48";"90,17";"1.075";"1.059,45";"Torgau";""
+"15,300";"31,5";"Starr";"83,44";"90,16";"1.075";"1.059,45";"Torgau";""
+"15,400";"34,6";"Starr";"83,29";"90,15";"1.075";"1.059,45";"Torgau";""
+"15,500";"36,6";"Starr";"83,24";"90,11";"1.075";"1.059,45";"Torgau";""
+"15,600";"36,7";"Starr";"83,11";"90,07";"1.075";"1.059,45";"Torgau";""
+"15,700";"36,3";"Starr";"83,09";"90,05";"1.075";"1.059,45";"Torgau";""
+"15,800";"37,1";"Starr";"83,12";"90,02";"1.075";"1.059,45";"Torgau";""
+"15,900";"37,9";"Starr";"83,13";"89,99";"1.075";"1.059,45";"Torgau";""
+"16,000";"36,1";"Starr";"83,24";"89,95";"1.075";"1.059,45";"Torgau";""
+"16,100";"35,7";"Starr";"83,12";"89,93";"1.075";"1.059,45";"Torgau";""
+"16,200";"37,8";"Starr";"82,84";"89,90";"1.075";"1.059,45";"Torgau";""
+"16,300";"37,9";"Starr";"82,86";"89,87";"1.075";"1.059,45";"Torgau";""
+"16,400";"39,4";"Starr";"82,92";"89,84";"1.075";"1.059,45";"Torgau";""
+"16,500";"41,9";"Starr";"82,78";"89,81";"1.075";"1.059,45";"Torgau";""
+"16,600";"43,7";"Starr";"82,72";"89,78";"1.075";"1.059,45";"Torgau";""
+"16,700";"44,2";"Starr";"82,78";"89,75";"1.075";"1.059,45";"Torgau";""
+"16,800";"43,3";"Starr";"82,89";"89,71";"1.075";"1.059,45";"Torgau";""
+"16,900";"43,0";"Starr";"82,93";"89,68";"1.075";"1.059,45";"Torgau";""
+"17,000";"42,6";"Starr";"82,92";"89,64";"1.075";"1.059,45";"Torgau";""
+"17,100";"42,9";"Starr";"82,83";"89,61";"1.075";"1.059,45";"Torgau";""
+"17,200";"43,8";"Starr";"82,74";"89,57";"1.075";"1.059,45";"Torgau";""
+"17,300";"44,2";"Starr";"82,72";"89,54";"1.075";"1.059,45";"Torgau";""
+"17,400";"45,9";"Starr";"82,56";"89,51";"1.075";"1.059,45";"Torgau";""
+"17,500";"48,8";"Starr";"82,24";"89,47";"1.075";"1.059,45";"Torgau";""
+"17,600";"45,5";"Starr";"82,56";"89,43";"1.075";"1.059,45";"Torgau";""
+"17,700";"44,1";"Starr";"82,66";"89,40";"1.075";"1.059,45";"Torgau";""
+"17,800";"42,1";"Starr";"82,89";"89,37";"1.075";"1.059,45";"Torgau";""
+"17,900";"46,5";"Starr";"82,33";"89,34";"1.075";"1.059,45";"Torgau";""
+"18,000";"49,3";"Starr";"81,93";"89,31";"1.075";"1.059,45";"Torgau";""
+"18,100";"48,9";"Starr";"81,92";"89,28";"1.075";"1.059,45";"Torgau";""
+"18,200";"48,1";"Starr";"82,15";"89,25";"1.075";"1.059,45";"Torgau";"Geschiebemessstelle: Mühlberg"
+"18,300";"47,2";"Starr";"82,27";"89,21";"1.075";"1.059,45";"Torgau";""
+"18,400";"46,8";"Starr";"82,19";"89,17";"1.075";"1.059,45";"Torgau";""
+"18,500";"47,7";"Starr";"81,95";"89,15";"1.075";"1.059,45";"Torgau";""
+"18,600";"48,8";"Starr";"81,69";"89,12";"1.075";"1.059,45";"Torgau";""
+"18,700";"49,7";"Starr";"81,44";"89,11";"1.075";"1.059,45";"Torgau";"Hafen: Mühlberg -Schutz- und Sicherheitshafen"
+"18,800";"45,9";"Starr";"81,27";"89,10";"1.075";"1.059,45";"Torgau";""
+"18,900";"36,8";"Starr";"81,44";"89,10";"1.075";"1.059,45";"Torgau";""
+"19,000";"43,3";"Starr";"81,47";"89,09";"1.075";"1.059,45";"Torgau";""
+"19,100";"44,2";"Starr";"81,88";"89,06";"1.075";"1.059,45";"Torgau";""
+"19,200";"42,1";"Starr";"82,06";"89,03";"1.075";"1.059,45";"Torgau";""
+"19,300";"42,6";"Starr";"81,87";"89,01";"1.075";"1.059,45";"Torgau";""
+"19,400";"41,1";"Starr";"81,76";"88,98";"1.075";"1.059,45";"Torgau";""
+"19,500";"39,6";"Starr";"81,58";"88,96";"1.075";"1.059,45";"Torgau";"Fähre: Köttlitz -Gierseilfähre"
+"19,600";"42,8";"Starr";"81,18";"88,94";"1.075";"1.059,45";"Torgau";"Zufluss: Lukke"
+"19,700";"43,5";"Starr";"81,14";"88,89";"1.075";"1.059,45";"Torgau";""
+"19,800";"42,8";"Starr";"81,50";"88,84";"1.068";"1.059,45";"Torgau";""
+"19,900";"42,4";"Starr";"81,73";"88,81";"1.068";"1.059,45";"Torgau";""
+"20,000";"41,1";"Starr";"81,91";"88,77";"1.068";"1.059,45";"Torgau";""
+"20,100";"40,5";"Starr";"81,98";"88,74";"1.068";"1.059,45";"Torgau";""
+"20,200";"40,3";"Starr";"81,94";"88,70";"1.068";"1.059,45";"Torgau";""
+"20,300";"40,1";"Starr";"81,90";"88,67";"1.068";"1.059,45";"Torgau";""
+"20,400";"39,1";"Starr";"81,96";"88,64";"1.068";"1.059,45";"Torgau";""
+"20,500";"39,5";"Starr";"81,82";"88,61";"1.068";"1.059,45";"Torgau";""
+"20,600";"39,8";"Starr";"81,91";"88,58";"1.068";"1.059,45";"Torgau";""
+"20,700";"40,8";"Starr";"81,83";"88,54";"1.068";"1.059,45";"Torgau";""
+"20,800";"40,8";"Starr";"81,60";"88,50";"1.068";"1.059,45";"Torgau";""
+"20,900";"40,0";"Starr";"81,39";"88,48";"1.068";"1.059,45";"Torgau";""
+"21,000";"42,3";"Starr";"81,00";"88,45";"1.068";"1.059,45";"Torgau";""
+"21,100";"43,4";"Starr";"80,80";"88,42";"1.068";"1.059,45";"Torgau";""
+"21,200";"42,2";"Starr";"80,90";"88,39";"1.068";"1.059,45";"Torgau";""
+"21,300";"40,4";"Starr";"81,09";"88,36";"1.068";"1.059,45";"Torgau";""
+"21,400";"38,4";"Starr";"81,28";"88,32";"1.068";"1.059,45";"Torgau";""
+"21,500";"40,0";"Starr";"80,94";"88,28";"1.068";"1.059,45";"Torgau";""
+"21,600";"39,8";"Starr";"81,13";"88,24";"1.068";"1.059,45";"Torgau";""
+"21,700";"39,6";"Starr";"81,25";"88,20";"1.068";"1.059,45";"Torgau";""
+"21,800";"38,9";"Starr";"81,28";"88,16";"1.064";"1.059,45";"Torgau";""
+"21,900";"38,6";"Starr";"81,26";"88,13";"1.064";"1.059,45";"Torgau";""
+"22,000";"37,1";"Starr";"81,29";"88,09";"1.064";"1.059,45";"Torgau";""
+"22,100";"35,5";"Starr";"81,30";"88,07";"1.064";"1.059,45";"Torgau";""
+"22,200";"36,1";"Starr";"80,90";"88,04";"1.064";"1.059,45";"Torgau";""
+"22,300";"33,4";"Starr";"80,98";"88,02";"1.064";"1.059,45";"Torgau";""
+"22,400";"35,2";"Starr";"80,94";"87,99";"1.064";"1.059,45";"Torgau";""
+"22,500";"36,5";"Starr";"80,91";"87,95";"1.064";"1.059,45";"Torgau";""
+"22,600";"34,1";"Starr";"81,11";"87,91";"1.064";"1.059,45";"Torgau";""
+"22,700";"32,9";"Starr";"81,09";"87,88";"1.064";"1.059,45";"Torgau";""
+"22,800";"30,8";"Starr";"81,10";"87,84";"1.064";"1.059,45";"Torgau";""
+"22,900";"28,9";"Starr";"81,02";"87,82";"1.064";"1.059,45";"Torgau";""
+"23,000";"28,7";"Starr";"81,11";"87,79";"1.064";"1.059,45";"Torgau";""
+"23,100";"30,2";"Starr";"80,86";"87,75";"1.064";"1.059,45";"Torgau";""
+"23,200";"28,8";"Starr";"80,82";"87,70";"1.064";"1.059,45";"Torgau";""
+"23,300";"27,4";"Starr";"80,78";"87,68";"1.064";"1.059,45";"Torgau";""
+"23,400";"25,2";"Starr";"80,80";"87,65";"1.064";"1.059,45";"Torgau";""
+"23,500";"23,0";"Starr";"80,78";"87,64";"1.064";"1.059,45";"Torgau";""
+"23,600";"29,3";"Starr";"80,74";"87,62";"1.064";"1.059,45";"Torgau";""
+"23,700";"33,6";"Starr";"80,70";"87,58";"1.064";"1.059,45";"Torgau";""
+"23,800";"32,7";"Starr";"80,70";"87,53";"1.064";"1.059,45";"Torgau";""
+"23,900";"32,2";"Starr";"80,64";"87,50";"1.064";"1.059,45";"Torgau";""
+"24,000";"32,9";"Starr";"80,52";"87,47";"1.064";"1.059,45";"Torgau";""
+"24,100";"33,7";"Starr";"80,38";"87,44";"1.064";"1.059,45";"Torgau";""
+"24,200";"35,0";"Starr";"80,16";"87,41";"1.064";"1.059,45";"Torgau";""
+"24,300";"36,3";"Starr";"79,94";"87,39";"1.064";"1.059,45";"Torgau";""
+"24,400";"35,2";"Starr";"80,02";"87,36";"1.064";"1.059,45";"Torgau";""
+"24,500";"33,2";"Starr";"80,24";"87,34";"1.064";"1.059,45";"Torgau";""
+"24,600";"33,7";"Starr";"80,44";"87,31";"1.064";"1.059,45";"Torgau";""
+"24,700";"34,5";"Starr";"80,53";"87,28";"1.064";"1.059,45";"Torgau";""
+"24,800";"35,8";"Starr";"80,50";"87,25";"1.064";"1.059,45";"Torgau";""
+"24,900";"37,9";"Starr";"80,32";"87,21";"1.064";"1.059,45";"Torgau";""
+"25,000";"37,6";"Starr";"80,34";"87,17";"1.064";"1.059,45";"Torgau";""
+"25,100";"37,2";"Starr";"80,36";"87,14";"1.064";"1.059,45";"Torgau";""
+"25,200";"37,2";"Starr";"80,31";"87,11";"1.064";"1.059,45";"Torgau";""
+"25,300";"36,3";"Starr";"80,41";"87,09";"1.064";"1.059,45";"Torgau";""
+"25,400";"35,8";"Starr";"80,36";"87,06";"1.064";"1.059,45";"Torgau";""
+"25,500";"36,5";"Starr";"80,11";"87,04";"1.064";"1.059,45";"Torgau";""
+"25,600";"39,1";"Starr";"79,87";"87,02";"1.064";"1.059,45";"Torgau";""
+"25,700";"40,2";"Starr";"79,79";"86,99";"1.064";"1.059,45";"Torgau";""
+"25,800";"40,0";"Starr";"79,82";"86,95";"1.064";"1.059,45";"Torgau";""
+"25,900";"40,4";"Starr";"79,78";"86,92";"1.064";"1.059,45";"Torgau";""
+"26,000";"41,2";"Starr";"79,52";"86,88";"1.064";"1.059,45";"Torgau";""
+"26,100";"40,3";"Starr";"79,52";"86,86";"1.064";"1.059,45";"Torgau";""
+"26,200";"40,4";"Starr";"79,53";"86,83";"1.064";"1.059,45";"Torgau";""
+"26,300";"40,7";"Starr";"79,52";"86,79";"1.064";"1.059,45";"Torgau";""
+"26,400";"42,0";"Starr";"79,39";"86,75";"1.064";"1.059,45";"Torgau";""
+"26,500";"42,1";"Starr";"79,43";"86,72";"1.064";"1.059,45";"Torgau";""
+"26,600";"38,8";"Starr";"79,75";"86,68";"1.064";"1.059,45";"Torgau";"Bundesland: Freistaat Sachsen"
+"26,700";"36,6";"Starr";"79,90";"86,67";"1.064";"1.059,45";"Torgau";""
+"26,800";"36,9";"Starr";"79,94";"86,65";"1.064";"1.059,45";"Torgau";""
+"26,900";"37,2";"Starr";"79,94";"86,61";"1.064";"1.059,45";"Torgau";""
+"27,000";"37,8";"Starr";"79,91";"86,57";"1.064";"1.059,45";"Torgau";""
+"27,100";"40,2";"Starr";"79,61";"86,53";"1.064";"1.059,45";"Torgau";""
+"27,200";"39,9";"Starr";"79,59";"86,49";"1.064";"1.059,45";"Torgau";""
+"27,300";"38,9";"Starr";"79,68";"86,47";"1.064";"1.059,45";"Torgau";""
+"27,400";"38,2";"Starr";"79,66";"86,45";"1.064";"1.059,45";"Torgau";""
+"27,500";"36,7";"Starr";"79,76";"86,43";"1.064";"1.059,45";"Torgau";""
+"27,600";"34,0";"Starr";"79,89";"86,41";"1.064";"1.059,45";"Torgau";""
+"27,700";"31,0";"Starr";"80,05";"86,39";"1.064";"1.059,45";"Torgau";""
+"27,800";"33,3";"Starr";"79,83";"86,37";"1.064";"1.059,45";"Torgau";""
+"27,900";"36,0";"Starr";"79,52";"86,33";"1.064";"1.059,45";"Torgau";""
+"28,000";"38,4";"Starr";"79,49";"86,29";"1.064";"1.059,45";"Torgau";""
+"28,100";"39,9";"Starr";"79,51";"86,24";"1.064";"1.059,45";"Torgau";""
+"28,200";"38,6";"Starr";"79,52";"86,18";"1.064";"1.059,45";"Torgau";""
+"28,300";"37,6";"Starr";"79,49";"86,17";"1.064";"1.059,45";"Torgau";""
+"28,400";"38,4";"Starr";"79,45";"86,15";"1.064";"1.059,45";"Torgau";""
+"28,500";"38,8";"Starr";"79,44";"86,11";"1.064";"1.059,45";"Torgau";""
+"28,600";"38,5";"Starr";"79,44";"86,07";"1.064";"1.059,45";"Torgau";""
+"28,700";"38,8";"Starr";"79,35";"86,04";"1.064";"1.059,45";"Torgau";""
+"28,800";"39,5";"Starr";"79,27";"86,00";"1.064";"1.059,45";"Torgau";""
+"28,900";"40,1";"Starr";"79,18";"85,97";"1.064";"1.059,45";"Torgau";""
+"29,000";"42,4";"Starr";"78,96";"85,93";"1.064";"1.059,45";"Torgau";""
+"29,100";"42,2";"Starr";"79,04";"85,89";"1.064";"1.059,45";"Torgau";""
+"29,200";"41,0";"Starr";"79,13";"85,84";"1.064";"1.059,45";"Torgau";""
+"29,300";"40,2";"Starr";"79,15";"85,82";"1.064";"1.059,45";"Torgau";""
+"29,400";"39,8";"Starr";"79,16";"85,80";"1.064";"1.059,45";"Torgau";""
+"29,500";"40,0";"Starr";"79,07";"85,77";"1.064";"1.059,45";"Torgau";""
+"29,600";"41,4";"Starr";"78,94";"85,73";"1.064";"1.059,45";"Torgau";""
+"29,700";"42,0";"Starr";"78,91";"85,69";"1.064";"1.059,45";"Torgau";""
+"29,800";"40,2";"Starr";"78,95";"85,64";"1.064";"1.059,45";"Torgau";""
+"29,900";"38,7";"Starr";"78,95";"85,63";"1.064";"1.059,45";"Torgau";""
+"30,000";"43,5";"Starr";"78,45";"85,62";"1.064";"1.059,45";"Torgau";""
+"30,100";"46,0";"Starr";"78,25";"85,59";"1.064";"1.059,45";"Torgau";""
+"30,200";"45,5";"Starr";"78,09";"85,55";"1.064";"1.059,45";"Torgau";""
+"30,300";"43,7";"Starr";"78,07";"85,54";"1.064";"1.059,45";"Torgau";""
+"30,400";"44,8";"Starr";"78,04";"85,52";"1.064";"1.059,45";"Torgau";""
+"30,500";"43,7";"Starr";"78,30";"85,48";"1.064";"1.059,45";"Torgau";""
+"30,600";"44,0";"Starr";"78,27";"85,44";"1.064";"1.059,45";"Torgau";""
+"30,700";"44,6";"Starr";"78,22";"85,42";"1.064";"1.059,45";"Torgau";""
+"30,800";"43,3";"Starr";"78,30";"85,39";"1.062";"1.059,45";"Torgau";""
+"30,900";"42,7";"Starr";"78,26";"85,37";"1.062";"1.059,45";"Torgau";""
+"31,000";"43,9";"Starr";"78,19";"85,34";"1.062";"1.059,45";"Torgau";""
+"31,100";"44,2";"Starr";"78,19";"85,29";"1.062";"1.059,45";"Torgau";""
+"31,200";"46,7";"Starr";"78,03";"85,24";"1.062";"1.059,45";"Torgau";""
+"31,300";"50,3";"Starr";"77,69";"85,19";"1.062";"1.059,45";"Torgau";""
+"31,400";"47,7";"Starr";"77,98";"85,14";"1.062";"1.059,45";"Torgau";""
+"31,500";"45,8";"Starr";"78,14";"85,09";"1.062";"1.059,45";"Torgau";""
+"31,600";"45,6";"Starr";"78,05";"85,03";"1.062";"1.059,45";"Torgau";""
+"32,200";"43,3";"Starr";"77,85";"85,01";"1.062";"1.059,45";"Torgau";""
+"32,300";"42,8";"Starr";"77,84";"85,00";"1.062";"1.059,45";"Torgau";""
+"32,400";"44,5";"Starr";"77,69";"84,98";"1.062";"1.059,45";"Torgau";""
+"32,500";"45,1";"Starr";"77,68";"84,95";"1.062";"1.059,45";"Torgau";""
+"32,600";"45,1";"Starr";"77,75";"84,92";"1.062";"1.059,45";"Torgau";""
+"32,700";"45,9";"Starr";"77,70";"84,89";"1.062";"1.059,45";"Torgau";""
+"32,800";"46,3";"Starr";"77,59";"84,85";"1.062";"1.059,45";"Torgau";""
+"32,900";"44,9";"Starr";"77,74";"84,83";"1.062";"1.059,45";"Torgau";""
+"33,000";"47,0";"Starr";"77,45";"84,80";"1.062";"1.059,45";"Torgau";""
+"33,100";"47,6";"Starr";"77,35";"84,78";"1.062";"1.059,45";"Torgau";""
+"33,200";"47,2";"Starr";"77,40";"84,76";"1.062";"1.059,45";"Torgau";""
+"33,300";"46,1";"Starr";"77,55";"84,74";"1.062";"1.059,45";"Torgau";""
+"33,400";"45,9";"Starr";"77,57";"84,71";"1.062";"1.059,45";"Torgau";""
+"33,500";"46,1";"Starr";"77,54";"84,69";"1.062";"1.059,45";"Torgau";""
+"33,600";"47,7";"Starr";"77,42";"84,67";"1.062";"1.059,45";"Torgau";""
+"33,700";"48,4";"Starr";"77,39";"84,64";"1.062";"1.059,45";"Torgau";""
+"33,800";"49,6";"Starr";"77,24";"84,61";"1.062";"1.059,45";"Torgau";""
+"33,900";"50,9";"Starr";"77,08";"84,59";"1.062";"1.059,45";"Torgau";""
+"34,000";"50,0";"Starr";"77,04";"84,56";"1.062";"1.059,45";"Torgau";""
+"34,100";"50,3";"Starr";"76,80";"84,54";"1.062";"1.059,45";"Torgau";""
+"34,200";"50,4";"Starr";"76,77";"84,52";"1.062";"1.059,45";"Torgau";""
+"34,300";"48,9";"Starr";"76,95";"84,50";"1.062";"1.059,45";"Torgau";""
+"34,400";"49,2";"Starr";"77,08";"84,47";"1.062";"1.059,45";"Torgau";""
+"34,500";"49,4";"Starr";"77,19";"84,45";"1.062";"1.059,45";"Torgau";""
+"34,600";"48,6";"Starr";"77,31";"84,42";"1.062";"1.059,45";"Torgau";""
+"34,700";"48,2";"Starr";"77,36";"84,39";"1.062";"1.059,45";"Torgau";""
+"34,800";"50,8";"Starr";"77,05";"84,36";"1.062";"1.059,45";"Torgau";""
+"34,900";"52,9";"Starr";"76,83";"84,35";"1.062";"1.059,45";"Torgau";""
+"35,000";"51,5";"Starr";"76,88";"84,33";"1.062";"1.059,45";"Torgau";""
+"35,100";"52,6";"Mobil";"76,55";"84,31";"1.062";"1.059,45";"Torgau";""
+"35,200";"53,8";"Mobil";"76,52";"84,28";"1.062";"1.059,45";"Torgau";""
+"35,300";"53,6";"Starr";"76,62";"84,25";"1.062";"1.059,45";"Torgau";""
+"35,400";"53,4";"Starr";"76,63";"84,21";"1.062";"1.059,45";"Torgau";""
+"35,500";"54,3";"Starr";"76,52";"84,19";"1.062";"1.059,45";"Torgau";""
+"35,600";"57,6";"Starr";"76,11";"84,16";"1.062";"1.059,45";"Torgau";""
+"35,700";"59,8";"Starr";"75,83";"84,13";"1.062";"1.059,45";"Torgau";""
+"35,800";"60,1";"Starr";"75,82";"84,10";"1.062";"1.059,45";"Torgau";""
+"35,900";"59,7";"Starr";"75,88";"84,07";"1.062";"1.059,45";"Torgau";""
+"36,000";"59,6";"Starr";"75,87";"84,03";"1.062";"1.059,45";"Torgau";""
+"36,100";"58,5";"Starr";"75,98";"84,00";"1.062";"1.059,45";"Torgau";""
+"36,200";"57,9";"Starr";"75,83";"83,97";"1.062";"1.059,45";"Torgau";""
+"36,300";"56,8";"Starr";"75,71";"83,96";"1.062";"1.059,45";"Torgau";""
+"36,400";"57,3";"Starr";"75,97";"83,94";"1.062";"1.059,45";"Torgau";""
+"36,500";"56,3";"Starr";"76,21";"83,90";"1.062";"1.059,45";"Torgau";""
+"36,600";"57,5";"Starr";"76,00";"83,86";"1.062";"1.059,45";"Torgau";""
+"36,700";"55,3";"Starr";"76,19";"83,84";"1.062";"1.059,45";"Torgau";""
+"36,800";"55,7";"Starr";"76,17";"83,81";"1.062";"1.059,45";"Torgau";""
+"36,900";"55,0";"Starr";"76,25";"83,78";"1.062";"1.059,45";"Torgau";""
+"37,000";"55,1";"Starr";"76,21";"83,74";"1.062";"1.059,45";"Torgau";""
+"37,100";"56,0";"Starr";"76,08";"83,71";"1.062";"1.059,45";"Torgau";""
+"37,200";"55,6";"Starr";"76,03";"83,68";"1.062";"1.059,45";"Torgau";""
+"37,300";"55,2";"Starr";"75,99";"83,66";"1.062";"1.059,45";"Torgau";""
+"37,400";"52,7";"Starr";"76,20";"83,64";"1.062";"1.059,45";"Torgau";""
+"37,500";"50,8";"Starr";"76,34";"83,63";"1.062";"1.059,45";"Torgau";""
+"37,600";"52,1";"Starr";"76,23";"83,61";"1.062";"1.059,45";"Torgau";""
+"37,700";"52,1";"Starr";"76,25";"83,58";"1.062";"1.059,45";"Torgau";""
+"37,800";"51,3";"Starr";"75,97";"83,55";"1.062";"1.059,45";"Torgau";""
+"37,900";"46,1";"Starr";"75,94";"83,56";"1.062";"1.059,45";"Torgau";""
+"38,000";"46,6";"Starr";"76,03";"83,56";"1.062";"1.059,45";"Torgau";""
+"38,100";"46,7";"Starr";"76,14";"83,54";"1.062";"1.059,45";"Torgau";""
+"38,200";"48,6";"Starr";"76,17";"83,52";"1.062";"1.059,45";"Torgau";""
+"38,300";"50,7";"Starr";"76,05";"83,47";"1.062";"1.059,45";"Torgau";""
+"38,400";"48,9";"Starr";"76,12";"83,42";"1.062";"1.059,45";"Torgau";""
+"38,500";"47,5";"Starr";"76,14";"83,40";"1.062";"1.059,45";"Torgau";""
+"38,600";"48,0";"Starr";"76,22";"83,37";"1.062";"1.059,45";"Torgau";""
+"38,700";"49,2";"Starr";"76,15";"83,33";"1.062";"1.059,45";"Torgau";""
+"38,800";"48,7";"Starr";"76,22";"83,29";"1.062";"1.059,45";"Torgau";""
+"38,900";"48,2";"Starr";"76,29";"83,26";"1.062";"1.059,45";"Torgau";""
+"39,000";"46,1";"Starr";"76,29";"83,23";"1.062";"1.059,45";"Torgau";""
+"39,100";"44,6";"Starr";"76,10";"83,22";"1.062";"1.059,45";"Torgau";""
+"39,200";"45,6";"Starr";"76,13";"83,21";"1.062";"1.059,45";"Torgau";""
+"39,300";"45,9";"Starr";"76,20";"83,18";"1.062";"1.059,45";"Torgau";""
+"39,400";"47,3";"Starr";"75,99";"83,14";"1.062";"1.059,45";"Torgau";""
+"39,500";"47,6";"Starr";"75,94";"83,12";"1.062";"1.059,45";"Torgau";""
+"39,600";"49,1";"Starr";"75,74";"83,09";"1.062";"1.059,45";"Torgau";""
+"39,700";"49,8";"Starr";"75,63";"83,06";"1.062";"1.059,45";"Torgau";""
+"39,800";"50,7";"Starr";"75,41";"83,02";"1.062";"1.059,45";"Torgau";""
+"39,900";"51,5";"Starr";"75,20";"83,01";"1.062";"1.059,45";"Torgau";""
+"40,000";"51,8";"Starr";"75,08";"82,99";"1.062";"1.059,45";"Torgau";""
+"40,100";"51,2";"Starr";"75,07";"82,98";"1.062";"1.059,45";"Torgau";""
+"40,200";"50,1";"Starr";"75,00";"82,96";"1.062";"1.059,45";"Torgau";""
+"40,300";"47,8";"Starr";"75,04";"82,94";"1.062";"1.059,45";"Torgau";""
+"40,400";"47,9";"Starr";"74,99";"82,92";"1.062";"1.059,45";"Torgau";""
+"40,500";"48,8";"Starr";"74,83";"82,90";"1.062";"1.059,45";"Torgau";""
+"40,600";"46,1";"Starr";"75,04";"82,87";"1.062";"1.059,45";"Torgau";""
+"40,700";"42,7";"Starr";"75,37";"82,85";"1.062";"1.059,45";"Torgau";""
+"40,800";"39,3";"Starr";"75,44";"82,83";"1.059";"1.059,45";"Torgau";""
+"40,900";"36,1";"Starr";"75,39";"82,82";"1.059";"1.059,45";"Torgau";""
+"41,000";"38,1";"Starr";"75,40";"82,81";"1.059";"1.059,45";"Torgau";""
+"41,100";"39,2";"Starr";"75,49";"82,78";"1.059";"1.059,45";"Torgau";""
+"41,200";"41,9";"Starr";"75,40";"82,75";"1.059";"1.059,45";"Torgau";""
+"41,300";"46,9";"Starr";"74,89";"82,71";"1.059";"1.059,45";"Torgau";""
+"41,400";"48,9";"Starr";"74,60";"82,67";"1.059";"1.059,45";"Torgau";""
+"41,500";"48,9";"Starr";"74,63";"82,66";"1.059";"1.059,45";"Torgau";""
+"41,600";"47,3";"Starr";"74,75";"82,65";"1.059";"1.059,45";"Torgau";""
+"41,700";"47,8";"Starr";"74,71";"82,63";"1.059";"1.059,45";"Torgau";""
+"41,800";"46,4";"Starr";"74,91";"82,61";"1.059";"1.059,45";"Torgau";""
+"41,900";"45,3";"Starr";"75,05";"82,59";"1.059";"1.059,45";"Torgau";""
+"42,000";"47,6";"Starr";"75,07";"82,56";"1.059";"1.059,45";"Torgau";""
+"42,100";"49,7";"Starr";"75,05";"82,53";"1.059";"1.059,45";"Torgau";""
+"42,200";"49,2";"Starr";"74,97";"82,50";"1.059";"1.059,45";"Torgau";""
+"42,300";"49,6";"Starr";"74,74";"82,49";"1.059";"1.059,45";"Torgau";""
+"42,400";"51,0";"Starr";"74,68";"82,48";"1.059";"1.059,45";"Torgau";""
+"42,500";"52,9";"Starr";"74,52";"82,46";"1.059";"1.059,45";"Torgau";""
+"42,600";"53,0";"Starr";"74,49";"82,43";"1.059";"1.059,45";"Torgau";""
+"42,700";"53,7";"Starr";"74,39";"82,42";"1.059";"1.059,45";"Torgau";""
+"42,800";"55,1";"Starr";"74,34";"82,40";"1.059";"1.059,45";"Torgau";""
+"42,900";"57,7";"Starr";"74,13";"82,38";"1.059";"1.059,45";"Torgau";""
+"43,000";"58,6";"Starr";"74,10";"82,36";"1.059";"1.059,45";"Torgau";""
+"43,100";"56,2";"Starr";"74,47";"82,34";"1.059";"1.059,45";"Torgau";""
+"43,200";"58,1";"Starr";"74,35";"82,32";"1.059";"1.059,45";"Torgau";""
+"43,300";"57,8";"Starr";"74,48";"82,30";"1.059";"1.059,45";"Torgau";""
+"43,400";"58,2";"Starr";"74,58";"82,28";"1.059";"1.059,45";"Torgau";""
+"43,500";"60,7";"Starr";"74,40";"82,26";"1.059";"1.059,45";"Torgau";""
+"43,600";"60,6";"Starr";"74,43";"82,24";"1.059";"1.059,45";"Torgau";""
+"43,700";"59,5";"Starr";"74,57";"82,23";"1.059";"1.059,45";"Torgau";""
+"43,800";"60,2";"Starr";"74,35";"82,22";"1.059";"1.059,45";"Torgau";""
+"43,900";"60,0";"Starr";"74,18";"82,22";"1.059";"1.059,45";"Torgau";""
+"44,000";"61,4";"Starr";"74,41";"82,21";"1.059";"1.059,45";"Torgau";""
+"44,100";"62,9";"Starr";"74,47";"82,17";"1.059";"1.059,45";"Torgau";""
+"44,200";"64,4";"Starr";"74,30";"82,13";"1.059";"1.059,45";"Torgau";""
+"44,300";"65,7";"Starr";"74,17";"82,13";"1.059";"1.059,45";"Torgau";""
+"44,400";"68,0";"Starr";"74,08";"82,13";"1.059";"1.059,45";"Torgau";""
+"44,500";"72,2";"Starr";"73,75";"82,11";"1.059";"1.059,45";"Torgau";""
+"44,600";"74,3";"Starr";"73,66";"82,08";"1.059";"1.059,45";"Torgau";""
+"44,700";"75,3";"Starr";"73,65";"82,05";"1.059";"1.059,45";"Torgau";""
+"44,800";"76,0";"Starr";"73,62";"82,02";"1.059";"1.059,45";"Torgau";""
+"44,900";"77,6";"Starr";"73,52";"82,00";"1.059";"1.059,45";"Torgau";""
+"45,000";"79,8";"Starr";"73,35";"81,98";"1.059";"1.059,45";"Torgau";""
+"45,100";"80,2";"Starr";"73,36";"81,97";"1.059";"1.059,45";"Torgau";""
+"45,200";"80,4";"Starr";"73,46";"81,96";"1.059";"1.059,45";"Torgau";""
+"45,300";"80,7";"Starr";"73,47";"81,93";"1.059";"1.059,45";"Torgau";""
+"45,400";"82,1";"Starr";"73,39";"81,89";"1.059";"1.059,45";"Torgau";""
+"45,500";"82,8";"Mobil";"73,39";"81,89";"1.059";"1.059,45";"Torgau";""
+"45,600";"83,0";"Mobil";"73,45";"81,88";"1.059";"1.059,45";"Torgau";""
+"45,700";"79,7";"Mobil";"73,58";"81,84";"1.059";"1.059,45";"Torgau";""
+"45,800";"76,5";"Mobil";"73,73";"81,80";"1.059";"1.059,45";"Torgau";"Hafen: Torgau"
+"45,900";"77,8";"Starr";"73,47";"81,80";"1.059";"1.059,45";"Torgau";""
+"46,000";"75,4";"Starr";"73,56";"81,79";"1.059";"1.059,45";"Torgau";""
+"46,100";"71,9";"Starr";"73,76";"81,77";"1.059";"1.059,45";"Torgau";"Brücke: Torgau -Straße B87"
+"46,200";"64,2";"Starr";"74,44";"81,75";"1.059";"1.059,45";"Torgau";""
+"46,300";"65,9";"Starr";"74,17";"81,72";"1.059";"1.059,45";"Torgau";""
+"46,400";"65,5";"Starr";"74,07";"81,69";"1.059";"1.059,45";"Torgau";""
+"46,500";"62,8";"Starr";"74,20";"81,66";"1.059";"1.059,45";"Torgau";""
+"46,600";"61,5";"Starr";"74,18";"81,63";"1.059";"1.059,45";"Torgau";""
+"46,700";"60,8";"Starr";"74,09";"81,61";"1.059";"1.059,45";"Torgau";""
+"46,800";"63,0";"Starr";"73,58";"81,59";"1.059";"1.059,45";"Torgau";"Geschiebemessstelle: Torgau"
+"46,900";"62,0";"Starr";"73,51";"81,58";"1.059";"1.059,45";"Torgau";""
+"47,000";"62,6";"Starr";"73,62";"81,57";"1.059";"1.059,45";"Torgau";""
+"47,100";"61,6";"Starr";"73,80";"81,53";"1.059";"1.059,45";"Torgau";""
+"47,200";"60,3";"Starr";"73,81";"81,48";"1.059";"1.059,45";"Torgau";""
+"47,300";"65,5";"Starr";"73,09";"81,48";"1.059";"1.059,45";"Torgau";""
+"47,400";"65,1";"Starr";"72,85";"81,47";"1.059";"1.059,45";"Torgau";""
+"47,500";"61,3";"Starr";"72,84";"81,47";"1.059";"1.059,45";"Torgau";""
+"47,600";"61,6";"Starr";"72,92";"81,46";"1.059";"1.059,45";"Torgau";""
+"47,700";"58,2";"Starr";"73,43";"81,44";"1.059";"1.059,45";"Torgau";""
+"47,800";"58,4";"Starr";"73,35";"81,41";"1.059";"1.059,45";"Torgau";""
+"47,900";"58,5";"Starr";"73,29";"81,40";"1.059";"1.059,45";"Torgau";""
+"48,000";"57,9";"Starr";"73,58";"81,38";"1.059";"1.059,45";"Torgau";""
+"48,100";"59,0";"Starr";"73,56";"81,35";"1.059";"1.059,45";"Torgau";""
+"48,200";"60,0";"Starr";"73,51";"81,32";"1.059";"1.059,45";"Torgau";""
+"48,300";"60,3";"Starr";"73,52";"81,30";"1.059";"1.059,45";"Torgau";""
+"48,400";"60,2";"Starr";"73,47";"81,27";"1.059";"1.059,45";"Torgau";""
+"48,500";"58,7";"Starr";"73,57";"81,25";"1.059";"1.059,45";"Torgau";""
+"48,600";"58,7";"Starr";"73,51";"81,22";"1.059";"1.059,45";"Torgau";""
+"48,700";"59,3";"Starr";"73,40";"81,20";"1.059";"1.059,45";"Torgau";""
+"48,800";"58,8";"Starr";"73,36";"81,17";"1.059";"1.059,45";"Torgau";""
+"48,900";"58,0";"Starr";"73,38";"81,16";"1.059";"1.059,45";"Torgau";""
+"49,000";"59,1";"Starr";"73,28";"81,15";"1.059";"1.059,45";"Torgau";""
+"49,100";"56,6";"Starr";"73,56";"81,12";"1.059";"1.059,45";"Torgau";""
+"49,200";"56,0";"Starr";"73,66";"81,08";"1.059";"1.059,45";"Torgau";""
+"49,300";"56,6";"Starr";"73,62";"81,06";"1.059";"1.059,45";"Torgau";""
+"49,400";"57,8";"Starr";"73,35";"81,04";"1.059";"1.059,45";"Torgau";""
+"49,500";"57,8";"Starr";"73,17";"81,03";"1.059";"1.059,45";"Torgau";""
+"49,600";"56,6";"Starr";"73,27";"81,01";"1.059";"1.059,45";"Torgau";""
+"49,700";"57,1";"Starr";"73,16";"80,99";"1.059";"1.059,45";"Torgau";""
+"49,800";"58,3";"Starr";"72,93";"80,96";"1.059";"1.059,45";"Torgau";""
+"49,900";"58,0";"Starr";"72,90";"80,94";"1.059";"1.059,45";"Torgau";""
+"50,000";"57,4";"Starr";"73,21";"80,92";"1.059";"1.059,45";"Torgau";""
+"50,100";"58,0";"Starr";"73,23";"80,87";"1.059";"1.059,45";"Torgau";""
+"50,200";"57,6";"Starr";"73,12";"80,82";"1.059";"1.059,45";"Torgau";""
+"50,300";"59,3";"Starr";"72,76";"80,81";"1.059";"1.059,45";"Torgau";""
+"50,400";"55,6";"Starr";"73,07";"80,79";"1.059";"1.059,45";"Torgau";""
+"50,500";"52,0";"Starr";"73,36";"80,78";"1.059";"1.059,45";"Torgau";""
+"50,600";"51,8";"Starr";"73,34";"80,76";"1.059";"1.059,45";"Torgau";""
+"50,700";"51,8";"Starr";"73,30";"80,74";"1.059";"1.059,45";"Torgau";""
+"50,800";"52,7";"Starr";"73,23";"80,72";"1.059";"1.059,45";"Torgau";""
+"50,900";"53,9";"Starr";"73,11";"80,70";"1.059";"1.059,45";"Torgau";""
+"51,000";"54,2";"Starr";"73,12";"80,67";"1.059";"1.059,45";"Torgau";""
+"51,100";"57,2";"Starr";"72,77";"80,64";"1.059";"1.059,45";"Torgau";""
+"51,200";"57,6";"Starr";"72,70";"80,61";"1.059";"1.059,45";"Torgau";""
+"51,300";"57,8";"Starr";"72,64";"80,58";"1.059";"1.059,45";"Torgau";""
+"51,400";"58,2";"Starr";"72,55";"80,55";"1.059";"1.059,45";"Torgau";""
+"51,500";"56,1";"Starr";"72,78";"80,53";"1.059";"1.059,45";"Torgau";""
+"51,600";"56,3";"Starr";"72,75";"80,50";"1.059";"1.059,45";"Torgau";""
+"51,700";"56,5";"Starr";"72,71";"80,48";"1.059";"1.059,45";"Torgau";""
+"51,800";"57,1";"Starr";"72,66";"80,45";"1.059";"1.059,45";"Torgau";""
+"51,900";"55,8";"Starr";"72,82";"80,42";"1.059";"1.059,45";"Torgau";""
+"52,000";"54,1";"Starr";"72,92";"80,39";"1.059";"1.059,45";"Torgau";""
+"52,100";"57,7";"Starr";"72,40";"80,37";"1.059";"1.059,45";"Torgau";""
+"52,200";"59,4";"Starr";"72,19";"80,34";"1.059";"1.059,45";"Torgau";""
+"52,300";"60,4";"Starr";"72,07";"80,32";"1.059";"1.059,45";"Torgau";""
+"52,400";"60,6";"Starr";"72,00";"80,29";"1.059";"1.059,45";"Torgau";""
+"52,500";"60,9";"Starr";"71,90";"80,28";"1.059";"1.059,45";"Torgau";""
+"52,600";"62,6";"Starr";"71,75";"80,27";"1.059";"1.059,45";"Torgau";""
+"52,700";"60,8";"Starr";"72,02";"80,26";"1.059";"1.059,45";"Torgau";""
+"52,800";"62,4";"Starr";"72,01";"80,24";"1.059";"1.059,45";"Torgau";""
+"52,900";"59,8";"Starr";"72,42";"80,20";"1.059";"1.059,45";"Torgau";""
+"53,000";"60,2";"Starr";"72,39";"80,16";"1.059";"1.059,45";"Torgau";""
+"53,100";"62,4";"Starr";"72,18";"80,14";"1.059";"1.059,45";"Torgau";""
+"53,200";"63,2";"Starr";"72,18";"80,12";"1.059";"1.059,45";"Torgau";""
+"53,300";"63,5";"Starr";"72,21";"80,09";"1.059";"1.059,45";"Torgau";""
+"53,400";"63,2";"Starr";"72,22";"80,05";"1.059";"1.059,45";"Torgau";""
+"53,500";"66,8";"Starr";"71,83";"80,03";"1.059";"1.059,45";"Torgau";""
+"53,600";"64,7";"Starr";"72,06";"80,00";"1.059";"1.059,45";"Torgau";""
+"53,700";"66,0";"Starr";"71,92";"79,99";"1.059";"1.059,45";"Torgau";""
+"53,800";"66,3";"Starr";"71,92";"79,97";"1.059";"1.059,45";"Torgau";""
+"53,900";"65,1";"Starr";"72,06";"79,96";"1.059";"1.059,45";"Torgau";""
+"54,000";"64,8";"Starr";"72,18";"79,94";"1.059";"1.059,45";"Torgau";""
+"54,100";"66,0";"Starr";"72,13";"79,92";"1.059";"1.059,45";"Torgau";""
+"54,200";"65,3";"Starr";"72,19";"79,90";"1.059";"1.059,45";"Torgau";""
+"54,300";"66,3";"Starr";"72,10";"79,89";"1.059";"1.059,45";"Torgau";""
+"54,400";"68,4";"Starr";"71,94";"79,88";"1.059";"1.059,45";"Torgau";""
+"54,500";"66,4";"Starr";"72,20";"79,86";"1.059";"1.059,45";"Torgau";""
+"54,600";"66,0";"Starr";"72,30";"79,84";"1.059";"1.059,45";"Torgau";""
+"54,700";"67,2";"Mobil";"72,21";"79,81";"1.059";"1.059,45";"Torgau";""
+"54,800";"73,0";"Mobil";"71,64";"79,77";"1.059";"1.059,45";"Torgau";""
+"54,900";"76,4";"Mobil";"71,34";"79,77";"1.059";"1.059,45";"Torgau";""
+"55,000";"77,4";"Mobil";"71,34";"79,76";"1.059";"1.059,45";"Torgau";""
+"55,100";"71,1";"Mobil";"71,85";"79,73";"1.059";"1.059,45";"Torgau";""
+"55,200";"73,4";"Mobil";"71,53";"79,69";"1.059";"1.059,45";"Torgau";""
+"55,300";"69,6";"Mobil";"71,82";"79,67";"1.059";"1.059,45";"Torgau";""
+"55,400";"68,4";"Starr";"71,84";"79,64";"1.059";"1.059,45";"Torgau";""
+"55,500";"67,1";"Starr";"71,88";"79,62";"1.059";"1.059,45";"Torgau";""
+"55,600";"62,9";"Starr";"72,21";"79,60";"1.059";"1.059,45";"Torgau";""
+"55,700";"63,3";"Starr";"72,07";"79,59";"1.059";"1.059,45";"Torgau";""
+"55,800";"63,0";"Starr";"72,07";"79,57";"1.059";"1.059,45";"Torgau";""
+"55,900";"64,0";"Starr";"71,91";"79,54";"1.059";"1.059,45";"Torgau";""
+"56,000";"65,5";"Starr";"71,57";"79,51";"1.059";"1.059,45";"Torgau";""
+"56,100";"64,2";"Starr";"71,47";"79,50";"1.059";"1.059,45";"Torgau";""
+"56,200";"60,4";"Starr";"71,75";"79,49";"1.059";"1.059,45";"Torgau";""
+"56,300";"58,4";"Starr";"71,82";"79,48";"1.059";"1.059,45";"Torgau";""
+"56,400";"59,7";"Starr";"71,64";"79,46";"1.059";"1.059,45";"Torgau";""
+"56,500";"57,3";"Starr";"71,88";"79,44";"1.059";"1.059,45";"Torgau";""
+"56,600";"56,2";"Starr";"71,80";"79,41";"1.059";"1.059,45";"Torgau";""
+"56,700";"56,9";"Starr";"71,48";"79,39";"1.059";"1.059,45";"Torgau";""
+"56,800";"56,6";"Starr";"71,38";"79,37";"1.059";"1.059,45";"Torgau";""
+"56,900";"55,5";"Starr";"71,38";"79,35";"1.059";"1.059,45";"Torgau";""
+"57,000";"54,5";"Starr";"71,43";"79,33";"1.059";"1.059,45";"Torgau";""
+"57,100";"52,8";"Starr";"71,57";"79,31";"1.059";"1.059,45";"Torgau";""
+"57,200";"49,5";"Starr";"72,00";"79,28";"1.059";"1.059,45";"Torgau";""
+"57,300";"52,3";"Starr";"71,64";"79,26";"1.059";"1.059,45";"Torgau";""
+"57,400";"57,0";"Starr";"70,98";"79,23";"1.059";"1.059,45";"Torgau";""
+"57,500";"56,6";"Starr";"70,97";"79,20";"1.059";"1.059,45";"Torgau";""
+"57,600";"54,7";"Starr";"71,21";"79,17";"1.059";"1.059,45";"Torgau";""
+"57,700";"52,9";"Starr";"71,41";"79,13";"1.059";"1.059,45";"Torgau";""
+"57,800";"52,6";"Starr";"71,21";"79,09";"1.059";"1.059,45";"Torgau";""
+"57,900";"51,6";"Starr";"71,08";"79,07";"1.059";"1.059,45";"Torgau";""
+"58,000";"50,7";"Starr";"71,20";"79,05";"1.059";"1.059,45";"Torgau";""
+"58,100";"49,7";"Starr";"71,34";"79,03";"1.059";"1.059,45";"Torgau";""
+"58,200";"45,8";"Starr";"71,58";"79,01";"1.059";"1.059,45";"Torgau";""
+"58,300";"43,1";"Starr";"71,62";"79,00";"1.059";"1.059,45";"Torgau";""
+"58,400";"41,0";"Starr";"71,70";"78,98";"1.059";"1.059,45";"Torgau";""
+"58,500";"42,4";"Starr";"71,18";"78,96";"1.059";"1.059,45";"Torgau";""
+"58,600";"44,2";"Starr";"70,75";"78,94";"1.059";"1.059,45";"Torgau";""
+"58,700";"41,6";"Starr";"71,06";"78,92";"1.059";"1.059,45";"Torgau";""
+"58,800";"36,5";"Starr";"71,38";"78,90";"1.059";"1.059,45";"Torgau";""
+"58,900";"31,2";"Starr";"71,71";"78,88";"1.059";"1.059,45";"Torgau";""
+"59,000";"33,0";"Starr";"71,54";"78,86";"1.059";"1.059,45";"Torgau";""
+"59,100";"34,2";"Starr";"71,49";"78,84";"1.059";"1.059,45";"Torgau";""
+"59,200";"25,3";"Starr";"71,31";"78,81";"1.059";"1.059,45";"Torgau";""
+"59,300";"9,8";"Starr";"71,07";"78,82";"1.059";"1.059,45";"Torgau";""
+"59,400";"22,2";"Starr";"70,97";"78,82";"1.059";"1.059,45";"Torgau";""
+"59,500";"32,1";"Mobil";"70,79";"78,80";"1.059";"1.059,45";"Torgau";""
+"59,600";"31,8";"Mobil";"70,95";"78,77";"1.059";"1.059,45";"Torgau";""
+"59,700";"31,3";"Mobil";"71,15";"78,75";"1.059";"1.059,45";"Torgau";""
+"59,800";"30,6";"Mobil";"71,37";"78,73";"1.059";"1.059,45";"Torgau";""
+"59,900";"30,6";"Mobil";"71,44";"78,72";"1.059";"1.059,45";"Torgau";""
+"60,000";"30,5";"Mobil";"71,49";"78,70";"1.059";"1.059,45";"Torgau";""
+"60,100";"30,1";"Mobil";"71,59";"78,69";"1.059";"1.059,45";"Torgau";""
+"60,200";"36,0";"Mobil";"71,53";"78,67";"1.059";"1.059,45";"Torgau";"HW-Schutz: Prettiner-Deich"
+"60,300";"40,1";"Mobil";"71,52";"78,63";"1.059";"1.059,45";"Torgau";""
+"60,400";"40,1";"Mobil";"71,41";"78,59";"1.059";"1.059,45";"Torgau";""
+"60,500";"39,3";"Mobil";"71,43";"78,58";"1.059";"1.059,45";"Torgau";""
+"60,600";"38,8";"Mobil";"71,44";"78,57";"1.059";"1.059,45";"Torgau";""
+"60,700";"39,4";"Mobil";"71,25";"78,56";"1.059";"1.059,45";"Torgau";""
+"60,800";"41,8";"Mobil";"71,18";"78,54";"1.059";"1.059,45";"Torgau";""
+"60,900";"44,0";"Mobil";"71,12";"78,52";"1.059";"1.059,45";"Torgau";""
+"61,000";"45,0";"Mobil";"70,93";"78,50";"1.059";"1.059,45";"Torgau";""
+"61,100";"45,1";"Mobil";"70,88";"78,49";"1.059";"1.059,45";"Torgau";""
+"61,200";"49,4";"Mobil";"70,83";"78,47";"1.059";"1.059,45";"Torgau";""
+"61,300";"51,9";"Mobil";"70,88";"78,45";"1.059";"1.059,45";"Torgau";""
+"61,400";"52,9";"Mobil";"70,77";"78,42";"1.059";"1.059,45";"Torgau";""
+"61,500";"51,2";"Mobil";"71,01";"78,41";"1.059";"1.059,45";"Torgau";""
+"61,600";"53,8";"Mobil";"70,81";"78,39";"1.059";"1.059,45";"Torgau";""
+"61,700";"57,2";"Mobil";"70,52";"78,37";"1.059";"1.059,45";"Torgau";""
+"61,800";"58,6";"Mobil";"70,39";"78,35";"1.059";"1.059,45";"Torgau";""
+"61,900";"59,2";"Mobil";"70,36";"78,34";"1.059";"1.059,45";"Torgau";""
+"62,000";"60,8";"Mobil";"70,41";"78,32";"1.059";"1.059,45";"Torgau";""
+"62,100";"65,4";"Mobil";"70,07";"78,30";"1.059";"1.059,45";"Torgau";""
+"62,200";"62,1";"Mobil";"70,53";"78,28";"1.059";"1.059,45";"Torgau";""
+"62,300";"59,3";"Mobil";"70,94";"78,26";"1.059";"1.059,45";"Torgau";""
+"62,400";"58,9";"Starr";"71,11";"78,24";"1.059";"1.059,45";"Torgau";""
+"62,500";"59,0";"Starr";"71,23";"78,23";"1.059";"1.059,45";"Torgau";""
+"62,600";"61,4";"Starr";"71,06";"78,21";"1.059";"1.059,45";"Torgau";""
+"62,700";"62,5";"Starr";"70,89";"78,20";"1.059";"1.059,45";"Torgau";""
+"62,800";"63,4";"Starr";"70,83";"78,18";"1.059";"1.059,45";"Torgau";""
+"62,900";"65,4";"Mobil";"70,62";"78,15";"1.059";"1.059,45";"Torgau";""
+"63,000";"64,6";"Mobil";"70,66";"78,12";"1.059";"1.059,45";"Torgau";""
+"63,100";"62,7";"Mobil";"70,83";"78,10";"1.059";"1.059,45";"Torgau";""
+"63,200";"63,5";"Mobil";"70,73";"78,08";"1.059";"1.059,45";"Torgau";""
+"63,300";"64,5";"Mobil";"70,62";"78,05";"1.059";"1.059,45";"Torgau";""
+"63,400";"65,2";"Mobil";"70,49";"78,02";"1.059";"1.059,45";"Torgau";""
+"63,500";"64,9";"Mobil";"70,47";"78,00";"1.059";"1.059,45";"Torgau";""
+"63,600";"65,2";"Mobil";"70,40";"77,98";"1.059";"1.059,45";"Torgau";"Fähre: Prettin -Gierseilfähre"
+"63,700";"67,8";"Mobil";"70,09";"77,96";"1.059";"1.059,45";"Torgau";""
+"63,800";"70,9";"Mobil";"69,85";"77,94";"1.059";"1.059,45";"Torgau";""
+"63,900";"68,6";"Mobil";"70,08";"77,91";"1.059";"1.059,45";"Torgau";""
+"64,000";"63,1";"Mobil";"70,59";"77,87";"1.059";"1.059,45";"Torgau";""
+"64,100";"62,6";"Mobil";"70,60";"77,85";"1.059";"1.059,45";"Torgau";"HW-Schutz: Axiener-Deich"
+"64,200";"64,6";"Mobil";"70,38";"77,82";"1.059";"1.059,45";"Torgau";""
+"64,300";"67,0";"Mobil";"70,12";"77,80";"1.059";"1.059,45";"Torgau";""
+"64,400";"67,3";"Mobil";"70,07";"77,78";"1.059";"1.059,45";"Torgau";""
+"64,500";"66,8";"Mobil";"70,09";"77,75";"1.059";"1.059,45";"Torgau";""
+"64,600";"65,2";"Mobil";"70,20";"77,71";"1.059";"1.059,45";"Torgau";""
+"64,700";"65,1";"Mobil";"70,17";"77,69";"1.059";"1.059,45";"Torgau";""
+"64,800";"63,7";"Mobil";"70,27";"77,67";"1.059";"1.059,45";"Torgau";""
+"64,900";"62,2";"Mobil";"70,37";"77,66";"1.059";"1.059,45";"Torgau";""
+"65,000";"62,4";"Mobil";"70,30";"77,65";"1.059";"1.059,45";"Torgau";""
+"65,100";"63,5";"Mobil";"70,10";"77,63";"1.059";"1.059,45";"Torgau";""
+"65,200";"64,8";"Mobil";"69,85";"77,61";"1.059";"1.059,45";"Torgau";""
+"65,300";"61,2";"Mobil";"70,10";"77,60";"1.059";"1.059,45";"Torgau";""
+"65,400";"62,6";"Mobil";"70,15";"77,59";"1.059";"1.059,45";"Torgau";""
+"65,500";"64,9";"Mobil";"69,99";"77,56";"1.059";"1.059,45";"Torgau";""
+"65,600";"64,6";"Mobil";"69,96";"77,52";"1.059";"1.059,45";"Torgau";""
+"65,700";"56,7";"Mobil";"70,14";"77,50";"1.059";"1.059,45";"Torgau";""
+"65,800";"51,2";"Mobil";"70,11";"77,47";"1.059";"1.059,45";"Torgau";""
+"65,900";"47,0";"Mobil";"69,92";"77,44";"1.059";"1.059,45";"Torgau";""
+"66,000";"42,5";"Mobil";"69,95";"77,41";"1.059";"1.059,45";"Torgau";""
+"66,100";"38,9";"Mobil";"69,92";"77,38";"1.059";"1.059,45";"Torgau";""
+"66,200";"34,8";"Mobil";"69,93";"77,35";"1.059";"1.059,45";"Torgau";""
+"66,300";"31,6";"Mobil";"69,83";"77,32";"1.059";"1.059,45";"Torgau";""
+"66,400";"24,1";"Starr";"69,83";"77,29";"1.059";"1.059,45";"Torgau";""
+"66,500";"15,6";"Starr";"69,78";"77,27";"1.059";"1.059,45";"Torgau";""
+"66,600";"10,6";"Starr";"69,89";"77,25";"1.059";"1.059,45";"Torgau";""
+"66,700";"16,1";"Starr";"69,93";"77,23";"1.059";"1.059,45";"Torgau";""
+"66,800";"21,8";"Starr";"69,93";"77,20";"1.059";"1.059,45";"Torgau";""
+"66,900";"27,8";"Mobil";"69,78";"77,17";"1.059";"1.059,45";"Torgau";""
+"67,000";"33,2";"Mobil";"69,69";"77,14";"1.059";"1.059,45";"Torgau";""
+"67,100";"38,0";"Mobil";"69,69";"77,11";"1.059";"1.059,45";"Torgau";""
+"67,200";"43,7";"Mobil";"69,57";"77,08";"1.059";"1.059,45";"Torgau";""
+"67,300";"47,8";"Mobil";"69,65";"77,05";"1.059";"1.059,45";"Torgau";""
+"67,400";"51,4";"Mobil";"69,65";"77,02";"1.059";"1.059,45";"Torgau";""
+"67,500";"56,7";"Mobil";"69,52";"77,01";"1.059";"1.059,45";"Torgau";""
+"67,600";"55,9";"Mobil";"69,45";"76,99";"1.059";"1.059,45";"Torgau";""
+"67,700";"53,9";"Mobil";"69,63";"76,97";"1.059";"1.059,45";"Torgau";""
+"67,800";"57,0";"Mobil";"69,32";"76,95";"1.059";"1.059,45";"Torgau";""
+"67,900";"60,6";"Mobil";"68,97";"76,93";"1.059";"1.059,45";"Torgau";""
+"68,000";"60,8";"Mobil";"69,00";"76,90";"1.059";"1.059,45";"Torgau";""
+"68,100";"60,3";"Mobil";"69,07";"76,86";"1.059";"1.059,45";"Torgau";""
+"68,200";"59,0";"Mobil";"69,20";"76,82";"1.059";"1.059,45";"Torgau";""
+"68,300";"57,4";"Mobil";"69,37";"76,79";"1.059";"1.059,45";"Torgau";""
+"68,400";"57,7";"Mobil";"69,26";"76,76";"1.059";"1.059,45";"Torgau";""
+"68,500";"56,1";"Mobil";"69,39";"76,75";"1.059";"1.059,45";"Torgau";""
+"68,600";"55,4";"Mobil";"69,45";"76,73";"1.059";"1.059,45";"Torgau";""
+"68,700";"56,0";"Mobil";"69,37";"76,72";"1.059";"1.059,45";"Torgau";""
+"68,800";"53,7";"Mobil";"69,49";"76,70";"1.059";"1.059,45";"Torgau";""
+"68,900";"53,9";"Mobil";"69,23";"76,68";"1.059";"1.059,45";"Torgau";""
+"69,000";"56,5";"Mobil";"69,05";"76,66";"1.059";"1.059,45";"Torgau";""
+"69,100";"59,2";"Mobil";"68,84";"76,64";"1.059";"1.059,45";"Torgau";""
+"69,200";"58,7";"Mobil";"68,90";"76,61";"1.059";"1.059,45";"Torgau";""
+"69,300";"58,4";"Mobil";"68,94";"76,59";"1.059";"1.059,45";"Torgau";""
+"69,400";"56,6";"Mobil";"69,09";"76,57";"1.059";"1.059,45";"Torgau";""
+"69,500";"58,1";"Mobil";"68,85";"76,56";"1.059";"1.059,45";"Torgau";""
+"69,600";"59,2";"Mobil";"68,82";"76,54";"1.059";"1.059,45";"Torgau";""
+"69,700";"60,4";"Mobil";"68,77";"76,52";"1.059";"1.059,45";"Torgau";""
+"69,800";"59,4";"Mobil";"68,74";"76,50";"1.059";"1.059,45";"Torgau";""
+"69,900";"56,3";"Mobil";"68,94";"76,49";"1.059";"1.059,45";"Torgau";""
+"70,000";"59,4";"Mobil";"68,84";"76,47";"1.059";"1.059,45";"Torgau";""
+"70,100";"59,9";"Mobil";"68,92";"76,43";"1.059";"1.059,45";"Torgau";""
+"70,200";"58,5";"Mobil";"69,00";"76,39";"1.059";"1.059,45";"Torgau";""
+"70,300";"59,5";"Mobil";"68,82";"76,38";"1.059";"1.059,45";"Torgau";""
+"70,400";"58,5";"Mobil";"68,96";"76,36";"1.059";"1.059,45";"Torgau";""
+"70,500";"59,3";"Mobil";"68,88";"76,34";"1.059";"1.059,45";"Torgau";""
+"70,600";"59,9";"Mobil";"68,80";"76,32";"1.059";"1.059,45";"Torgau";""
+"70,700";"60,3";"Mobil";"68,74";"76,31";"1.059";"1.059,45";"Torgau";""
+"70,800";"59,4";"Mobil";"68,80";"76,29";"1.059";"1.059,45";"Torgau";""
+"70,900";"58,6";"Mobil";"68,84";"76,27";"1.059";"1.059,45";"Torgau";""
+"71,000";"57,9";"Mobil";"68,97";"76,25";"1.059";"1.059,45";"Torgau";""
+"71,100";"58,8";"Mobil";"68,92";"76,23";"1.059";"1.059,45";"Torgau";""
+"71,200";"60,2";"Mobil";"68,73";"76,20";"1.059";"1.059,45";"Torgau";""
+"71,300";"57,3";"Mobil";"69,01";"76,18";"1.059";"1.059,45";"Torgau";""
+"71,400";"59,6";"Mobil";"68,78";"76,15";"1.059";"1.059,45";"Torgau";""
+"71,500";"61,1";"Mobil";"68,65";"76,14";"1.059";"1.059,45";"Torgau";""
+"71,600";"60,0";"Mobil";"68,80";"76,12";"1.059";"1.059,45";"Torgau";"Bundesland: Sachsen-Anhalt"
+"71,700";"61,2";"Mobil";"68,68";"76,10";"1.059";"1.059,45";"Torgau";""
+"71,800";"59,4";"Mobil";"68,80";"76,08";"1.059";"1.059,45";"Torgau";""
+"71,900";"60,2";"Mobil";"68,59";"76,06";"1.059";"1.059,45";"Torgau";""
+"72,000";"63,3";"Mobil";"68,30";"76,04";"1.059";"1.059,45";"Torgau";""
+"72,100";"62,9";"Mobil";"68,37";"76,01";"1.059";"1.059,45";"Torgau";""
+"72,200";"61,7";"Mobil";"68,52";"75,98";"1.059";"1.059,45";"Torgau";""
+"72,300";"60,9";"Mobil";"68,60";"75,95";"1.059";"1.059,45";"Torgau";""
+"72,400";"62,6";"Mobil";"68,35";"75,91";"1.059";"1.059,45";"Torgau";""
+"72,500";"58,2";"Mobil";"68,73";"75,89";"1.059";"1.059,45";"Torgau";"HW-Schutz: Maukener-Deich"
+"72,600";"61,8";"Mobil";"68,21";"75,87";"1.059";"1.059,45";"Torgau";""
+"72,700";"57,6";"Mobil";"68,54";"75,86";"1.059";"1.059,45";"Torgau";""
+"72,800";"57,3";"Mobil";"68,58";"75,85";"1.059";"1.059,45";"Torgau";""
+"72,900";"57,0";"Mobil";"68,64";"75,84";"1.059";"1.059,45";"Torgau";""
+"73,000";"57,4";"Mobil";"68,66";"75,82";"1.059";"1.059,45";"Torgau";""
+"73,100";"59,2";"Mobil";"68,51";"75,79";"1.059";"1.059,45";"Torgau";""
+"73,200";"61,7";"Mobil";"68,16";"75,76";"1.059";"1.059,45";"Torgau";""
+"73,300";"60,9";"Mobil";"68,17";"75,75";"1.059";"1.059,45";"Torgau";""
+"73,400";"60,9";"Mobil";"68,23";"75,73";"1.059";"1.059,45";"Torgau";""
+"73,500";"60,0";"Mobil";"68,35";"75,70";"1.059";"1.059,45";"Torgau";""
+"73,600";"60,4";"Mobil";"68,28";"75,67";"1.059";"1.059,45";"Torgau";""
+"73,700";"58,8";"Mobil";"68,44";"75,65";"1.059";"1.059,45";"Torgau";""
+"73,800";"60,6";"Mobil";"68,23";"75,63";"1.059";"1.059,45";"Torgau";""
+"73,900";"58,7";"Mobil";"68,43";"75,61";"1.059";"1.059,45";"Torgau";""
+"74,000";"59,9";"Mobil";"68,27";"75,58";"1.059";"1.059,45";"Torgau";""
+"74,100";"62,3";"Mobil";"68,00";"75,56";"1.059";"1.059,45";"Torgau";""
+"74,200";"61,3";"Mobil";"68,11";"75,53";"1.059";"1.059,45";"Torgau";""
+"74,300";"62,1";"Mobil";"68,02";"75,50";"1.059";"1.059,45";"Torgau";""
+"74,400";"63,7";"Mobil";"67,80";"75,46";"1.059";"1.059,45";"Torgau";""
+"74,500";"63,0";"Mobil";"67,83";"75,43";"1.059";"1.059,45";"Torgau";""
+"74,600";"60,6";"Mobil";"68,06";"75,40";"1.059";"1.059,45";"Torgau";""
+"74,700";"62,4";"Mobil";"67,85";"75,37";"1.059";"1.059,45";"Torgau";""
+"74,800";"62,4";"Mobil";"67,81";"75,34";"1.059";"1.059,45";"Torgau";""
+"74,900";"59,4";"Mobil";"68,07";"75,33";"1.059";"1.059,45";"Torgau";""
+"75,000";"60,2";"Mobil";"67,97";"75,32";"1.059";"1.059,45";"Torgau";""
+"75,100";"59,1";"Mobil";"68,05";"75,30";"1.059";"1.059,45";"Torgau";""
+"75,200";"56,8";"Mobil";"68,27";"75,27";"1.059";"1.059,45";"Torgau";""
+"75,300";"55,4";"Mobil";"68,41";"75,26";"1.059";"1.059,45";"Torgau";""
+"75,400";"57,3";"Mobil";"68,20";"75,24";"1.059";"1.059,45";"Torgau";""
+"75,500";"58,3";"Mobil";"68,06";"75,22";"1.059";"1.059,45";"Torgau";""
+"75,600";"61,2";"Mobil";"67,76";"75,19";"1.059";"1.059,45";"Torgau";""
+"75,700";"60,6";"Mobil";"67,81";"75,16";"1.059";"1.059,45";"Torgau";""
+"75,800";"59,7";"Mobil";"67,87";"75,12";"1.059";"1.059,45";"Torgau";""
+"75,900";"60,5";"Mobil";"67,76";"75,10";"1.059";"1.059,45";"Torgau";""
+"76,000";"59,7";"Mobil";"67,84";"75,08";"1.059";"1.059,45";"Torgau";""
+"76,100";"59,9";"Mobil";"67,80";"75,06";"1.059";"1.059,45";"Torgau";""
+"76,200";"58,9";"Mobil";"67,86";"75,03";"1.059";"1.059,45";"Torgau";""
+"76,300";"54,5";"Mobil";"68,27";"75,01";"1.059";"1.059,45";"Torgau";""
+"76,400";"54,2";"Mobil";"68,22";"74,99";"1.059";"1.059,45";"Torgau";"HW-Schutz: Kloedener-Deich"
+"76,500";"59,7";"Mobil";"67,46";"74,98";"1.059";"1.059,45";"Torgau";""
+"76,600";"62,3";"Mobil";"67,38";"74,96";"1.059";"1.059,45";"Torgau";"Geschiebemessstelle: Pretsch-Mauken"
+"76,700";"62,6";"Mobil";"67,43";"74,93";"1.059";"1.059,45";"Torgau";""
+"76,800";"61,4";"Mobil";"67,54";"74,90";"1.059";"1.059,45";"Torgau";""
+"76,900";"61,9";"Mobil";"67,46";"74,88";"1.059";"1.059,45";"Torgau";""
+"77,000";"63,0";"Mobil";"67,32";"74,85";"1.059";"1.059,45";"Torgau";""
+"77,100";"62,1";"Mobil";"67,40";"74,84";"1.059";"1.059,45";"Torgau";""
+"77,200";"56,8";"Mobil";"68,02";"74,82";"1.059";"1.059,45";"Torgau";""
+"77,300";"60,0";"Mobil";"67,71";"74,79";"1.059";"1.059,45";"Torgau";""
+"77,400";"57,3";"Mobil";"67,97";"74,76";"1.059";"1.059,45";"Torgau";""
+"77,500";"58,2";"Mobil";"67,86";"74,73";"1.059";"1.059,45";"Torgau";""
+"77,600";"59,5";"Mobil";"67,71";"74,69";"1.059";"1.059,45";"Torgau";""
+"77,700";"59,4";"Mobil";"67,72";"74,68";"1.059";"1.059,45";"Torgau";""
+"77,800";"60,5";"Mobil";"67,62";"74,66";"1.059";"1.059,45";"Torgau";""
+"77,900";"60,6";"Mobil";"67,61";"74,65";"1.059";"1.059,45";"Torgau";""
+"78,000";"60,3";"Mobil";"67,64";"74,63";"1.059";"1.059,45";"Torgau";""
+"78,100";"57,7";"Mobil";"67,90";"74,62";"1.059";"1.059,45";"Torgau";""
+"78,200";"59,6";"Mobil";"67,74";"74,60";"1.059";"1.059,45";"Torgau";""
+"78,300";"59,1";"Mobil";"67,79";"74,58";"1.059";"1.059,45";"Torgau";""
+"78,400";"59,1";"Mobil";"67,79";"74,55";"1.059";"1.059,45";"Torgau";""
+"78,500";"61,5";"Mobil";"67,55";"74,52";"1.059";"1.059,45";"Torgau";""
+"78,600";"61,4";"Mobil";"67,54";"74,49";"1.059";"1.059,45";"Torgau";""
+"78,700";"59,9";"Mobil";"67,67";"74,47";"1.059";"1.059,45";"Torgau";""
+"78,800";"59,0";"Mobil";"67,76";"74,44";"1.059";"1.059,45";"Torgau";""
+"78,900";"62,8";"Mobil";"67,42";"74,42";"1.059";"1.059,45";"Torgau";""
+"79,000";"62,1";"Mobil";"67,46";"74,39";"1.059";"1.059,45";"Torgau";""
+"79,100";"63,9";"Mobil";"67,26";"74,37";"1.059";"1.059,45";"Torgau";""
+"79,200";"60,8";"Mobil";"67,56";"74,34";"1.059";"1.059,45";"Torgau";""
+"79,300";"60,4";"Mobil";"67,61";"74,31";"1.059";"1.059,45";"Torgau";""
+"79,400";"61,7";"Mobil";"67,50";"74,28";"1.059";"1.059,45";"Torgau";""
+"79,500";"60,9";"Mobil";"67,58";"74,27";"1.059";"1.059,45";"Torgau";""
+"79,600";"61,1";"Mobil";"67,59";"74,25";"1.059";"1.059,45";"Torgau";""
+"79,700";"62,5";"Mobil";"67,45";"74,24";"1.059";"1.059,45";"Torgau";""
+"79,800";"61,7";"Mobil";"67,54";"74,22";"1.059";"1.059,45";"Torgau";""
+"79,900";"63,6";"Mobil";"67,29";"74,19";"1.059";"1.059,45";"Torgau";""
+"80,000";"63,7";"Mobil";"67,30";"74,16";"1.059";"1.059,45";"Torgau";""
+"80,100";"63,9";"Mobil";"67,30";"74,14";"1.059";"1.059,45";"Torgau";""
+"80,200";"62,7";"Mobil";"67,39";"74,11";"1.059";"1.059,45";"Torgau";""
+"80,300";"64,0";"Mobil";"67,24";"74,09";"1.059";"1.059,45";"Torgau";""
+"80,400";"64,5";"Mobil";"67,18";"74,06";"1.059";"1.059,45";"Torgau";""
+"80,500";"64,1";"Mobil";"67,20";"74,04";"1.059";"1.059,45";"Torgau";""
+"80,600";"60,4";"Mobil";"67,43";"74,01";"1.059";"1.059,45";"Torgau";""
+"80,700";"59,9";"Mobil";"67,33";"73,98";"1.059";"1.059,45";"Torgau";""
+"80,800";"61,5";"Mobil";"67,19";"73,94";"1.059";"1.059,45";"Torgau";""
+"80,900";"61,7";"Mobil";"67,17";"73,91";"1.059";"1.059,45";"Torgau";""
+"81,000";"61,5";"Mobil";"67,11";"73,87";"1.055";"1.059,45";"Torgau";""
+"81,100";"60,1";"Mobil";"67,15";"73,84";"1.055";"1.059,45";"Torgau";""
+"81,200";"59,4";"Mobil";"67,18";"73,80";"1.055";"1.059,45";"Torgau";""
+"81,300";"58,9";"Mobil";"67,18";"73,77";"1.055";"1.059,45";"Torgau";""
+"81,400";"60,1";"Mobil";"67,05";"73,73";"1.055";"1.059,45";"Torgau";""
+"81,500";"59,0";"Mobil";"67,12";"73,70";"1.055";"1.059,45";"Torgau";""
+"81,600";"59,6";"Mobil";"67,04";"73,66";"1.055";"1.059,45";"Torgau";""
+"81,700";"59,3";"Mobil";"67,04";"73,63";"1.055";"1.059,45";"Torgau";""
+"81,800";"59,6";"Mobil";"67,12";"73,59";"1.055";"1.059,45";"Torgau";""
+"81,900";"59,1";"Mobil";"67,27";"73,57";"1.055";"1.059,45";"Torgau";""
+"82,000";"64,4";"Mobil";"66,79";"73,54";"1.055";"1.059,45";"Torgau";""
+"82,100";"64,7";"Mobil";"66,74";"73,51";"1.055";"1.059,45";"Torgau";""
+"82,200";"65,2";"Mobil";"66,65";"73,48";"1.055";"1.059,45";"Torgau";""
+"82,300";"66,9";"Mobil";"66,45";"73,45";"1.055";"1.059,45";"Torgau";""
+"82,400";"66,0";"Mobil";"66,59";"73,41";"1.055";"1.059,45";"Torgau";""
+"82,500";"66,9";"Mobil";"66,58";"73,40";"1.055";"1.059,45";"Torgau";""
+"82,600";"67,4";"Mobil";"66,56";"73,38";"1.055";"1.059,45";"Torgau";""
+"82,700";"68,8";"Mobil";"66,45";"73,36";"1.055";"1.059,45";"Torgau";""
+"82,800";"66,8";"Mobil";"66,50";"73,33";"1.055";"1.059,45";"Torgau";""
+"82,900";"65,3";"Mobil";"66,50";"73,30";"1.055";"1.059,45";"Torgau";""
+"83,000";"67,1";"Mobil";"66,32";"73,27";"1.055";"1.059,45";"Torgau";""
+"83,100";"66,0";"Mobil";"66,40";"73,25";"1.055";"1.059,45";"Torgau";""
+"83,200";"67,2";"Mobil";"66,36";"73,22";"1.055";"1.059,45";"Torgau";""
+"83,300";"66,0";"Mobil";"66,52";"73,21";"1.055";"1.059,45";"Torgau";""
+"83,400";"66,8";"Mobil";"66,37";"73,19";"1.055";"1.059,45";"Torgau";""
+"83,500";"66,8";"Mobil";"66,25";"73,16";"1.055";"1.059,45";"Torgau";""
+"83,600";"63,8";"Mobil";"66,48";"73,12";"1.055";"1.059,45";"Torgau";""
+"83,700";"63,3";"Mobil";"66,48";"73,09";"1.055";"1.059,45";"Torgau";""
+"83,800";"62,6";"Mobil";"66,53";"73,06";"1.055";"1.059,45";"Torgau";""
+"83,900";"61,4";"Mobil";"66,64";"73,04";"1.055";"1.059,45";"Torgau";""
+"84,000";"63,3";"Mobil";"66,47";"73,02";"1.055";"1.059,45";"Torgau";""
+"84,100";"64,7";"Mobil";"66,33";"73,00";"1.055";"1.059,45";"Torgau";""
+"84,200";"64,5";"Mobil";"66,28";"72,97";"1.055";"1.059,45";"Torgau";""
+"84,300";"65,6";"Mobil";"66,11";"72,95";"1.055";"1.059,45";"Torgau";""
+"84,400";"66,7";"Mobil";"66,04";"72,92";"1.055";"1.059,45";"Torgau";""
+"84,500";"68,3";"Mobil";"65,91";"72,90";"1.055";"1.059,45";"Torgau";""
+"84,600";"69,0";"Mobil";"65,83";"72,88";"1.055";"1.059,45";"Torgau";"HW-Schutz: Schuetzberger-Deich"
+"84,700";"65,7";"Mobil";"66,10";"72,86";"1.055";"1.059,45";"Torgau";""
+"84,800";"65,7";"Mobil";"66,07";"72,84";"1.055";"1.059,45";"Torgau";""
+"84,900";"64,8";"Mobil";"66,12";"72,82";"1.055";"1.059,45";"Torgau";""
+"85,000";"65,4";"Mobil";"66,05";"72,80";"1.055";"1.059,45";"Torgau";""
+"85,100";"66,0";"Mobil";"65,99";"72,79";"1.055";"1.059,45";"Torgau";""
+"85,200";"67,3";"Mobil";"65,85";"72,77";"1.055";"1.059,45";"Torgau";""
+"85,300";"66,2";"Mobil";"65,93";"72,75";"1.055";"1.059,45";"Torgau";""
+"85,400";"64,8";"Mobil";"66,02";"72,73";"1.055";"1.059,45";"Torgau";""
+"85,500";"64,2";"Mobil";"66,03";"72,71";"1.055";"1.059,45";"Torgau";""
+"85,600";"62,6";"Mobil";"66,12";"72,68";"1.050";"1.059,45";"Torgau";""
+"85,700";"60,4";"Mobil";"66,26";"72,66";"1.050";"1.059,45";"Torgau";""
+"85,800";"59,1";"Mobil";"66,33";"72,63";"1.050";"1.059,45";"Torgau";""
+"85,900";"62,6";"Mobil";"65,98";"72,61";"1.050";"1.059,45";"Torgau";""
+"86,000";"60,3";"Mobil";"66,17";"72,58";"1.050";"1.059,45";"Torgau";""
+"86,100";"60,5";"Mobil";"66,15";"72,56";"1.050";"1.059,45";"Torgau";""
+"86,200";"60,3";"Mobil";"66,15";"72,53";"1.050";"1.059,45";"Torgau";""
+"86,300";"62,4";"Mobil";"65,95";"72,51";"1.050";"1.059,45";"Torgau";""
+"86,400";"61,8";"Mobil";"66,00";"72,49";"1.050";"1.059,45";"Torgau";""
+"86,500";"61,5";"Mobil";"66,00";"72,48";"1.050";"1.059,45";"Torgau";""
+"86,600";"62,0";"Mobil";"65,94";"72,46";"1.050";"1.059,45";"Torgau";""
+"86,700";"62,3";"Mobil";"65,88";"72,45";"1.050";"1.059,45";"Torgau";""
+"86,800";"62,7";"Mobil";"65,81";"72,43";"1.050";"1.059,45";"Torgau";""
+"86,900";"62,7";"Mobil";"65,77";"72,42";"1.050";"1.059,45";"Torgau";""
+"87,000";"62,5";"Mobil";"65,77";"72,40";"1.050";"1.059,45";"Torgau";""
+"87,100";"61,7";"Mobil";"65,82";"72,39";"1.050";"1.059,45";"Torgau";""
+"87,200";"63,9";"Mobil";"65,61";"72,37";"1.050";"1.059,45";"Torgau";""
+"87,300";"64,3";"Mobil";"65,53";"72,35";"1.050";"1.059,45";"Torgau";""
+"87,400";"64,4";"Mobil";"65,50";"72,32";"1.050";"1.059,45";"Torgau";""
+"87,500";"64,7";"Mobil";"65,43";"72,32";"1.050";"1.059,45";"Torgau";""
+"87,600";"63,5";"Mobil";"65,53";"72,31";"1.050";"1.059,45";"Torgau";""
+"87,700";"62,6";"Mobil";"65,59";"72,30";"1.050";"1.059,45";"Torgau";""
+"87,800";"62,2";"Mobil";"65,59";"72,28";"1.050";"1.059,45";"Torgau";""
+"87,900";"63,2";"Mobil";"65,47";"72,27";"1.050";"1.059,45";"Torgau";""
+"88,000";"62,5";"Mobil";"65,53";"72,25";"1.050";"1.059,45";"Torgau";""
+"88,100";"62,4";"Mobil";"65,53";"72,24";"1.050";"1.059,45";"Torgau";""
+"88,200";"62,8";"Mobil";"65,43";"72,22";"1.050";"1.059,45";"Torgau";""
+"88,300";"62,8";"Mobil";"65,36";"72,21";"1.050";"1.059,45";"Torgau";""
+"88,400";"60,7";"Mobil";"65,50";"72,20";"1.050";"1.059,45";"Torgau";""
+"88,500";"60,4";"Mobil";"65,45";"72,19";"1.050";"1.059,45";"Torgau";""
+"88,600";"62,5";"Mobil";"65,36";"72,17";"1.050";"1.059,45";"Torgau";""
+"88,700";"62,3";"Mobil";"65,41";"72,15";"1.050";"1.059,45";"Torgau";""
+"88,800";"63,3";"Mobil";"65,28";"72,12";"1.050";"1.059,45";"Torgau";""
+"88,900";"63,3";"Mobil";"65,26";"72,11";"1.050";"1.059,45";"Torgau";""
+"89,000";"61,7";"Mobil";"65,36";"72,09";"1.050";"1.059,45";"Torgau";""
+"89,100";"61,0";"Mobil";"65,32";"72,08";"1.050";"1.059,45";"Torgau";""
+"89,200";"61,4";"Mobil";"65,28";"72,06";"1.050";"1.059,45";"Torgau";""
+"89,300";"62,1";"Mobil";"65,20";"72,05";"1.050";"1.059,45";"Torgau";""
+"89,400";"63,1";"Mobil";"65,05";"72,03";"1.050";"1.059,45";"Torgau";""
+"89,500";"61,9";"Mobil";"65,12";"72,02";"1.050";"1.059,45";"Torgau";""
+"89,600";"63,9";"Mobil";"65,02";"72,01";"1.050";"1.059,45";"Torgau";""
+"89,700";"63,8";"Mobil";"65,05";"71,98";"1.050";"1.059,45";"Torgau";""
+"89,800";"64,6";"Mobil";"64,95";"71,95";"1.050";"1.059,45";"Torgau";""
+"89,900";"63,2";"Mobil";"65,05";"71,92";"1.050";"1.059,45";"Torgau";""
+"90,000";"63,6";"Mobil";"64,98";"71,89";"1.050";"1.059,45";"Torgau";""
+"90,100";"66,4";"Mobil";"64,95";"71,85";"1.050";"1.059,45";"Torgau";""
+"90,200";"69,4";"Mobil";"64,94";"71,81";"1.050";"1.059,45";"Torgau";"Zufluss: Schwarze Elster"
+"90,300";"71,0";"Mobil";"64,79";"71,80";"1.050";"1.059,45";"außerh. d. Bez.pegels";""
+"90,400";"69,9";"Mobil";"64,79";"71,78";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"90,500";"68,3";"Mobil";"64,85";"71,76";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"90,600";"68,4";"Mobil";"64,74";"71,73";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"90,700";"66,9";"Mobil";"64,78";"71,71";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"90,800";"66,6";"Mobil";"64,69";"71,68";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"90,900";"64,6";"Mobil";"64,76";"71,64";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,000";"63,9";"Mobil";"64,71";"71,60";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,100";"63,5";"Mobil";"64,67";"71,58";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,200";"60,1";"Mobil";"64,92";"71,55";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,300";"60,5";"Mobil";"64,80";"71,54";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,400";"60,7";"Mobil";"64,69";"71,52";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,500";"57,6";"Starr";"64,88";"71,49";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,600";"55,6";"Starr";"64,99";"71,45";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,700";"54,4";"Starr";"65,02";"71,44";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,800";"53,3";"Starr";"65,06";"71,42";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"91,900";"53,3";"Starr";"64,97";"71,39";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,000";"53,0";"Starr";"64,90";"71,36";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,100";"52,5";"Starr";"64,86";"71,34";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,200";"52,2";"Starr";"64,81";"71,32";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,300";"50,9";"Mobil";"64,84";"71,30";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,400";"51,0";"Mobil";"64,73";"71,27";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,500";"50,9";"Mobil";"64,64";"71,25";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,600";"51,3";"Mobil";"64,48";"71,23";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,700";"50,7";"Mobil";"64,46";"71,22";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,800";"49,4";"Mobil";"64,53";"71,20";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"92,900";"48,8";"Mobil";"64,54";"71,18";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,000";"47,4";"Mobil";"64,56";"71,16";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,100";"47,3";"Mobil";"64,42";"71,14";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,200";"46,0";"Mobil";"64,51";"71,11";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,300";"45,5";"Mobil";"64,51";"71,09";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,400";"41,9";"Mobil";"64,79";"71,06";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,500";"41,9";"Mobil";"64,62";"71,05";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,600";"39,8";"Mobil";"64,71";"71,03";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,700";"37,8";"Mobil";"64,80";"71,01";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,800";"38,5";"Mobil";"64,69";"70,99";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"93,900";"37,7";"Mobil";"64,77";"70,97";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,000";"38,8";"Mobil";"64,55";"70,95";"1.119";"1.059,45";"außerh. d. Bez.pegels";"Zufluss: Zugbach"
+"94,100";"38,6";"Mobil";"64,52";"70,93";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,200";"38,1";"Mobil";"64,51";"70,91";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,300";"37,9";"Mobil";"64,46";"70,89";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,400";"36,6";"Mobil";"64,55";"70,86";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,500";"35,8";"Mobil";"64,56";"70,84";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,600";"34,0";"Mobil";"64,60";"70,82";"1.119";"1.059,45";"außerh. d. Bez.pegels";"HW-Schutz: Galliner-Deich"
+"94,700";"32,8";"Mobil";"64,64";"70,81";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,800";"33,2";"Mobil";"64,59";"70,79";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"94,900";"34,0";"Mobil";"64,45";"70,77";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,000";"33,0";"Mobil";"64,47";"70,74";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,100";"33,2";"Mobil";"64,26";"70,73";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,200";"32,4";"Mobil";"64,35";"70,71";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,300";"32,0";"Mobil";"64,36";"70,69";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,400";"27,8";"Mobil";"64,51";"70,67";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,500";"23,6";"Mobil";"64,50";"70,66";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,600";"22,3";"Mobil";"64,48";"70,65";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,700";"21,2";"Mobil";"64,39";"70,64";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,800";"31,3";"Mobil";"64,22";"70,63";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"95,900";"36,6";"Mobil";"64,21";"70,59";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,000";"42,2";"Mobil";"64,01";"70,55";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,100";"44,8";"Mobil";"63,91";"70,49";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,200";"44,9";"Mobil";"63,81";"70,43";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,300";"43,2";"Mobil";"63,95";"70,41";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,400";"42,4";"Mobil";"64,09";"70,38";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,500";"42,9";"Mobil";"64,06";"70,35";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,600";"43,7";"Mobil";"63,87";"70,32";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,700";"42,3";"Mobil";"63,92";"70,31";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,800";"37,7";"Mobil";"63,90";"70,29";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"96,900";"26,3";"Mobil";"63,92";"70,30";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,000";"39,5";"Mobil";"64,12";"70,31";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,100";"42,6";"Mobil";"64,17";"70,25";"1.119";"1.059,45";"außerh. d. Bez.pegels";"Zufluss: Alte Elbe"
+"97,200";"42,8";"Mobil";"64,02";"70,18";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,300";"44,7";"Mobil";"63,66";"70,17";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,400";"45,5";"Mobil";"63,55";"70,15";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,500";"46,1";"Mobil";"63,47";"70,13";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,600";"44,4";"Mobil";"63,45";"70,10";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,700";"40,9";"Mobil";"63,56";"70,10";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,800";"44,1";"Mobil";"63,48";"70,09";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"97,900";"46,5";"Mobil";"63,39";"70,06";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,000";"46,1";"Mobil";"63,40";"70,03";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,100";"44,5";"Mobil";"63,57";"70,01";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,200";"44,9";"Mobil";"63,54";"69,99";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,300";"43,8";"Mobil";"63,70";"69,97";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,400";"41,4";"Mobil";"63,86";"69,95";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,500";"40,2";"Mobil";"63,83";"69,94";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,600";"41,2";"Mobil";"63,90";"69,92";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,700";"44,3";"Mobil";"63,64";"69,90";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,800";"47,2";"Mobil";"63,43";"69,87";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"98,900";"49,8";"Mobil";"63,21";"69,84";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,000";"52,5";"Mobil";"62,85";"69,81";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,100";"51,1";"Mobil";"62,95";"69,79";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,200";"51,8";"Mobil";"62,94";"69,76";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,300";"51,6";"Mobil";"63,03";"69,74";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,400";"49,1";"Mobil";"63,25";"69,72";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,500";"48,1";"Mobil";"63,32";"69,71";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,600";"46,0";"Mobil";"63,45";"69,69";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,700";"44,5";"Mobil";"63,46";"69,68";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,800";"45,9";"Mobil";"63,40";"69,66";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"99,900";"47,1";"Mobil";"63,35";"69,64";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,000";"48,6";"Mobil";"63,40";"69,62";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,100";"49,9";"Mobil";"63,32";"69,58";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,200";"50,1";"Mobil";"63,26";"69,54";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,300";"52,4";"Mobil";"62,98";"69,52";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,400";"51,6";"Mobil";"62,93";"69,50";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,500";"50,7";"Mobil";"62,79";"69,49";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,600";"48,1";"Mobil";"62,81";"69,48";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,700";"43,7";"Mobil";"62,89";"69,48";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,800";"46,5";"Mobil";"62,84";"69,47";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"100,900";"48,7";"Mobil";"62,81";"69,45";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,000";"49,6";"Mobil";"62,94";"69,43";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,100";"51,9";"Mobil";"62,82";"69,41";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,200";"53,4";"Mobil";"62,73";"69,39";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,300";"53,4";"Mobil";"62,77";"69,37";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,400";"53,3";"Mobil";"62,77";"69,34";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,500";"53,0";"Mobil";"62,80";"69,32";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,600";"51,2";"Mobil";"63,01";"69,30";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,700";"49,9";"Mobil";"63,16";"69,28";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,800";"49,6";"Mobil";"63,05";"69,26";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"101,900";"47,1";"Mobil";"63,10";"69,25";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,000";"45,8";"Mobil";"63,11";"69,23";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,100";"44,7";"Mobil";"63,08";"69,22";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,200";"45,9";"Mobil";"62,90";"69,20";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,300";"47,1";"Mobil";"62,75";"69,19";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,400";"51,9";"Mobil";"62,67";"69,18";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,500";"54,3";"Mobil";"62,63";"69,16";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,600";"52,8";"Mobil";"62,71";"69,13";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,700";"51,3";"Mobil";"62,78";"69,12";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,800";"51,8";"Mobil";"62,75";"69,10";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"102,900";"52,6";"Mobil";"62,68";"69,08";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,000";"50,8";"Mobil";"62,85";"69,06";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,100";"51,0";"Mobil";"62,80";"69,05";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,200";"51,0";"Mobil";"62,83";"69,03";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,300";"51,0";"Mobil";"62,84";"69,01";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,400";"51,1";"Mobil";"62,92";"68,99";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,500";"51,4";"Mobil";"62,94";"68,97";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,600";"55,0";"Mobil";"62,62";"68,95";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,700";"58,5";"Mobil";"62,28";"68,92";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,800";"56,6";"Mobil";"62,44";"68,88";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"103,900";"55,6";"Mobil";"62,53";"68,86";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,000";"56,2";"Mobil";"62,44";"68,83";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,100";"58,4";"Mobil";"62,21";"68,82";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,200";"56,5";"Mobil";"62,41";"68,80";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,300";"55,1";"Mobil";"62,53";"68,78";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,400";"54,5";"Mobil";"62,59";"68,75";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,500";"54,5";"Mobil";"62,59";"68,73";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,600";"55,9";"Mobil";"62,43";"68,70";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,700";"54,6";"Mobil";"62,54";"68,69";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,800";"55,6";"Mobil";"62,46";"68,67";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"104,900";"56,4";"Mobil";"62,37";"68,64";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,000";"58,2";"Mobil";"62,19";"68,61";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,100";"60,1";"Mobil";"61,98";"68,59";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,200";"61,7";"Mobil";"61,82";"68,57";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,300";"62,1";"Mobil";"61,77";"68,55";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,400";"60,8";"Mobil";"61,90";"68,53";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,500";"61,8";"Mobil";"61,80";"68,51";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,600";"63,9";"Mobil";"61,59";"68,48";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,700";"60,9";"Mobil";"61,77";"68,44";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,800";"62,2";"Mobil";"61,61";"68,39";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"105,900";"61,4";"Mobil";"61,66";"68,37";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,000";"61,7";"Mobil";"61,66";"68,34";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,100";"60,3";"Mobil";"61,83";"68,32";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,200";"59,1";"Mobil";"61,95";"68,30";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,300";"57,8";"Mobil";"62,08";"68,28";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,400";"58,1";"Mobil";"62,05";"68,26";"1.119";"1.059,45";"außerh. d. Bez.pegels";"Schwebstoffmessstelle: Wittenberg"
+"106,500";"59,0";"Mobil";"61,94";"68,24";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,600";"60,1";"Mobil";"61,80";"68,22";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,700";"60,4";"Mobil";"61,74";"68,20";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,800";"60,4";"Mobil";"61,70";"68,17";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"106,900";"58,3";"Mobil";"61,85";"68,15";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,000";"57,4";"Mobil";"61,91";"68,12";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,100";"59,4";"Mobil";"61,70";"68,10";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,200";"59,4";"Mobil";"61,65";"68,08";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,300";"57,8";"Starr";"61,76";"68,06";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,400";"57,7";"Starr";"61,75";"68,04";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,500";"57,9";"Starr";"61,70";"68,02";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,600";"57,9";"Starr";"61,64";"67,99";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,700";"56,4";"Starr";"61,72";"67,97";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,800";"58,4";"Starr";"61,52";"67,94";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"107,900";"57,3";"Starr";"61,61";"67,92";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,000";"55,5";"Starr";"61,76";"67,90";"1.119";"1.059,45";"außerh. d. Bez.pegels";"Hafen: Wittenberg -Schutz- und Sicherheitshafen"
+"108,100";"54,0";"Starr";"61,87";"67,88";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,200";"55,8";"Starr";"61,67";"67,85";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,300";"56,0";"Starr";"61,62";"67,83";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,400";"54,2";"Mobil";"61,78";"67,81";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,500";"53,5";"Mobil";"61,82";"67,79";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,600";"53,8";"Mobil";"61,76";"67,77";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,700";"52,2";"Mobil";"61,88";"67,75";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,800";"51,3";"Mobil";"61,93";"67,72";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"108,900";"49,6";"Mobil";"62,06";"67,70";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,000";"48,8";"Mobil";"62,11";"67,67";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,100";"51,4";"Mobil";"61,82";"67,65";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,200";"52,2";"Mobil";"61,70";"67,62";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,300";"51,0";"Mobil";"61,76";"67,59";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,400";"48,8";"Mobil";"61,91";"67,56";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,500";"51,7";"Mobil";"61,56";"67,53";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,600";"56,0";"Mobil";"61,20";"67,49";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,700";"56,4";"Mobil";"61,17";"67,47";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,800";"58,6";"Mobil";"60,92";"67,45";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"109,900";"59,2";"Mobil";"60,82";"67,44";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"110,000";"59,3";"Mobil";"60,86";"67,42";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"110,100";"60,0";"Mobil";"60,78";"67,39";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"110,200";"57,9";"Mobil";"60,95";"67,35";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"110,300";"58,3";"Mobil";"60,87";"67,34";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"110,400";"59,2";"Mobil";"60,77";"67,32";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"110,500";"60,2";"Mobil";"60,65";"67,30";"1.119";"1.059,45";"außerh. d. Bez.pegels";""
+"110,600";"59,6";"Mobil";"60,68";"67,28";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"110,700";"57,8";"Mobil";"60,83";"67,27";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"110,800";"55,5";"Mobil";"61,07";"67,25";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"110,900";"54,1";"Mobil";"61,21";"67,23";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,000";"52,6";"Mobil";"61,34";"67,21";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,100";"52,5";"Mobil";"61,34";"67,19";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,200";"58,6";"Mobil";"60,72";"67,17";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,300";"62,1";"Mobil";"60,37";"67,16";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,400";"61,0";"Mobil";"60,50";"67,14";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,500";"58,4";"Mobil";"60,74";"67,12";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,600";"59,3";"Mobil";"60,64";"67,09";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,700";"59,1";"Mobil";"60,65";"67,08";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,800";"59,5";"Mobil";"60,59";"67,06";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"111,900";"58,8";"Mobil";"60,64";"67,05";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,000";"57,3";"Mobil";"60,79";"67,03";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,100";"56,8";"Mobil";"60,83";"67,01";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,200";"55,3";"Mobil";"60,95";"66,99";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,300";"55,5";"Mobil";"60,91";"66,98";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,400";"54,1";"Mobil";"61,06";"66,96";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,500";"53,3";"Mobil";"61,15";"66,94";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,600";"52,7";"Mobil";"61,20";"66,92";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,700";"52,4";"Mobil";"61,21";"66,90";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,800";"51,9";"Mobil";"61,26";"66,88";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"112,900";"54,2";"Mobil";"61,03";"66,86";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,000";"53,7";"Mobil";"61,06";"66,84";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,100";"53,1";"Mobil";"61,11";"66,82";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,200";"52,7";"Mobil";"61,11";"66,80";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,300";"52,8";"Mobil";"61,07";"66,79";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,400";"51,5";"Mobil";"61,18";"66,78";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,500";"51,6";"Mobil";"61,15";"66,77";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,600";"54,2";"Mobil";"60,82";"66,75";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,700";"55,3";"Mobil";"60,59";"66,74";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,800";"58,3";"Mobil";"60,35";"66,73";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"113,900";"61,4";"Mobil";"60,08";"66,72";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,000";"62,3";"Mobil";"60,01";"66,70";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,100";"61,3";"Mobil";"60,11";"66,69";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,200";"58,7";"Mobil";"60,24";"66,68";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,300";"54,3";"Mobil";"60,44";"66,67";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,400";"54,8";"Mobil";"60,44";"66,66";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,500";"55,3";"Mobil";"60,42";"66,65";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,600";"50,3";"Mobil";"60,50";"66,64";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,700";"40,5";"Mobil";"60,59";"66,64";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,800";"52,3";"Mobil";"60,32";"66,64";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"114,900";"56,2";"Mobil";"60,32";"66,63";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,000";"56,6";"Mobil";"60,28";"66,61";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,100";"56,9";"Mobil";"60,26";"66,61";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,200";"58,7";"Mobil";"60,13";"66,60";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,300";"62,1";"Mobil";"59,81";"66,59";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,400";"63,0";"Mobil";"59,79";"66,57";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,500";"61,4";"Mobil";"59,99";"66,56";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,600";"59,2";"Mobil";"60,21";"66,55";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,700";"57,9";"Mobil";"60,34";"66,54";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,800";"60,1";"Mobil";"60,11";"66,53";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"115,900";"63,1";"Mobil";"59,78";"66,52";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,000";"61,5";"Mobil";"59,92";"66,51";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,100";"57,7";"Mobil";"60,28";"66,51";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,200";"54,4";"Mobil";"60,54";"66,50";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,300";"52,5";"Mobil";"60,62";"66,50";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,400";"55,4";"Mobil";"60,41";"66,49";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,500";"59,1";"Mobil";"60,11";"66,48";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,600";"57,5";"Mobil";"60,29";"66,47";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,700";"57,8";"Mobil";"60,28";"66,46";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,800";"56,7";"Mobil";"60,36";"66,44";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"116,900";"56,8";"Mobil";"60,33";"66,43";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,000";"57,7";"Mobil";"60,29";"66,42";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,100";"57,5";"Mobil";"60,27";"66,40";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,200";"60,6";"Mobil";"59,98";"66,38";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,300";"59,5";"Mobil";"60,06";"66,35";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,400";"60,6";"Mobil";"59,92";"66,31";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,500";"63,9";"Mobil";"59,60";"66,30";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,600";"69,4";"Mobil";"59,08";"66,29";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,700";"70,3";"Mobil";"58,95";"66,27";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,800";"72,4";"Mobil";"58,76";"66,24";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"117,900";"69,9";"Mobil";"58,98";"66,22";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,000";"68,7";"Mobil";"59,06";"66,20";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,100";"70,3";"Mobil";"58,89";"66,18";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,200";"68,9";"Mobil";"58,99";"66,15";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,300";"64,8";"Mobil";"59,34";"66,13";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,400";"63,3";"Mobil";"59,44";"66,11";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,500";"63,4";"Mobil";"59,38";"66,08";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,600";"64,3";"Mobil";"59,28";"66,05";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,700";"63,2";"Mobil";"59,38";"66,04";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,800";"62,4";"Mobil";"59,44";"66,03";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"118,900";"61,9";"Mobil";"59,45";"66,01";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,000";"62,0";"Mobil";"59,41";"65,98";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,100";"60,9";"Mobil";"59,47";"65,95";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,200";"60,9";"Mobil";"59,43";"65,92";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,300";"61,8";"Mobil";"59,33";"65,90";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,400";"60,5";"Mobil";"59,44";"65,87";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,500";"60,0";"Mobil";"59,49";"65,85";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,600";"62,7";"Mobil";"59,25";"65,83";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,700";"63,4";"Mobil";"59,15";"65,83";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,800";"64,6";"Mobil";"58,99";"65,82";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"119,900";"65,6";"Mobil";"58,84";"65,81";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,000";"67,7";"Mobil";"58,56";"65,79";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,100";"65,7";"Mobil";"58,66";"65,78";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,200";"66,1";"Mobil";"58,59";"65,77";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,300";"62,5";"Mobil";"58,92";"65,75";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,400";"64,9";"Mobil";"58,60";"65,73";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,500";"60,8";"Mobil";"58,93";"65,71";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,600";"59,4";"Mobil";"59,02";"65,68";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,700";"58,3";"Mobil";"59,09";"65,66";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,800";"61,1";"Mobil";"58,76";"65,64";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"120,900";"62,9";"Mobil";"58,51";"65,61";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,000";"60,8";"Mobil";"58,69";"65,57";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,100";"57,1";"Mobil";"59,01";"65,54";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,200";"56,3";"Mobil";"59,01";"65,50";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,300";"55,4";"Mobil";"59,03";"65,49";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,400";"54,5";"Mobil";"59,07";"65,48";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,500";"54,5";"Mobil";"59,00";"65,46";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,600";"56,0";"Mobil";"58,82";"65,44";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,700";"58,2";"Mobil";"58,55";"65,41";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,800";"56,5";"Mobil";"58,67";"65,38";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"121,900";"53,4";"Mobil";"58,94";"65,36";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,000";"51,2";"Mobil";"59,13";"65,33";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,100";"49,9";"Mobil";"59,22";"65,31";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,200";"50,1";"Mobil";"59,15";"65,28";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,300";"53,4";"Mobil";"58,77";"65,25";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,400";"53,1";"Mobil";"58,70";"65,22";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,500";"50,0";"Mobil";"58,93";"65,21";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,600";"50,4";"Mobil";"58,80";"65,20";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,700";"49,8";"Mobil";"58,74";"65,19";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,800";"47,5";"Mobil";"58,94";"65,17";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"122,900";"49,2";"Mobil";"58,67";"65,15";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,000";"49,3";"Mobil";"58,69";"65,13";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,100";"49,2";"Mobil";"58,71";"65,11";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,200";"47,7";"Mobil";"58,84";"65,08";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,300";"48,4";"Mobil";"58,71";"65,05";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,400";"48,7";"Mobil";"58,61";"65,02";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,500";"49,4";"Mobil";"58,46";"65,00";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,600";"51,5";"Mobil";"58,11";"64,98";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,700";"49,8";"Mobil";"58,18";"64,96";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,800";"49,8";"Mobil";"58,09";"64,93";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"123,900";"47,7";"Mobil";"58,26";"64,92";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,000";"50,6";"Mobil";"57,92";"64,90";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,100";"54,2";"Mobil";"57,49";"64,88";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,200";"52,7";"Mobil";"57,58";"64,85";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,300";"50,7";"Mobil";"57,74";"64,83";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,400";"48,1";"Mobil";"58,04";"64,80";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,500";"45,5";"Mobil";"58,34";"64,78";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,600";"40,9";"Mobil";"58,78";"64,75";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,700";"40,9";"Mobil";"58,69";"64,73";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,800";"41,6";"Mobil";"58,53";"64,70";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"124,900";"42,1";"Mobil";"58,37";"64,68";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,000";"43,4";"Mobil";"58,25";"64,66";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,100";"43,2";"Mobil";"58,32";"64,64";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,200";"42,3";"Mobil";"58,47";"64,62";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,300";"42,3";"Mobil";"58,50";"64,60";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,400";"41,2";"Mobil";"58,56";"64,58";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,500";"40,7";"Mobil";"58,53";"64,56";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,600";"40,2";"Mobil";"58,51";"64,54";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,700";"40,6";"Mobil";"58,37";"64,52";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,800";"43,2";"Mobil";"58,24";"64,50";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"125,900";"44,5";"Mobil";"58,24";"64,48";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,000";"44,9";"Mobil";"58,21";"64,46";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,100";"44,5";"Mobil";"58,27";"64,44";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,200";"43,9";"Mobil";"58,28";"64,41";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,300";"42,6";"Mobil";"58,37";"64,39";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,400";"44,3";"Mobil";"58,18";"64,37";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,500";"43,9";"Mobil";"58,26";"64,35";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,600";"41,0";"Mobil";"58,44";"64,33";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,700";"40,1";"Mobil";"58,32";"64,32";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,800";"41,0";"Mobil";"58,23";"64,30";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"126,900";"41,0";"Mobil";"58,25";"64,29";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,000";"43,1";"Mobil";"58,02";"64,27";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,100";"42,7";"Mobil";"58,12";"64,25";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,200";"43,4";"Mobil";"58,12";"64,23";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,300";"45,8";"Mobil";"57,90";"64,21";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,400";"46,8";"Mobil";"57,74";"64,18";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,500";"45,2";"Mobil";"57,92";"64,17";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,600";"46,3";"Mobil";"57,90";"64,15";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,700";"49,3";"Mobil";"57,62";"64,12";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,800";"49,7";"Mobil";"57,59";"64,08";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"127,900";"50,0";"Mobil";"57,58";"64,05";"1.118";"1.059,45";"außerh. d. Bez.pegels";"Fähre: Coswig -Gierseilfähre"
+"128,000";"51,5";"Mobil";"57,47";"64,02";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,100";"51,5";"Mobil";"57,49";"63,99";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,200";"53,1";"Mobil";"57,30";"63,95";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,300";"54,0";"Mobil";"57,18";"63,93";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,400";"54,2";"Mobil";"57,17";"63,90";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,500";"53,2";"Mobil";"57,27";"63,86";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,600";"53,1";"Mobil";"57,24";"63,82";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,700";"51,7";"Mobil";"57,35";"63,79";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,800";"52,8";"Mobil";"57,24";"63,75";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"128,900";"53,2";"Mobil";"57,19";"63,72";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,000";"53,8";"Mobil";"57,11";"63,69";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,100";"52,9";"Mobil";"57,19";"63,67";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,200";"53,9";"Mobil";"57,07";"63,65";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,300";"54,6";"Mobil";"56,99";"63,63";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,400";"50,4";"Mobil";"57,39";"63,60";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,500";"52,9";"Mobil";"57,10";"63,59";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,600";"54,0";"Mobil";"56,98";"63,58";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,700";"54,2";"Mobil";"56,96";"63,57";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,800";"54,8";"Mobil";"56,89";"63,55";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"129,900";"54,4";"Mobil";"56,91";"63,53";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,000";"55,1";"Mobil";"56,83";"63,51";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,100";"54,0";"Mobil";"56,92";"63,49";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,200";"53,3";"Mobil";"56,97";"63,47";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,300";"53,0";"Mobil";"56,98";"63,46";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,400";"51,0";"Mobil";"57,20";"63,44";"1.118";"1.059,45";"außerh. d. Bez.pegels";"HW-Schutz: Buroer-Deich"
+"130,500";"51,4";"Mobil";"57,14";"63,43";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,600";"52,2";"Mobil";"57,05";"63,42";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,700";"51,7";"Mobil";"57,08";"63,41";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,800";"51,9";"Mobil";"57,12";"63,39";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"130,900";"52,4";"Mobil";"57,12";"63,37";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,000";"52,5";"Mobil";"57,12";"63,34";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,100";"52,6";"Mobil";"57,11";"63,32";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,200";"53,6";"Mobil";"56,98";"63,29";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,300";"53,1";"Mobil";"57,00";"63,28";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,400";"52,8";"Mobil";"57,04";"63,26";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,500";"54,6";"Mobil";"56,86";"63,25";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,600";"57,9";"Mobil";"56,53";"63,23";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,700";"57,7";"Mobil";"56,57";"63,22";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,800";"57,2";"Mobil";"56,65";"63,20";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"131,900";"59,1";"Mobil";"56,48";"63,18";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,000";"60,0";"Mobil";"56,43";"63,15";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,100";"61,2";"Mobil";"56,31";"63,11";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,200";"61,4";"Mobil";"56,28";"63,06";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,300";"63,9";"Mobil";"56,04";"63,04";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,400";"65,0";"Mobil";"55,94";"63,01";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,500";"62,8";"Mobil";"56,14";"62,99";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,600";"59,6";"Mobil";"56,41";"62,96";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,700";"56,0";"Mobil";"56,64";"62,92";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,800";"58,7";"Mobil";"56,43";"62,87";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"132,900";"63,2";"Mobil";"56,06";"62,86";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,000";"62,5";"Mobil";"56,15";"62,85";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,100";"59,6";"Mobil";"56,44";"62,84";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,200";"57,6";"Mobil";"56,63";"62,83";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,300";"57,0";"Mobil";"56,70";"62,82";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,400";"58,3";"Mobil";"56,58";"62,81";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,500";"60,0";"Mobil";"56,43";"62,80";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,600";"59,8";"Mobil";"56,46";"62,78";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,700";"61,6";"Mobil";"56,29";"62,77";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,800";"65,4";"Mobil";"55,95";"62,75";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"133,900";"67,8";"Mobil";"55,73";"62,73";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,000";"69,8";"Mobil";"55,56";"62,71";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,100";"69,6";"Mobil";"55,59";"62,70";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,200";"67,3";"Mobil";"55,76";"62,68";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,300";"63,7";"Mobil";"55,99";"62,68";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,400";"61,9";"Mobil";"56,24";"62,67";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,500";"61,0";"Mobil";"56,39";"62,66";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,600";"62,7";"Mobil";"56,31";"62,65";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,700";"61,7";"Mobil";"56,39";"62,63";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,800";"62,7";"Mobil";"56,28";"62,60";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"134,900";"64,5";"Mobil";"56,10";"62,58";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,000";"66,3";"Mobil";"55,92";"62,56";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,100";"64,9";"Mobil";"56,04";"62,55";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,200";"69,4";"Mobil";"55,63";"62,53";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,300";"72,1";"Mobil";"55,40";"62,52";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,400";"72,8";"Mobil";"55,31";"62,50";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,500";"74,1";"Mobil";"55,12";"62,47";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,600";"71,4";"Mobil";"55,36";"62,43";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,700";"70,4";"Mobil";"55,47";"62,42";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,800";"69,6";"Mobil";"55,48";"62,40";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"135,900";"66,6";"Mobil";"55,67";"62,37";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,000";"64,3";"Mobil";"55,84";"62,33";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,100";"62,0";"Mobil";"56,04";"62,32";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,200";"62,5";"Mobil";"56,00";"62,30";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,300";"62,3";"Mobil";"56,00";"62,28";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,400";"63,8";"Mobil";"55,83";"62,26";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,500";"62,4";"Mobil";"55,91";"62,24";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,600";"60,6";"Mobil";"56,07";"62,21";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,700";"64,1";"Mobil";"55,77";"62,19";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,800";"64,0";"Mobil";"55,77";"62,16";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"136,900";"63,6";"Mobil";"55,79";"62,15";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,000";"65,8";"Mobil";"55,55";"62,13";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,100";"67,2";"Mobil";"55,33";"62,09";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,200";"67,0";"Mobil";"55,30";"62,05";"1.118";"1.059,45";"außerh. d. Bez.pegels";"Geschiebemessstelle: Vockerode"
+"137,300";"63,3";"Mobil";"55,57";"62,02";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,400";"60,4";"Mobil";"55,86";"61,99";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,500";"61,0";"Mobil";"55,85";"61,98";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,600";"61,1";"Mobil";"55,85";"61,96";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,700";"62,9";"Mobil";"55,70";"61,95";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,800";"64,5";"Mobil";"55,55";"61,94";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"137,900";"65,8";"Mobil";"55,42";"61,93";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,000";"64,6";"Mobil";"55,51";"61,91";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,100";"64,8";"Mobil";"55,46";"61,89";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,200";"65,4";"Mobil";"55,38";"61,87";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,300";"66,5";"Mobil";"55,24";"61,85";"1.118";"1.059,45";"außerh. d. Bez.pegels";"HW-Schutz: Kliekener-Deich"
+"138,400";"63,8";"Mobil";"55,44";"61,82";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,500";"69,1";"Mobil";"54,96";"61,80";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,600";"67,3";"Mobil";"55,12";"61,78";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,700";"63,4";"Mobil";"55,45";"61,76";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,800";"66,2";"Mobil";"55,19";"61,73";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"138,900";"62,8";"Mobil";"55,48";"61,72";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,000";"63,7";"Mobil";"55,38";"61,70";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,100";"62,1";"Mobil";"55,50";"61,68";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,200";"63,3";"Mobil";"55,38";"61,66";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,300";"63,1";"Mobil";"55,40";"61,64";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,400";"61,2";"Mobil";"55,52";"61,62";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,500";"60,6";"Mobil";"55,50";"61,59";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,600";"62,9";"Mobil";"55,27";"61,56";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,700";"61,8";"Mobil";"55,33";"61,54";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,800";"60,3";"Mobil";"55,45";"61,51";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"139,900";"62,9";"Mobil";"55,21";"61,49";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,000";"64,0";"Mobil";"55,07";"61,47";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,100";"63,8";"Mobil";"55,04";"61,44";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,200";"62,0";"Mobil";"55,16";"61,41";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,300";"62,1";"Mobil";"55,11";"61,39";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,400";"64,2";"Mobil";"54,94";"61,37";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,500";"66,8";"Mobil";"54,72";"61,35";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,600";"67,4";"Mobil";"54,59";"61,33";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,700";"66,2";"Mobil";"54,58";"61,29";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,800";"63,1";"Mobil";"54,80";"61,25";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"140,900";"61,4";"Mobil";"54,90";"61,22";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"141,000";"61,1";"Mobil";"54,89";"61,19";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"141,100";"60,9";"Mobil";"54,88";"61,16";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"141,200";"61,1";"Mobil";"54,80";"61,13";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"141,300";"60,4";"Mobil";"54,80";"61,10";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"141,400";"61,8";"Mobil";"54,67";"61,06";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"141,500";"62,4";"Mobil";"54,62";"61,04";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"141,600";"63,9";"Mobil";"54,47";"61,01";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"143,700";"65,5";"Mobil";"54,24";"60,85";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"143,800";"65,7";"Mobil";"54,22";"60,83";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"143,900";"63,8";"Mobil";"54,34";"60,80";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,000";"62,6";"Mobil";"54,39";"60,77";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,100";"64,1";"Mobil";"54,24";"60,74";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,200";"65,7";"Mobil";"54,08";"60,70";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,300";"66,6";"Mobil";"53,99";"60,68";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,400";"67,7";"Mobil";"53,89";"60,65";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,500";"67,4";"Mobil";"53,90";"60,63";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,600";"64,0";"Mobil";"54,18";"60,60";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,700";"62,0";"Mobil";"54,30";"60,57";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,800";"61,9";"Mobil";"54,25";"60,54";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"144,900";"59,2";"Mobil";"54,41";"60,52";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,000";"60,0";"Mobil";"54,28";"60,49";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,100";"61,2";"Mobil";"54,15";"60,47";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,200";"62,4";"Mobil";"54,03";"60,44";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,300";"62,4";"Mobil";"54,06";"60,42";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,400";"62,1";"Mobil";"54,11";"60,40";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,500";"61,3";"Mobil";"54,11";"60,37";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,600";"59,6";"Mobil";"54,16";"60,34";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,700";"63,8";"Mobil";"53,91";"60,31";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,800";"63,8";"Mobil";"53,96";"60,28";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"145,900";"61,6";"Mobil";"54,14";"60,25";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,000";"60,7";"Mobil";"54,19";"60,22";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,100";"64,8";"Mobil";"53,79";"60,20";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,200";"66,1";"Mobil";"53,64";"60,18";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,300";"66,2";"Mobil";"53,60";"60,15";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,400";"66,3";"Mobil";"53,56";"60,11";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,500";"64,0";"Mobil";"53,76";"60,11";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,600";"63,1";"Mobil";"53,84";"60,10";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,700";"64,4";"Mobil";"53,70";"60,09";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,800";"62,4";"Mobil";"53,84";"60,07";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"146,900";"61,2";"Mobil";"53,92";"60,06";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,000";"61,6";"Mobil";"53,85";"60,04";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,100";"62,6";"Mobil";"53,77";"60,02";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,200";"63,1";"Mobil";"53,71";"60,00";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,300";"62,6";"Mobil";"53,73";"59,99";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,400";"61,5";"Mobil";"53,78";"59,97";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,500";"60,1";"Mobil";"53,89";"59,96";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,600";"59,5";"Mobil";"53,93";"59,95";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,700";"58,0";"Mobil";"53,78";"59,94";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,800";"56,7";"Starr";"53,61";"59,93";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"147,900";"53,3";"Starr";"53,47";"59,92";"1.118";"1.059,45";"außerh. d. Bez.pegels";"HW-Schutz: Rosslau-Deich"
+"148,000";"47,7";"Starr";"53,49";"59,90";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,100";"47,7";"Starr";"53,51";"59,89";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,200";"46,9";"Starr";"53,59";"59,88";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,300";"46,2";"Starr";"53,57";"59,87";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,400";"45,4";"Starr";"53,57";"59,86";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,500";"45,7";"Starr";"53,49";"59,85";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,600";"45,2";"Starr";"53,49";"59,83";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,700";"38,6";"Starr";"53,52";"59,82";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,800";"26,4";"Starr";"53,51";"59,81";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"148,900";"37,9";"Starr";"53,37";"59,79";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,000";"42,6";"Starr";"53,27";"59,77";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,100";"45,7";"Starr";"53,18";"59,75";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,200";"46,3";"Starr";"53,12";"59,72";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,300";"43,5";"Starr";"53,16";"59,70";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,400";"38,0";"Starr";"53,19";"59,67";"1.118";"1.059,45";"außerh. d. Bez.pegels";"Zufluss: Rossel"
+"149,500";"37,3";"Starr";"53,26";"59,65";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,600";"37,9";"Starr";"53,14";"59,63";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,700";"39,7";"Starr";"53,07";"59,59";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,800";"38,8";"Starr";"53,36";"59,54";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"149,900";"43,8";"Starr";"52,78";"59,48";"1.118";"1.059,45";"außerh. d. Bez.pegels";"Hafen: Werfthafen"
+"150,000";"44,9";"Starr";"52,73";"59,42";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,100";"45,0";"Starr";"52,87";"59,41";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,200";"45,4";"Starr";"52,97";"59,39";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,300";"47,4";"Starr";"52,98";"59,37";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,400";"48,8";"Starr";"53,06";"59,35";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,500";"50,8";"Starr";"53,01";"59,33";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,600";"52,8";"Starr";"52,96";"59,31";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,700";"54,4";"Starr";"53,01";"59,30";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,800";"56,4";"Starr";"53,01";"59,28";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"150,900";"57,7";"Starr";"53,05";"59,26";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"151,000";"60,0";"Mobil";"53,00";"59,24";"1.118";"1.059,45";"außerh. d. Bez.pegels";"Geschiebemessstelle: Dessau 259 (oberhalb Muldemündung)"
+"151,100";"62,7";"Mobil";"52,92";"59,23";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"151,200";"68,4";"Mobil";"52,54";"59,21";"1.118";"1.059,45";"außerh. d. Bez.pegels";"Zufluss: Mulde"
+"151,300";"74,9";"Mobil";"51,99";"59,19";"1.118";"1.059,45";"außerh. d. Bez.pegels";""
+"151,400";"70,2";"Mobil";"52,39";"59,17";"1.298";"1.059,45";"außerh. d. Bez.pegels";"Geschiebemessstelle: Dessau 260 (unterhalb Muldemündung)"
+"151,500";"72,2";"Mobil";"52,14";"59,15";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"151,600";"69,4";"Mobil";"52,30";"59,12";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"151,700";"66,7";"Mobil";"52,54";"59,11";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"151,800";"67,2";"Mobil";"52,49";"59,10";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"151,900";"65,6";"Mobil";"52,63";"59,08";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,000";"70,1";"Mobil";"52,22";"59,05";"1.298";"1.059,45";"außerh. d. Bez.pegels";"Hafen: Dessau-Wallwitz"
+"152,100";"74,7";"Mobil";"51,79";"59,04";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,200";"73,5";"Mobil";"51,88";"59,03";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,300";"70,8";"Mobil";"52,09";"59,01";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,400";"65,8";"Mobil";"52,51";"58,98";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,500";"62,8";"Mobil";"52,74";"58,96";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,600";"62,0";"Mobil";"52,79";"58,94";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,700";"64,8";"Mobil";"52,51";"58,93";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,800";"67,4";"Mobil";"52,26";"58,91";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"152,900";"68,2";"Mobil";"52,16";"58,89";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,000";"70,1";"Mobil";"51,96";"58,87";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,100";"69,0";"Mobil";"52,05";"58,85";"1.298";"1.059,45";"außerh. d. Bez.pegels";"Hafen: Leopoldhafen"
+"153,200";"68,6";"Mobil";"52,06";"58,83";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,300";"67,3";"Mobil";"52,15";"58,82";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,400";"68,9";"Mobil";"52,00";"58,80";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,500";"67,8";"Mobil";"52,07";"58,78";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,600";"70,0";"Mobil";"51,83";"58,76";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,700";"70,4";"Mobil";"51,76";"58,74";"1.298";"1.059,45";"außerh. d. Bez.pegels";""
+"153,800";"70,3";"Mobil";"51,74";"58,72";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"153,900";"68,3";"Mobil";"51,90";"58,71";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,000";"67,0";"Mobil";"52,00";"58,70";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,100";"67,1";"Mobil";"51,97";"58,69";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,200";"66,8";"Mobil";"51,98";"58,67";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,300";"66,6";"Mobil";"51,96";"58,66";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,400";"66,9";"Mobil";"51,91";"58,64";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,500";"64,8";"Mobil";"52,07";"58,62";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,600";"66,0";"Mobil";"51,93";"58,60";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,700";"65,5";"Mobil";"51,96";"58,59";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,800";"64,5";"Mobil";"52,01";"58,57";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"154,900";"64,0";"Mobil";"52,02";"58,56";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,000";"67,9";"Mobil";"51,64";"58,54";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,100";"67,3";"Mobil";"51,64";"58,52";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,200";"67,5";"Mobil";"51,57";"58,49";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,300";"67,7";"Mobil";"51,56";"58,47";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,400";"67,0";"Mobil";"51,62";"58,45";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,500";"66,6";"Mobil";"51,56";"58,43";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,600";"66,8";"Mobil";"51,42";"58,40";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,700";"68,9";"Mobil";"51,22";"58,37";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"155,800";"67,3";"Mobil";"51,36";"58,34";"1.294";"1.059,45";"außerh. d. Bez.pegels";"Hafen: Roßlau Industriehafen"
+"155,900";"67,8";"Mobil";"51,29";"58,30";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,000";"71,5";"Mobil";"50,92";"58,25";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,100";"69,6";"Mobil";"51,10";"58,25";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,200";"70,0";"Mobil";"51,06";"58,24";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,300";"68,1";"Mobil";"51,19";"58,18";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,400";"65,9";"Mobil";"51,34";"58,12";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,500";"63,9";"Mobil";"51,50";"58,10";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,600";"62,3";"Mobil";"51,62";"58,08";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,700";"60,2";"Mobil";"51,81";"58,07";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,800";"60,3";"Mobil";"51,80";"58,05";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"156,900";"59,2";"Mobil";"51,87";"58,04";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,000";"59,5";"Mobil";"51,83";"58,02";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,100";"59,1";"Mobil";"51,83";"58,00";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,200";"59,0";"Mobil";"51,79";"57,98";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,300";"59,5";"Mobil";"51,72";"57,96";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,400";"60,3";"Mobil";"51,62";"57,94";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,500";"61,0";"Mobil";"51,56";"57,92";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,600";"62,5";"Mobil";"51,43";"57,90";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,700";"62,6";"Mobil";"51,41";"57,88";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,800";"62,5";"Mobil";"51,40";"57,86";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"157,900";"63,3";"Mobil";"51,30";"57,83";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,000";"62,7";"Mobil";"51,33";"57,80";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,100";"62,1";"Mobil";"51,37";"57,78";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,200";"61,7";"Mobil";"51,39";"57,76";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,300";"62,1";"Mobil";"51,34";"57,75";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,400";"60,4";"Mobil";"51,47";"57,73";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,500";"60,8";"Mobil";"51,43";"57,71";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,600";"61,4";"Mobil";"51,35";"57,69";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,700";"60,8";"Mobil";"51,39";"57,67";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,800";"61,3";"Mobil";"51,33";"57,65";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"158,900";"60,6";"Mobil";"51,38";"57,63";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,000";"61,0";"Mobil";"51,32";"57,61";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,100";"61,8";"Mobil";"51,20";"57,59";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,200";"62,7";"Mobil";"51,09";"57,56";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,300";"61,1";"Mobil";"51,26";"57,55";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,400";"60,7";"Mobil";"51,28";"57,53";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,500";"61,2";"Mobil";"51,22";"57,51";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,600";"62,3";"Mobil";"51,10";"57,49";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,700";"64,6";"Mobil";"50,87";"57,47";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,800";"65,3";"Mobil";"50,79";"57,45";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"159,900";"62,1";"Mobil";"51,05";"57,43";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,000";"59,8";"Mobil";"51,24";"57,40";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,100";"59,4";"Mobil";"51,27";"57,39";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,200";"63,1";"Mobil";"50,93";"57,38";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,300";"66,1";"Mobil";"50,64";"57,37";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,400";"65,9";"Mobil";"50,64";"57,35";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,500";"65,7";"Mobil";"50,65";"57,33";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,600";"65,7";"Mobil";"50,63";"57,31";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,700";"62,5";"Mobil";"50,92";"57,29";"1.294";"1.059,45";"außerh. d. Bez.pegels";""
+"160,800";"61,8";"Mobil";"50,95";"57,27";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"160,900";"62,2";"Mobil";"50,90";"57,25";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,000";"61,9";"Mobil";"50,91";"57,23";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,100";"62,4";"Mobil";"50,85";"57,22";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,200";"61,2";"Mobil";"50,96";"57,20";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,300";"60,3";"Mobil";"51,03";"57,19";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,400";"60,4";"Mobil";"51,00";"57,17";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,500";"62,6";"Mobil";"50,79";"57,16";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,600";"63,6";"Mobil";"50,66";"57,14";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,700";"63,4";"Mobil";"50,68";"57,13";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,800";"64,9";"Mobil";"50,53";"57,11";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"161,900";"61,4";"Mobil";"50,84";"57,10";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,000";"60,8";"Mobil";"50,89";"57,08";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,100";"62,1";"Mobil";"50,74";"57,06";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,200";"61,9";"Mobil";"50,72";"57,04";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,300";"60,0";"Mobil";"50,86";"57,03";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,400";"62,4";"Mobil";"50,60";"57,02";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,500";"63,6";"Mobil";"50,52";"57,00";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,600";"63,2";"Mobil";"50,57";"56,98";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,700";"63,4";"Mobil";"50,54";"56,97";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,800";"67,9";"Mobil";"50,13";"56,95";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"162,900";"67,8";"Mobil";"50,12";"56,93";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,000";"66,9";"Mobil";"50,18";"56,90";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,100";"63,8";"Mobil";"50,42";"56,87";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,200";"62,9";"Mobil";"50,47";"56,84";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,300";"63,0";"Mobil";"50,45";"56,83";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,400";"62,2";"Mobil";"50,53";"56,82";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,500";"61,9";"Mobil";"50,55";"56,80";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,600";"60,9";"Mobil";"50,62";"56,78";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,700";"63,0";"Mobil";"50,40";"56,77";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,800";"64,4";"Mobil";"50,24";"56,75";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"163,900";"63,9";"Mobil";"50,28";"56,73";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,000";"63,9";"Mobil";"50,26";"56,71";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,100";"62,9";"Mobil";"50,36";"56,70";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,200";"64,0";"Mobil";"50,25";"56,68";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,300";"66,4";"Mobil";"50,01";"56,67";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,400";"65,6";"Mobil";"50,07";"56,65";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,500";"65,6";"Mobil";"50,05";"56,63";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,600";"65,8";"Mobil";"50,00";"56,60";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,700";"65,7";"Mobil";"50,00";"56,59";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,800";"66,1";"Mobil";"49,96";"56,57";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"164,900";"64,8";"Mobil";"50,05";"56,56";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,000";"62,6";"Mobil";"50,21";"56,54";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,100";"62,7";"Mobil";"50,18";"56,52";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,200";"63,3";"Mobil";"50,10";"56,49";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,300";"64,2";"Mobil";"50,02";"56,47";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,400";"65,1";"Mobil";"49,93";"56,45";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,500";"63,8";"Mobil";"50,02";"56,44";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,600";"63,6";"Mobil";"50,01";"56,42";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,700";"63,8";"Mobil";"50,00";"56,40";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,800";"65,7";"Mobil";"49,82";"56,37";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"165,900";"67,3";"Mobil";"49,67";"56,35";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,000";"68,6";"Mobil";"49,54";"56,33";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,100";"68,6";"Mobil";"49,53";"56,32";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,200";"69,5";"Mobil";"49,43";"56,30";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,300";"68,2";"Mobil";"49,53";"56,28";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,400";"65,4";"Mobil";"49,76";"56,26";"1.290";"1.059,45";"außerh. d. Bez.pegels";"Hafen: Hornhafen Aken"
+"166,500";"67,5";"Mobil";"49,56";"56,25";"1.290";"1.059,45";"außerh. d. Bez.pegels";"Fähre: Aken -Gierseilfähre"
+"166,600";"65,6";"Mobil";"49,72";"56,23";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,700";"66,9";"Mobil";"49,60";"56,22";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,800";"67,2";"Mobil";"49,57";"56,20";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"166,900";"68,7";"Mobil";"49,40";"56,19";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,000";"69,0";"Mobil";"49,34";"56,17";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,100";"67,8";"Mobil";"49,43";"56,15";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,200";"67,5";"Mobil";"49,45";"56,13";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,300";"69,5";"Mobil";"49,24";"56,11";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,400";"68,1";"Mobil";"49,33";"56,09";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,500";"65,7";"Mobil";"49,55";"56,08";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,600";"63,6";"Mobil";"49,74";"56,06";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,700";"64,9";"Mobil";"49,61";"56,04";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,800";"67,5";"Mobil";"49,36";"56,02";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"167,900";"68,4";"Mobil";"49,23";"56,00";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,000";"67,5";"Mobil";"49,25";"55,98";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,100";"66,6";"Mobil";"49,32";"55,96";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,200";"65,7";"Mobil";"49,38";"55,94";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,300";"63,6";"Mobil";"49,54";"55,93";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,400";"63,0";"Mobil";"49,58";"55,91";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,500";"63,7";"Mobil";"49,51";"55,89";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,600";"65,6";"Mobil";"49,33";"55,87";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,700";"68,1";"Mobil";"49,10";"55,85";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,800";"70,8";"Mobil";"48,85";"55,83";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"168,900";"71,4";"Mobil";"48,79";"55,81";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,000";"67,0";"Mobil";"49,16";"55,79";"1.290";"1.059,45";"außerh. d. Bez.pegels";"Hafen: Verkehrshafen Aken"
+"169,100";"71,1";"Mobil";"48,80";"55,77";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,200";"74,1";"Mobil";"48,52";"55,75";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,300";"74,5";"Mobil";"48,47";"55,74";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,400";"74,5";"Mobil";"48,46";"55,72";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,500";"73,3";"Mobil";"48,54";"55,70";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,600";"72,6";"Mobil";"48,57";"55,68";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,700";"72,7";"Mobil";"48,55";"55,67";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,800";"72,4";"Mobil";"48,57";"55,65";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"169,900";"72,0";"Mobil";"48,59";"55,64";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,000";"70,9";"Mobil";"48,68";"55,62";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,100";"69,2";"Mobil";"48,84";"55,61";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,200";"67,9";"Mobil";"48,95";"55,59";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,300";"67,7";"Mobil";"48,95";"55,57";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,400";"69,7";"Mobil";"48,75";"55,55";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,500";"74,3";"Mobil";"48,31";"55,53";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,600";"70,8";"Mobil";"48,60";"55,51";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,700";"68,4";"Mobil";"48,80";"55,50";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,800";"68,3";"Mobil";"48,79";"55,48";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"170,900";"70,5";"Mobil";"48,56";"55,47";"1.290";"1.059,45";"außerh. d. Bez.pegels";""
+"171,000";"70,4";"Mobil";"48,53";"55,46";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,100";"71,3";"Mobil";"48,44";"55,44";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,200";"69,4";"Mobil";"48,60";"55,42";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,300";"69,0";"Mobil";"48,63";"55,40";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,400";"67,5";"Mobil";"48,74";"55,38";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,500";"69,4";"Mobil";"48,56";"55,37";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,600";"69,7";"Mobil";"48,51";"55,35";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,700";"68,0";"Mobil";"48,63";"55,33";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,800";"67,7";"Mobil";"48,62";"55,30";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"171,900";"70,4";"Mobil";"48,38";"55,29";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,000";"71,0";"Mobil";"48,33";"55,27";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,100";"71,4";"Mobil";"48,27";"55,26";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,200";"70,0";"Mobil";"48,37";"55,24";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,300";"69,0";"Mobil";"48,43";"55,22";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,400";"67,2";"Mobil";"48,56";"55,19";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,500";"66,1";"Mobil";"48,61";"55,17";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,600";"65,5";"Mobil";"48,62";"55,15";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,700";"67,6";"Mobil";"48,44";"55,13";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,800";"68,2";"Mobil";"48,38";"55,11";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"172,900";"66,3";"Mobil";"48,47";"55,09";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,000";"64,8";"Mobil";"48,52";"55,07";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,100";"65,9";"Mobil";"48,45";"55,05";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,200";"67,8";"Mobil";"48,30";"55,02";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,300";"68,4";"Mobil";"48,26";"55,00";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,400";"67,4";"Mobil";"48,36";"54,97";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,500";"68,7";"Mobil";"48,23";"54,95";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,600";"68,5";"Mobil";"48,24";"54,93";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,700";"67,1";"Mobil";"48,29";"54,89";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"173,800";"67,5";"Mobil";"48,20";"54,84";"1.288";"1.059,45";"außerh. d. Bez.pegels";"Geschiebemessstelle: Aken"
+"173,900";"68,9";"Mobil";"48,08";"54,83";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,000";"69,7";"Mobil";"48,00";"54,82";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,100";"68,6";"Mobil";"48,09";"54,81";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,200";"67,7";"Mobil";"48,16";"54,80";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,300";"71,6";"Mobil";"47,80";"54,79";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,400";"71,4";"Mobil";"47,80";"54,77";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,500";"72,2";"Mobil";"47,68";"54,75";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,600";"69,9";"Mobil";"47,83";"54,72";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,700";"67,4";"Mobil";"48,06";"54,71";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,800";"66,8";"Mobil";"48,11";"54,69";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"174,900";"66,9";"Mobil";"48,07";"54,67";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,000";"68,4";"Mobil";"47,90";"54,65";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,100";"69,4";"Mobil";"47,80";"54,64";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,200";"69,2";"Mobil";"47,81";"54,62";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,300";"68,3";"Mobil";"47,86";"54,60";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,400";"69,3";"Mobil";"47,73";"54,57";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,500";"70,9";"Mobil";"47,58";"54,56";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,600";"75,0";"Mobil";"47,20";"54,55";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,700";"71,5";"Mobil";"47,47";"54,53";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,800";"70,3";"Mobil";"47,54";"54,51";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"175,900";"70,6";"Mobil";"47,52";"54,50";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,000";"68,7";"Mobil";"47,69";"54,48";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,100";"68,3";"Mobil";"47,69";"54,46";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,200";"68,8";"Mobil";"47,61";"54,43";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,300";"70,3";"Mobil";"47,46";"54,42";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,400";"70,4";"Mobil";"47,44";"54,40";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,500";"68,4";"Mobil";"47,58";"54,38";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,600";"67,9";"Mobil";"47,59";"54,35";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,700";"66,8";"Mobil";"47,65";"54,34";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,800";"66,1";"Mobil";"47,66";"54,32";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"176,900";"65,5";"Mobil";"47,67";"54,30";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,000";"70,8";"Mobil";"47,14";"54,27";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,100";"69,7";"Mobil";"47,24";"54,26";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,200";"68,2";"Mobil";"47,36";"54,24";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,300";"67,8";"Mobil";"47,39";"54,22";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,400";"71,5";"Mobil";"47,04";"54,19";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,500";"76,7";"Mobil";"46,57";"54,16";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,600";"76,0";"Mobil";"46,61";"54,13";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,700";"73,8";"Mobil";"46,75";"54,10";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,800";"69,6";"Mobil";"47,07";"54,06";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"177,900";"67,3";"Mobil";"47,25";"54,04";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,000";"66,4";"Mobil";"47,32";"54,02";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,100";"66,7";"Mobil";"47,31";"54,01";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,200";"65,8";"Mobil";"47,40";"53,99";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,300";"66,9";"Mobil";"47,24";"53,97";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,400";"66,3";"Mobil";"47,21";"53,95";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,500";"64,8";"Mobil";"47,33";"53,93";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,600";"65,4";"Mobil";"47,26";"53,91";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,700";"68,1";"Mobil";"47,03";"53,89";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"178,800";"69,8";"Mobil";"46,88";"53,87";"1.288";"1.059,45";"außerh. d. Bez.pegels";"Fähre: Breitenhagen -Gierseilfähre"
+"178,900";"70,8";"Mobil";"46,75";"53,86";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"179,000";"71,5";"Mobil";"46,66";"53,84";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"179,100";"68,9";"Mobil";"46,86";"53,80";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"179,200";"68,1";"Mobil";"46,89";"53,76";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"179,300";"66,2";"Mobil";"47,06";"53,74";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"179,400";"67,0";"Mobil";"46,99";"53,72";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"179,500";"68,0";"Mobil";"46,88";"53,71";"1.288";"1.059,45";"außerh. d. Bez.pegels";""
+"179,600";"67,3";"Mobil";"46,92";"53,69";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"179,700";"68,3";"Mobil";"46,82";"53,67";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"179,800";"67,0";"Mobil";"46,91";"53,64";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"179,900";"66,9";"Mobil";"46,89";"53,63";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,000";"66,8";"Mobil";"46,87";"53,61";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,100";"67,8";"Mobil";"46,75";"53,59";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,200";"67,0";"Mobil";"46,79";"53,57";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,300";"66,6";"Mobil";"46,80";"53,55";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,400";"67,9";"Mobil";"46,67";"53,52";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,500";"68,5";"Mobil";"46,59";"53,50";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,600";"69,1";"Mobil";"46,52";"53,48";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,700";"69,4";"Mobil";"46,48";"53,46";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,800";"69,4";"Mobil";"46,47";"53,43";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"180,900";"69,3";"Mobil";"46,46";"53,41";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,000";"68,6";"Mobil";"46,51";"53,39";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,100";"68,0";"Mobil";"46,54";"53,37";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,200";"68,1";"Mobil";"46,50";"53,35";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,300";"67,6";"Mobil";"46,55";"53,33";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,400";"68,4";"Mobil";"46,46";"53,30";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,500";"67,0";"Mobil";"46,56";"53,29";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,600";"66,2";"Mobil";"46,59";"53,27";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,800";"68,0";"Mobil";"46,43";"53,22";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"181,900";"68,8";"Mobil";"46,34";"53,21";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"182,000";"69,9";"Mobil";"46,22";"53,19";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"182,100";"69,2";"Mobil";"46,27";"53,18";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+"182,200";"70,2";"Starr";"46,29";"53,16";"1.286";"1.059,45";"außerh. d. Bez.pegels";""
+""

http://dive4elements.wald.intevation.org