changeset 8575:a8048aac8831

Merge of MINFO improvement developments
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 10 Mar 2015 17:01:42 +0100
parents c16d04f2c5bc (diff) 4dd6d89ce95e (current diff)
children 0d711ecbcd49
files gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties
diffstat 87 files changed, 1781 insertions(+), 1557 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/artifacts/chart.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/artifacts/chart.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -116,6 +116,7 @@
                     <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>
--- a/artifacts/doc/conf/artifacts/minfo.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/artifacts/minfo.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -35,31 +35,31 @@
 
         <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
             <from state="state.minfo.calculation_mode"/>
-            <to state="state.minfo.bed.difference_select"/>
+            <to state="state.minfo.distance_only"/>
             <condition data="calculation_mode" value="calc.bed.diff" operator="equal"/>
         </transition>
 
         <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
             <from state="state.minfo.calculation_mode"/>
-            <to state="state.minfo.bed.location"/>
+            <to state="state.minfo.distance"/>
             <condition data="calculation_mode" value="calc.bed.quality" operator="equal"/>
         </transition>
 
-
         <state id="state.minfo.distance_only" description="state.minfo.distance_only" state="org.dive4elements.river.artifacts.states.DistanceOnlySelect" helpText="help.state.minfo.distance_only">
             <data name="ld_from" type="Double" />
             <data name="ld_to"   type="Double" />
         </state>
 
+        <state id="state.minfo.distance" description="state.minfo.distance" state="org.dive4elements.river.artifacts.states.DistanceSelect" helpText="help.state.minfo.distance">
+            <data name="ld_from" type="Double" />
+            <data name="ld_to"   type="Double" />
+            <data name="ld_step" type="Double" />
+        </state>
+
         <state id="state.minfo.sq.location" description="state.minfo.sq.location" state="org.dive4elements.river.artifacts.states.LocationSelect" helpText="help.state.minfo.sq.location">
             <data name="ld_locations" type="double"/>
         </state>
 
-        <state id="state.minfo.bed.location" description="state.minfo.bed.location" state="org.dive4elements.river.artifacts.states.DistanceOnlySelect" helpText="help.state.minfo.bed.location">
-            <data name="ld_from" type="Double" />
-            <data name="ld_to" type="Double" />
-        </state>
-
         <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
             <from state="state.minfo.distance_only"/>
             <to state="state.minfo.dischargestate"/>
@@ -72,14 +72,21 @@
             <condition data="calculation_mode" value="calc.bed.middle" operator="equal"/>
         </transition>
 
+        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+            <from state="state.minfo.distance_only"/>
+            <to state="state.minfo.bed.difference_select"/>
+            <condition data="calculation_mode" value="calc.bed.diff" operator="equal"/>
+        </transition>
+
         <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
             <from state="state.minfo.sq.location"/>
             <to state="state.minfo.sq.period"/>
         </transition>
 
         <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
-            <from state="state.minfo.bed.location"/>
+            <from state="state.minfo.distance"/>
             <to state="state.minfo.bed.periods"/>
+            <condition data="calculation_mode" value="calc.bed.quality" operator="equal"/>
         </transition>
 
         <state id="state.minfo.dischargestate" description="state.minfo.dischargestate" state="org.dive4elements.river.artifacts.states.DischargeState" helpText="help.state.minfo.dischargestate">
@@ -545,8 +552,7 @@
 
         <state id="state.minfo.sediment.load.period" description="state.minfo.bed.period" state="org.dive4elements.river.artifacts.states.minfo.SedimentLoadYearSelect"
 				helpText="help.state.minfo.sediment.load.period">
-            <data name="start" type="Integer"/>
-            <data name="end" type="Integer"/>
+            <data name="years" type="String"/>
         </state>
 
         <state id="state.minfo.sediment.load.epochs" description="state.minfo.bed.epochs" state="org.dive4elements.river.artifacts.states.minfo.SedimentLoadEpochSelect"
--- a/artifacts/doc/conf/artifacts/winfo.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/artifacts/winfo.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -47,7 +47,7 @@
 
         <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
             <from state="state.winfo.calculation_mode"/>
-            <to state="state.winfo.waterlevel_pair_select"/>
+            <to state="state.winfo.distance_only"/>
             <condition data="calculation_mode" value="calc.w.differences" operator="equal"/>
         </transition>
 
@@ -63,6 +63,12 @@
             <condition data="calculation_mode" value="calc.extreme.curve" operator="equal"/>
         </transition>
 
+        <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
+            <from state="state.winfo.distance_only"/>
+            <to state="state.winfo.waterlevel_pair_select"/>
+            <condition data="calculation_mode" value="calc.w.differences" operator="equal"/>
+        </transition>
+
         <transition transition="org.dive4elements.river.artifacts.transitions.DefaultTransition">
             <from state="state.winfo.waterlevel_pair_select"/>
             <to state="state.winfo.w_differences"/>
--- a/artifacts/doc/conf/cache.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/cache.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -58,6 +58,16 @@
            memoryStoreEvictionPolicy="LRU"
            />
 
+    <!-- This one is used to cache the non-computed bedheight-values.-->
+    <cache name="bedheight-value-table-static"
+           maxElementsInMemory="200"
+           eternal="false"
+           timeToLiveSeconds="172800"
+           overflowToDisk="true"
+           diskPersistent="true"
+           memoryStoreEvictionPolicy="LRU"
+           />
+
     <!-- This one is used to cache the non-computed wst-values.-->
     <cache name="wst-wq-value-table-static"
            maxElementsInMemory="200"
--- a/artifacts/doc/conf/log4j.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/log4j.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -16,3 +16,9 @@
 log4j.appender.FLYS.File=/var/log/d4e-river/d4e-server.log
 log4j.appender.FLYS.MaxFileSize=5000KB
 log4j.appender.FLYS.MaxBackupIndex=1
+
+log4j.logger.org.dive4elements.artifactdatabase.rest.Standalone=INFO, START
+log4j.appender.START=org.apache.log4j.ConsoleAppender
+log4j.appender.START.Target = System.out
+log4j.appender.START.layout = org.apache.log4j.PatternLayout
+log4j.appender.START.layout.ConversionPattern=%d %m%n
--- a/artifacts/doc/conf/meta-data.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/meta-data.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -1873,8 +1873,9 @@
                             bhs.year
                      FROM   bed_height_single bhs
                             JOIN bed_height_single_values bhsv
-                              ON bhsv.bed_height_single_id = bhs.id
-                     WHERE  bhs.river_id = ${river_id}),
+                                ON bhsv.bed_height_single_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,
@@ -1885,7 +1886,8 @@
                      FROM   sta b1
                             JOIN sta b2
                               ON b1.station = b2.station
-                                 AND b1.id &lt;&gt; b2.id)
+                              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
--- a/artifacts/doc/conf/themes.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/themes.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -212,6 +212,7 @@
         <mapping from="flow_velocity.discharge" to="FlowVelocityDischarge" />
         <mapping from="flow_velocity.measurement" to="FlowVelocityDischarge" />
         <mapping from="bedheight_middle.single" to="MiddleBedHeightSingle" />
+        <mapping from="bedheight_middle.manualpoints" to="ManualPoints" />
         <mapping from="bed_longitudinal_section.porosity_toplayer" to="PorosityTopLayer" />
         <mapping from="bed_longitudinal_section.porosity_sublayer" to="PorositySubLayer" />
         <mapping from="bed_longitudinal_section.sediment_density_toplayer" to="DensityTopLayer" />
@@ -243,72 +244,72 @@
         <mapping from="sq_a_measurement" to="SQMeasurementsA" />
         <mapping from="sq_a_outlier" to="SQOutliersA" />
         <mapping from="sq_a_curve" to="SQCurveA" />
-        <mapping from="sq_a_outlier_curve" to="SQCurveA" />
+        <mapping from="sq_a_outlier_curve" to="SQOutlierCurveA" />
         <mapping from="sq_a_outlier_measurement" to="SQMeasurementsA" />
         <mapping from="sq_b_measurement" to="SQMeasurementsB" />
         <mapping from="sq_b_outlier" to="SQOutliersB" />
         <mapping from="sq_b_curve" to="SQCurveB" />
-        <mapping from="sq_b_outlier_curve" to="SQCurveB" />
+        <mapping from="sq_b_outlier_curve" to="SQOutlierCurveB" />
         <mapping from="sq_b_outlier_measurement" to="SQMeasurementsB" />
         <mapping from="sq_c_measurement" to="SQMeasurementsC" />
         <mapping from="sq_c_outlier" to="SQOutliersC" />
         <mapping from="sq_c_curve" to="SQCurveC" />
-        <mapping from="sq_c_outlier_curve" to="SQCurveC" />
+        <mapping from="sq_c_outlier_curve" to="SQOutlierCurveC" />
         <mapping from="sq_c_outlier_measurement" to="SQMeasurementsC" />
         <mapping from="sq_d_measurement" to="SQMeasurementsD" />
         <mapping from="sq_d_outlier" to="SQOutliersD" />
         <mapping from="sq_d_curve" to="SQCurveD" />
-        <mapping from="sq_d_outlier_curve" to="SQCurveD" />
+        <mapping from="sq_d_outlier_curve" to="SQOutlierCurveD" />
         <mapping from="sq_d_outlier_measurement" to="SQMeasurementsD" />
         <mapping from="sq_e_measurement" to="SQMeasurementsE" />
         <mapping from="sq_e_outlier" to="SQOutliersE" />
         <mapping from="sq_e_curve" to="SQCurveE" />
-        <mapping from="sq_e_outlier_curve" to="SQCurveE" />
+        <mapping from="sq_e_outlier_curve" to="SQOutlierCurveE" />
         <mapping from="sq_e_outlier_measurement" to="SQMeasurementsE" />
         <mapping from="sq_f_measurement" to="SQMeasurementsF" />
         <mapping from="sq_f_outlier" to="SQOutliersF" />
         <mapping from="sq_f_curve" to="SQCurveF" />
-        <mapping from="sq_f_outlier_curve" to="SQCurveF" />
+        <mapping from="sq_f_outlier_curve" to="SQOutlierCurveF" />
         <mapping from="sq_f_outlier_measurement" to="SQMeasurementsF" />
         <mapping from="sq_g_measurement" to="SQMeasurementsG" />
         <mapping from="sq_g_outlier" to="SQOutliersG" />
         <mapping from="sq_g_curve" to="SQCurveG" />
-        <mapping from="sq_g_outlier_curve" to="SQCurveG" />
+        <mapping from="sq_g_outlier_curve" to="SQOutlierCurveG" />
         <mapping from="sq_g_outlier_measurement" to="SQMeasurementsG" />
         <mapping from="sq_a_measurement_overview" to="SQMeasurementsA" />
         <mapping from="sq_a_outlier_overview" to="SQOutliersA" />
         <mapping from="sq_a_curve_overview" to="SQCurveA" />
-        <mapping from="sq_a_outlier_curve_overview" to="SQCurveA" />
+        <mapping from="sq_a_outlier_curve_overview" to="SQOutlierCurveA" />
         <mapping from="sq_a_outlier_measurement_overview" to="SQMeasurementsA" />
         <mapping from="sq_b_measurement_overview" to="SQMeasurementsB" />
         <mapping from="sq_b_outlier_overview" to="SQOutliersB" />
         <mapping from="sq_b_curve_overview" to="SQCurveB" />
-        <mapping from="sq_b_outlier_curve_overview" to="SQCurveB" />
+        <mapping from="sq_b_outlier_curve_overview" to="SQOutlierCurveB" />
         <mapping from="sq_b_outlier_measurement_overview" to="SQMeasurementsB" />
         <mapping from="sq_c_measurement_overview" to="SQMeasurementsC" />
         <mapping from="sq_c_outlier_overview" to="SQOutliersC" />
         <mapping from="sq_c_curve_overview" to="SQCurveC" />
-        <mapping from="sq_c_outlier_curve_overview" to="SQCurveC" />
+        <mapping from="sq_c_outlier_curve_overview" to="SQOutlierCurveC" />
         <mapping from="sq_c_outlier_measurement_overview" to="SQMeasurementsC" />
         <mapping from="sq_d_measurement_overview" to="SQMeasurementsD" />
         <mapping from="sq_d_outlier_overview" to="SQOutliersD" />
         <mapping from="sq_d_curve_overview" to="SQCurveD" />
-        <mapping from="sq_d_outlier_curve_overview" to="SQCurveD" />
+        <mapping from="sq_d_outlier_curve_overview" to="SQOutlierCurveD" />
         <mapping from="sq_d_outlier_measurement_overview" to="SQMeasurementsD" />
         <mapping from="sq_e_measurement_overview" to="SQMeasurementsE" />
         <mapping from="sq_e_outlier_overview" to="SQOutliersE" />
         <mapping from="sq_e_curve_overview" to="SQCurveE" />
-        <mapping from="sq_e_outlier_curve_overview" to="SQCurveE" />
+        <mapping from="sq_e_outlier_curve_overview" to="SQOutlierCurveE" />
         <mapping from="sq_e_outlier_measurement_overview" to="SQMeasurementsE" />
         <mapping from="sq_f_measurement_overview" to="SQMeasurementsF" />
         <mapping from="sq_f_outlier_overview" to="SQOutliersF" />
         <mapping from="sq_f_curve_overview" to="SQCurveF" />
-        <mapping from="sq_f_outlier_curve_overview" to="SQCurveF" />
+        <mapping from="sq_f_outlier_curve_overview" to="SQOutlierCurveF" />
         <mapping from="sq_f_outlier_measurement_overview" to="SQMeasurementsF" />
         <mapping from="sq_g_measurement_overview" to="SQMeasurementsG" />
         <mapping from="sq_g_outlier_overview" to="SQOutliersG" />
         <mapping from="sq_g_curve_overview" to="SQCurveG" />
-        <mapping from="sq_g_outlier_curve_overview" to="SQCurveG" />
+        <mapping from="sq_g_outlier_curve_overview" to="SQOutlierCurveG" />
         <mapping from="sq_g_outlier_measurement_overview" to="SQMeasurementsG" />
 
         <mapping from="fix_sector_average_wq_0" to="FixingSectorAverageWQ0" />
--- a/artifacts/doc/conf/themes/default.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/themes/default.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -2345,6 +2345,7 @@
         <inherits>
             <inherit from="Lines" />
             <inherit from="Points" />
+            <inherit from="Label" />
         </inherits>
         <fields>
             <field name="showlines" type="boolean" display="Linie anzeigen"
@@ -2355,8 +2356,10 @@
                 default="10" hints="hidden" />
             <field name="linecolor" type="Color" display="Linienfarbe"
                 default="0, 0, 0" hints="hidden" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
+            <field name="textorientation" type="boolean" display="Textausrichtung"
+                default="true" />
+            <field name="showpointlabel" type="boolean"
+                display="Punktbeschriftung anzeigen" default="true"/>
         </fields>
     </theme>
 
@@ -2391,6 +2394,7 @@
             <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>
 
@@ -2580,6 +2584,63 @@
         </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" />
--- a/artifacts/doc/conf/themes/second.xml	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/doc/conf/themes/second.xml	Tue Mar 10 17:01:42 2015 +0100
@@ -2345,6 +2345,7 @@
         <inherits>
             <inherit from="Lines" />
             <inherit from="Points" />
+            <inherit from="Label" />
         </inherits>
         <fields>
             <field name="pointcolor" type="Color" default="0, 153, 255" />
@@ -2356,8 +2357,10 @@
                 default="10" hints="hidden" />
             <field name="linecolor" type="Color" display="Linienfarbe"
                 default="0, 0, 0" hints="hidden" />
-            <field name="showlinelabel" type="boolean"
-                display="Beschriftung anzeigen" default="false" hints="hidden" />
+            <field name="textorientation" type="boolean" display="Textausrichtung"
+                default="true" />
+            <field name="showpointlabel" type="boolean"
+                display="Punktbeschriftung anzeigen" default="true"/>
         </fields>
     </theme>
 
@@ -2393,6 +2396,7 @@
             <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>
 
@@ -2577,6 +2581,63 @@
         </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" />
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java	Tue Mar 10 17:01:42 2015 +0100
@@ -280,6 +280,14 @@
             Integer.parseInt(getDataAsString("wst_id")));
     }
 
+    public WKms getWKms(int idx, double from, double to) {
+        log.debug("StaticWKmsArtifact.getWKms");
+
+        return WKmsFactory.getWKms(
+            Integer.parseInt(getDataAsString("col_pos")),
+            Integer.parseInt(getDataAsString("wst_id")),
+            from, to);
+    }
 
     /**
      * Returns W at Km of WKms, linearly interpolated.
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Tue Mar 10 17:01:42 2015 +0100
@@ -85,9 +85,6 @@
      * range. */
     public static final int DEFAULT_Q_STEPS = 30;
 
-    /** The default step width between the start end end kilometer. */
-    public static final double DEFAULT_KM_STEPS = 0.1;
-
     private static final String [] INACTIVES = new String[] {
         LONGITUDINAL_Q,
         DURATION_Q,
@@ -176,9 +173,8 @@
         return this.getWaterlevelData(null);
     }
 
-    // THIS IS FREAKY BULLSHIT! Felix, why do you call the calculation directly????
     protected CalculationResult getDischargeLongitudinalSectionData() {
-        // XXX: THIS AN _EXPENSIVE_ CALCULATION! CACHE IT!
+        // TODO: This caluclation should be cached as it is quite expensive.
         return new Calculation4(new Calculation4Access(this)).calculate();
     }
 
@@ -823,42 +819,12 @@
     /**
      * Returns the selected Kms.
      *
-     * @param distance An 2dim array with [lower, upper] values.
-     *
-     * @return the selected Kms.
-     */
-    public double[] getKms(double[] distance) {
-        StateData dStep = getData("ld_step");
-
-        if (dStep == null) {
-            log.warn("No step width given. Cannot compute Kms.");
-            return null;
-        }
-
-        double step = Double.parseDouble((String) dStep.getValue());
-
-        // transform step from 'm' into 'km'
-        step = step / 1000;
-
-        if (step == 0d) {
-            step = DEFAULT_KM_STEPS;
-        }
-
-        return DoubleUtil.explode(distance[0], distance[1], step);
-    }
-
-
-    /**
-     * Returns the selected Kms.
-     *
      * @return the selected kms.
      */
     public double[] getKms() {
         if (isRange()) {
             RangeAccess rangeAccess = new RangeAccess(this);
-            double [] distance = rangeAccess.getKmRange();
-            return getKms(distance);
-
+            return rangeAccess.getKmSteps();
         }
         else {
             return LocationDistanceSelect.getLocations(this);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedDifferencesAccess.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedDifferencesAccess.java	Tue Mar 10 17:01:42 2015 +0100
@@ -19,7 +19,7 @@
 
 
 public class BedDifferencesAccess
-extends RiverAccess
+extends RangeAccess
 {
     private static Logger log = Logger.getLogger(BedDifferencesAccess.class);
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedHeightAccess.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/BedHeightAccess.java	Tue Mar 10 17:01:42 2015 +0100
@@ -49,7 +49,7 @@
     }
 
 
-    public int[] getBedHeightSingleIDs() {
+    public int[] getBedHeightIDs() {
         if (singleIDs == null) {
             String data = getString("soundings");
 
@@ -58,7 +58,7 @@
                 return null;
             }
             else {
-                log.debug("getBedHeightSingleIDs(): data=" + data);
+                log.debug("getBedHeightIDs(): data=" + data);
             }
 
             String[] parts = data.split(";");
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java	Tue Mar 10 17:01:42 2015 +0100
@@ -16,6 +16,7 @@
 import org.dive4elements.river.artifacts.WINFOArtifact;
 
 import org.dive4elements.river.utils.RiverUtils;
+import org.dive4elements.river.utils.DoubleUtil;
 
 
 /** For the moment, light-weight wrapper around RiverUtils. */
@@ -27,6 +28,9 @@
 
     public static enum KM_MODE { RANGE, LOCATIONS, NONE };
 
+    /** The default step width between the start end end kilometer. */
+    public static final double DEFAULT_KM_STEPS = 0.1;
+
     double[] kmRange;
 
     Double from;
@@ -214,5 +218,23 @@
     public double[] getKmFromTo() {
          return RiverUtils.getKmFromTo(this.getArtifact());
     }
+
+    /**
+     * Returns the selected Kms in steps as specified.
+     *
+     * @return Each step for this range.
+     */
+    public double[] getKmSteps() {
+        double step = getStep();
+
+        // transform step from 'm' into 'km'
+        step = step / 1000;
+
+        if (step == 0d) {
+            step = DEFAULT_KM_STEPS;
+        }
+
+        return DoubleUtil.explode(getFrom(), getTo(), step);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SedimentLoadAccess.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SedimentLoadAccess.java	Tue Mar 10 17:01:42 2015 +0100
@@ -25,12 +25,13 @@
 
     private int [][] epochs;
 
-    private int [] period;
+    private int [] years;
 
     private Integer sqTiId;
 
     public SedimentLoadAccess(D4EArtifact artifact) {
         super(artifact);
+        years = null;
     }
 
     public Double getLowerKM() {
@@ -50,21 +51,33 @@
         return time;
     }
 
-    /** [startyear, endyear] if its about years. */
-    public int[] getPeriod() {
-        if (period != null) {
-            return period;
+    /** [year1, years2,..] if its about years. */
+    public int[] getYears() {
+        if (years != null) {
+            return years;
         }
         if (getYearEpoch().equals("year") ) {
-            Integer start = getInteger("start");
-            Integer end = getInteger("end");
-            if (start == null || end == null) {
-                log.warn("No 'start' or 'end' parameter specified!");
+            TIntArrayList ints = new TIntArrayList();
+            String yearsData = getString("years");
+            if (yearsData == null || yearsData.isEmpty()) {
+                log.warn("No years provided");
                 return null;
             }
+            for (String sValue :yearsData.split(" ")) {
+                try {
+                    ints.add(Integer.parseInt(sValue));
+                } catch (NumberFormatException e) {
+                    /* Client should prevent this */
+                    log.warn("Invalid year value: " + sValue);
+                    continue;
+                }
+            }
 
-            period = new int[]{start.intValue(), end.intValue()};
-            return period;
+            if (!ints.isEmpty()) {
+                ints.sort();
+                years = ints.toNativeArray();
+            }
+            return years;
         }
         return null;
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/context/SessionCallContextListener.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/context/SessionCallContextListener.java	Tue Mar 10 17:01:42 2015 +0100
@@ -67,9 +67,6 @@
     public void close(CallContext context) {
         log.debug("SessionCallContextListener.close");
 
-        Session session = (Session)context.getContextValue(SESSION_KEY);
-        session.close();
-
         SessionHolder.release();
     }
 }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DifferenceCurveFacet.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DifferenceCurveFacet.java	Tue Mar 10 17:01:42 2015 +0100
@@ -14,6 +14,7 @@
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.model.WKmsImpl;
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
 
 
@@ -54,11 +55,15 @@
 
         WKms [] wkms = (WKms [])res.getData();
 
-        WKms result = wkms[index];
-        log.debug("Got difference curve data (" + result.getName()
-            + ") at index: " + index);
-
-        return result;
+        if (wkms.length > 0) {
+            WKms result = wkms[index];
+            log.debug("Got difference curve data (" + result.getName()
+                + ") at index: " + index);
+            return result;
+        } else {
+            log.debug("Empty difference facet.");
+            return new WKmsImpl();
+        }
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKms.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKms.java	Tue Mar 10 17:01:42 2015 +0100
@@ -21,6 +21,9 @@
 
     TDoubleArrayList allKms();
 
+    /** A new list of values between the km's from and to. */
+    WKms filteredKms(double from, double to);
+
     TDoubleArrayList allWs();
 
     boolean guessWaterIncreasing();
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFactory.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFactory.java	Tue Mar 10 17:01:42 2015 +0100
@@ -39,6 +39,11 @@
         "SELECT km, w FROM wst_w_values " +
         "WHERE wst_id = :wst_id AND column_pos = :column_pos";
 
+    public static final String SQL_SELECT_WS_FOR_RANGE =
+        "SELECT km, w FROM wst_w_values " +
+        "WHERE wst_id = :wst_id AND column_pos = :column_pos " +
+        "AND km BETWEEN :kmfrom AND :kmto";
+
     /** Query to get name for wst_id and column_pos. */
     public static final String SQL_SELECT_NAME =
         "SELECT name " +
@@ -82,31 +87,26 @@
     private WKmsFactory() {
     }
 
+    public static WKms getWKms(int column, int wst_id, double from, double to) {
+        log.debug("WKmsFactory.getWKms");
+        Cache cache = CacheFactory.getCache(StaticWQKmsCacheKey.CACHE_NAME);
 
-    /**
-     * Get WKms for given column and wst_id, caring about the cache.
-     */
-    public static WKms getWKms(int column, int wst_id) {
-        log.debug("WKmsFactory.getWKms");
-        Cache cache = CacheFactory.getCache(StaticWKmsCacheKey.CACHE_NAME);
-
-        StaticWKmsCacheKey cacheKey;
+        String cacheKey = Integer.toString(column) + ":" + Integer.toString(wst_id);
 
         if (cache != null) {
-            cacheKey = new StaticWKmsCacheKey(wst_id, column);
+            if (!Double.isNaN(from) && ! Double.isNaN(to)) {
+                cacheKey += ":" + Double.toString(from) + ":" + Double.toString(to);
+            }
             Element element = cache.get(cacheKey);
             if (element != null) {
                 log.debug("Got static wst values from cache");
                 return (WKms)element.getValue();
             }
         }
-        else {
-            cacheKey = null;
-        }
 
-        WKms values = getWKmsUncached(column, wst_id);
+        WKms values = getWKmsUncached(column, wst_id, from, to);
 
-        if (values != null && cacheKey != null) {
+        if (values != null && cache != null) {
             log.debug("Store static wst values in cache.");
             Element element = new Element(cacheKey, values);
             cache.put(element);
@@ -114,6 +114,13 @@
         return values;
     }
 
+    /**
+     * Get WKms for given column and wst_id, caring about the cache.
+     */
+    public static WKms getWKms(int column, int wst_id) {
+        return getWKms(column, wst_id, Double.NaN, Double.NaN);
+    }
+
     /** Get name for a WKms wrapped in W, if suitable. */
     public static String getWKmsNameWWrapped(int wst_id) {
         return getWKmsNameWWrapped(-1, wst_id);
@@ -210,7 +217,7 @@
      * @param wst_id database id of the wst
      * @return according WKms.
      */
-    public static WKms getWKmsUncached(int column, int wst_id) {
+    public static WKms getWKmsUncached(int column, int wst_id, double from, double to) {
 
         if (log.isDebugEnabled()) {
             log.debug("WKmsFactory.getWKmsUncached c/" + column + ", wst_id/" + wst_id);
@@ -219,9 +226,17 @@
         WKmsImpl wkms = new WKmsImpl(getWKmsName(column, wst_id));
 
         Session session = SessionHolder.HOLDER.get();
-        SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_WS)
-            .addScalar("km", StandardBasicTypes.DOUBLE)
-            .addScalar("w",  StandardBasicTypes.DOUBLE);
+        SQLQuery sqlQuery;
+        if (Double.isNaN(from) || Double.isNaN(to)) {
+            sqlQuery = session.createSQLQuery(SQL_SELECT_WS);
+        } else {
+            sqlQuery = session.createSQLQuery(SQL_SELECT_WS_FOR_RANGE);
+            sqlQuery.setDouble("kmfrom", from);
+            sqlQuery.setDouble("kmto", to);
+        }
+
+        sqlQuery.addScalar("km", StandardBasicTypes.DOUBLE)
+                .addScalar("w",  StandardBasicTypes.DOUBLE);
         sqlQuery.setInteger("wst_id",     wst_id);
         sqlQuery.setInteger("column_pos", column);
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsImpl.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsImpl.java	Tue Mar 10 17:01:42 2015 +0100
@@ -108,5 +108,17 @@
     public TDoubleArrayList allWs() {
         return ws;
     }
+
+    @Override
+    public WKms filteredKms(double from, double to) {
+        WKmsImpl retval = new WKmsImpl(getName());
+        for (int i = 0; i < size(); i++) {
+            double km = kms.getQuick(i);
+            if (km >= from && km <= to) {
+                retval.add(ws.getQuick(i), km);
+            }
+        }
+        return retval;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKms.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKms.java	Tue Mar 10 17:01:42 2015 +0100
@@ -137,6 +137,18 @@
         return qs;
     }
 
+    @Override
+    public WKms filteredKms(double from, double to) {
+        WQKms retval = new WQKms(getName());
+        for (int i = 0; i < size(); i++) {
+            double km = kms.getQuick(i);
+            if (km >= from && km <= to) {
+                retval.add(ws.getQuick(i), qs.getQuick(i), km);
+            }
+        }
+        return retval;
+    }
+
     public double[] getKms() {
         return kms.toNativeArray();
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java	Tue Mar 10 17:01:42 2015 +0100
@@ -37,10 +37,12 @@
 
         this.river     = access.getRiverName();
         this.heightIds = access.extractHeightIds(context);
+        double fromKm  = access.getFrom();
+        double toKm    = access.getTo();
 
         BedDiffYearResult [] results = new BedDiffYearResult[heightIds.length];
         for (int i = 0; i < heightIds.length; i++) {
-            BedHeightSingleData [] pair = getHeightPair(heightIds[i]);
+            BedHeightData [] pair = getHeightPair(heightIds[i], fromKm, toKm);
             if (pair[0].getYear() == null || pair[1].getYear() == null) {
                 addProblem("beddiff.missing.year");
             }
@@ -51,20 +53,20 @@
     }
 
     /** Get two BedHeights from factory. */
-    private static BedHeightSingleData [] getHeightPair(int [] ids) {
-        return new BedHeightSingleData [] {
-            (BedHeightSingleData)BedHeightFactory.getHeight("single", ids[0]),
-            (BedHeightSingleData)BedHeightFactory.getHeight("single", ids[1])
+    private static BedHeightData [] getHeightPair(int [] ids, double from, double to) {
+        return new BedHeightData [] {
+            (BedHeightData)BedHeightFactory.getHeight("single", ids[0], from, to),
+            (BedHeightData)BedHeightFactory.getHeight("single", ids[1], from, to)
         };
     }
 
     private BedDiffYearResult calculateYearDifference(
-        BedHeightSingleData[] pair,
+        BedHeightData[] pair,
         int[] ids
         ) {
         log.debug("BedDiffCalculation.calculateYearDifference");
-        BedHeightSingleData s1 = pair[0];
-        BedHeightSingleData s2 = pair[1];
+        BedHeightData s1 = pair[0];
+        BedHeightData s2 = pair[1];
 
         TDoubleArrayList stations = s1.getStations();
         int size = stations.size();
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightMinFacet.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightMinFacet.java	Tue Mar 10 17:01:42 2015 +0100
@@ -5,7 +5,7 @@
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 
-import org.dive4elements.river.model.BedHeightSingle;
+import org.dive4elements.river.model.BedHeight;
 
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.access.RiverAccess;
@@ -46,7 +46,7 @@
         if (resultData != null && resultData.length > index) {
             BedDiffYearResult data = resultData[index];
 
-            BedHeightSingle first = BedHeightSingle.getBedHeightSingleById(
+            BedHeight first = BedHeight.getBedHeightById(
                 data.getIdFirst());
             this.addMetaData(Resources.getMsg(
                     context.getMeta(),
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightMinFilterFacet.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightMinFilterFacet.java	Tue Mar 10 17:01:42 2015 +0100
@@ -14,7 +14,7 @@
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 
-import org.dive4elements.river.model.BedHeightSingle;
+import org.dive4elements.river.model.BedHeight;
 
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.access.RiverAccess;
@@ -68,7 +68,7 @@
                 Resources.getMsg(context.getMeta(),
                     "chart.subtitle.radius", new Object[] { radius }), "");
 
-            BedHeightSingle first = BedHeightSingle.getBedHeightSingleById(
+            BedHeight first = BedHeight.getBedHeightById(
                 oldData.getIdFirst());
             this.addMetaData(Resources.getMsg(
                     context.getMeta(),
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightSubFacet.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightSubFacet.java	Tue Mar 10 17:01:42 2015 +0100
@@ -5,7 +5,7 @@
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 
-import org.dive4elements.river.model.BedHeightSingle;
+import org.dive4elements.river.model.BedHeight;
 
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.access.RiverAccess;
@@ -46,7 +46,7 @@
         if (resultData != null && resultData.length > index) {
             BedDiffYearResult data = resultData[index];
 
-            BedHeightSingle second = BedHeightSingle.getBedHeightSingleById(
+            BedHeight second = BedHeight.getBedHeightById(
                 data.getIdSecond());
             this.addMetaData(Resources.getMsg(
                     context.getMeta(),
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightSubFilterFacet.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffHeightSubFilterFacet.java	Tue Mar 10 17:01:42 2015 +0100
@@ -14,7 +14,7 @@
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 
-import org.dive4elements.river.model.BedHeightSingle;
+import org.dive4elements.river.model.BedHeight;
 
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.access.RiverAccess;
@@ -68,7 +68,7 @@
                 Resources.getMsg(context.getMeta(),
                     "chart.subtitle.radius", new Object[] { radius }), "");
 
-            BedHeightSingle second = BedHeightSingle.getBedHeightSingleById(
+            BedHeight second = BedHeight.getBedHeightById(
                 oldData.getIdSecond());
             this.addMetaData(Resources.getMsg(
                     context.getMeta(),
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightData.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightData.java	Tue Mar 10 17:01:42 2015 +0100
@@ -20,16 +20,23 @@
 
     protected TDoubleArrayList heights;
     protected TDoubleArrayList station;
+    protected TDoubleArrayList data_gap;
+    protected TDoubleArrayList soundingWidth;
+    protected Integer year;
 
     public BedHeightData() {
         heights = new TDoubleArrayList();
         station = new TDoubleArrayList();
+        data_gap = new TDoubleArrayList();
+        soundingWidth = new TDoubleArrayList();
     }
 
     public BedHeightData(String name) {
         super(name);
         heights = new TDoubleArrayList();
         station = new TDoubleArrayList();
+        data_gap = new TDoubleArrayList();
+        soundingWidth = new TDoubleArrayList();
     }
 
     public BedHeightData(int capacity) {
@@ -42,9 +49,20 @@
         station = new TDoubleArrayList(capacity);
     }
 
-    public void add(double value, double station) {
+    public void add(
+        double value,
+        double station,
+        double gap,
+        double sounding,
+        Integer year
+    ) {
         this.heights.add(value);
         this.station.add(station);
+        if (year != null) {
+            this.year = year;
+        }
+        this.data_gap.add(gap);
+        this.soundingWidth.add(sounding);
     }
 
     public int size() {
@@ -82,6 +100,32 @@
         return index >= 0 ? heights.getQuick(index) : Double.NaN;
     }
 
+    public Integer getYear() {
+        return this.year;
+    }
+
+    public double getSoundingWidth(int idx) {
+        return this.soundingWidth.getQuick(idx);
+    }
+
+    public double getDataGap(int idx) {
+        return this.data_gap.getQuick(idx);
+    }
+
+    public double getSoundingWidth(double station) {
+        int index = this.station.indexOf(station);
+        return index >= 0 ? soundingWidth.getQuick(index): Double.NaN;
+    }
+
+    public double getDataGap(double station) {
+        int index = this.station.indexOf(station);
+        return index >= 0 ? data_gap.getQuick(index) : Double.NaN;
+    }
+
+    public double[] getSoundingWidths() {
+        return this.soundingWidth.toNativeArray();
+    }
+
 
     public static void removeNaNs(TDoubleArrayList [] arrays) {
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFacet.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFacet.java	Tue Mar 10 17:01:42 2015 +0100
@@ -19,8 +19,8 @@
 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.model.BedHeightSingle;
-import org.dive4elements.river.model.BedHeightSingleValue;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
 
 public class BedHeightFacet
 extends      BlackboardDataFacet
@@ -52,19 +52,19 @@
         BedHeightAccess access = new BedHeightAccess((D4EArtifact)artifact);
         if (type.equals("singlevalues")) {
             /* Former doc (from BedHeightAccess):
-             * Return a {@link List} of {@link BedHeightSingleValue}s
+             * Return a {@link List} of {@link BedHeightValue}s
              * at the range of the artifact
-             * @return List of {@link BedHeightSingleValue}s */
-            BedHeightSingle single = BedHeightSingle.getBedHeightSingleById(
+             * @return List of {@link BedHeightValue}s */
+            BedHeight single = BedHeight.getBedHeightById(
                     access.getHeightId());
-            List<BedHeightSingleValue> bedheightValues =
-                BedHeightSingleValue.getBedHeightSingleValues(
+            List<BedHeightValue> bedheightValues =
+                BedHeightValue.getBedHeightValues(
                     single,
                     access.getFrom(),
                     access.getTo());
             double[][] values = new double[2][bedheightValues.size()];
             int i = 0;
-            for (BedHeightSingleValue bedheightValue : bedheightValues) {
+            for (BedHeightValue bedheightValue : bedheightValues) {
                 values[0][i] = bedheightValue.getStation();
                 values[1][i] = bedheightValue.getHeight();
                 i++;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFactory.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFactory.java	Tue Mar 10 17:01:42 2015 +0100
@@ -30,13 +30,19 @@
 
     /** Query to get km and ws for wst_id and column_pos. */
     public static final String SQL_SELECT_SINGLE =
-        "SELECT bhsv.height, bhsv.station, bhsv.data_gap, bhsv.sounding_width," +
-        "       bhs.year, bhsv.width" +
+        "SELECT bhsv.height, bhsv.station, bhsv.data_gap," +
+        "       bhsv.sounding_width, bhs.year" +
         "   FROM bed_height_single bhs" +
-        "       JOIN bed_height_single_values bhsv on bhsv.bed_height_single_id = bhs.id" +
+        "       JOIN bed_height_single_values bhsv on bhsv.bed_height_single_id = bhs.id";
+
+    public static final String ID_CLAUSE =
         "   WHERE bhs.id = :height_id" +
         "       ORDER BY bhsv.station";
 
+    public static final String ID_STATION_CLAUSE =
+        "   WHERE bhs.id = :height_id AND" +
+        "         bhsv.station BETWEEN :fromkm AND :tokm" +
+        "       ORDER BY bhsv.station";
 
     /** Query to get name (description) for wst_id. */
     public static final String SQL_SELECT_DESCR_SINGLE =
@@ -46,17 +52,23 @@
     private BedHeightFactory() {
     }
 
-
     /**
      * Get BedHeightData for given type and height_id, caring about the cache.
+     * If from or to are NaN all values are returned. Otherwise only get
+     * values with stations between from and to.
      */
-    public static BedHeightData getHeight(String type, int height_id) {
+    public static BedHeightData getHeight(String type, int height_id, double from, double to) {
         log.debug("BedHeightFactory.getHeight");
         Cache cache = CacheFactory.getCache("bedheight-value-table-static");
 
-        String cacheKey = Integer.toString(height_id);
+        String cacheKey = Integer.toString(height_id) + ":" +
+            Double.toString(from) + ":" + Double.toString(to);
 
         if (cache != null) {
+            /* We could be more intelligent here and reuse cached values for
+             * a complete river and filter the other stations out afterwards.
+             * It might even be better to cache all values first and filter
+             * later. */
             Element element = cache.get(cacheKey);
             if (element != null) {
                 log.debug("Got static bedheight values from cache");
@@ -67,7 +79,7 @@
             cacheKey = null;
         }
 
-        BedHeightData values = getBedHeightUncached(type, height_id);
+        BedHeightData values = getBedHeightUncached(type, height_id, from, to);
 
         if (values != null && cacheKey != null) {
             log.debug("Store static bed height values in cache.");
@@ -77,6 +89,13 @@
         return values;
     }
 
+    /**
+     * Get BedHeightData for given type and height_id, caring about the cache.
+     */
+    public static BedHeightData getHeight(String type, int height_id) {
+        return getHeight(type, height_id, Double.NaN, Double.NaN);
+    }
+
     /** Get name for a BedHeight. */
     public static String getHeightName(String type, int height_id) {
         log.debug("BedHeightFactory.getHeightName height_id/" + height_id);
@@ -104,12 +123,19 @@
 
     /**
      * Get BedHeightData from db.
+     *
+     * If from or to are negative all stations are returned. Otherwise
+     * only the values with a station betweend from and to.
      * @param height_id database id of the bed_height
+     * @param from minimum station value or NaN
+     * @param to maximum station value or NaN
      * @return according BedHeight.
      */
     public static BedHeightData getBedHeightUncached(
         String type,
-        int height_id)
+        int height_id,
+        double from,
+        double to)
     {
         if (log.isDebugEnabled()) {
             log.debug("BedHeightFactory.getBedHeightUncached");
@@ -118,16 +144,25 @@
         Session session = SessionHolder.HOLDER.get();
         SQLQuery sqlQuery = null;
         if (type.equals("single")) {
-            BedHeightSingleData height =
-                new BedHeightSingleData(getHeightName(type, height_id));
-            sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLE)
+            BedHeightData height =
+                new BedHeightData(getHeightName(type, height_id));
+            String queryString = SQL_SELECT_SINGLE;
+            if (Double.isNaN(from) || Double.isNaN(to)) {
+                queryString += ID_CLAUSE;
+            } else {
+                queryString += ID_STATION_CLAUSE;
+            }
+            sqlQuery = session.createSQLQuery(queryString)
                 .addScalar("height", StandardBasicTypes.DOUBLE)
                 .addScalar("station", StandardBasicTypes.DOUBLE)
                 .addScalar("data_gap", StandardBasicTypes.DOUBLE)
                 .addScalar("sounding_width", StandardBasicTypes.DOUBLE)
-                .addScalar("width", StandardBasicTypes.DOUBLE)
                 .addScalar("year", StandardBasicTypes.INTEGER);
             sqlQuery.setInteger("height_id", height_id);
+            if (!Double.isNaN(from) && !Double.isNaN(to)) {
+                sqlQuery.setDouble("fromkm", from);
+                sqlQuery.setDouble("tokm", to);
+            }
             List<Object []> results = sqlQuery.list();
 
             for (Object [] row: results) {
@@ -136,8 +171,7 @@
                 Double row1 = row[1] != null ? (Double)row[1] : Double.NaN;
                 Double row2 = row[2] != null ? (Double)row[2] : Double.NaN;
                 Double row3 = row[3] != null ? (Double)row[3] : Double.NaN;
-                Double row4 = row[4] != null ? (Double)row[4] : Double.NaN;
-                height.add(row0, row1, row2, row3, row4, (Integer) row[5]);
+                height.add(row0, row1, row2, row3, (Integer) row[4]);
             }
             return height;
         }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightSingleData.java	Wed Feb 18 17:17:20 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +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.artifacts.model.minfo;
-
-import gnu.trove.TDoubleArrayList;
-
-
-public class BedHeightSingleData
-extends BedHeightData
-{
-    protected Integer year;
-    protected TDoubleArrayList data_gap;
-    protected TDoubleArrayList soundingWidth;
-    protected TDoubleArrayList width;
-
-    public BedHeightSingleData() {
-        super();
-        data_gap = new TDoubleArrayList();
-        soundingWidth = new TDoubleArrayList();
-        width = new TDoubleArrayList();
-    }
-
-    public BedHeightSingleData(String name) {
-        super(name);
-        data_gap = new TDoubleArrayList();
-        soundingWidth = new TDoubleArrayList();
-        width = new TDoubleArrayList();
-    }
-
-    public void add(
-        double value,
-        double station,
-        double gap,
-        double sounding,
-        double width,
-        Integer year
-    ) {
-        super.add(value, station);
-        if (year != null) {
-            this.year = year;
-        }
-        this.data_gap.add(gap);
-        this.soundingWidth.add(sounding);
-        this.width.add(width);
-    }
-
-    public Integer getYear() {
-        return this.year;
-    }
-
-    public double getSoundingWidth(int idx) {
-        return this.soundingWidth.getQuick(idx);
-    }
-
-    public double getDataGap(int idx) {
-        return this.data_gap.getQuick(idx);
-    }
-
-    public double getSoundingWidth(double station) {
-        int index = this.station.indexOf(station);
-        return index >= 0 ? soundingWidth.getQuick(index): Double.NaN;
-    }
-
-    public double getDataGap(double station) {
-        int index = this.station.indexOf(station);
-        return index >= 0 ? data_gap.getQuick(index) : Double.NaN;
-    }
-
-    public double[] getSoundingWidths() {
-        return this.soundingWidth.toNativeArray();
-    }
-
-    public double getWidth(int ndx) {
-        return width.getQuick(ndx);
-    }
-
-    public double getWidth(double station) {
-        int ndx = this.station.indexOf(station);
-        if (ndx < 0) {
-            return Double.NaN;
-        }
-        return width.get(ndx);
-    }
-}
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightSoundingWidthFacet.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightSoundingWidthFacet.java	Tue Mar 10 17:01:42 2015 +0100
@@ -8,8 +8,8 @@
 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.model.BedHeightSingle;
-import org.dive4elements.river.model.BedHeightSingleValue;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
 
 
 public class BedHeightSoundingWidthFacet
@@ -36,19 +36,19 @@
     public Object getData(Artifact artifact, CallContext context) {
         BedHeightAccess access = new BedHeightAccess((D4EArtifact)artifact);
         /* Former doc (from BedHeightAccess):
-         * Return a {@link List} of {@link BedHeightSingleValue}s
+         * Return a {@link List} of {@link BedHeightValue}s
          * at the range of the artifact
-         * @return List of {@link BedHeightSingleValue}s */
-        BedHeightSingle single = BedHeightSingle.getBedHeightSingleById(
+         * @return List of {@link BedHeightValue}s */
+        BedHeight single = BedHeight.getBedHeightById(
                 access.getHeightId());
-        List<BedHeightSingleValue> bedheightValues =
-            BedHeightSingleValue.getBedHeightSingleValues(
+        List<BedHeightValue> bedheightValues =
+            BedHeightValue.getBedHeightValues(
                 single,
                 access.getFrom(),
                 access.getTo());
         double[][] values = new double[2][bedheightValues.size()];
         int i = 0;
-        for (BedHeightSingleValue bedheightValue : bedheightValues) {
+        for (BedHeightValue bedheightValue : bedheightValues) {
             values[0][i] = bedheightValue.getStation();
             values[1][i] = bedheightValue.getSoundingWidth() != null
                 ? bedheightValue.getSoundingWidth() : Double.NaN;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityCalculation.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedQualityCalculation.java	Tue Mar 10 17:01:42 2015 +0100
@@ -191,11 +191,11 @@
         TDoubleArrayList location = new TDoubleArrayList();
         TDoubleArrayList avDiameterCap = new TDoubleArrayList();
         TDoubleArrayList avDiameterSub = new TDoubleArrayList();
+        QualityMeasurements capFiltered = filterCapMeasurements(qm);
+        QualityMeasurements subFiltered = filterSubMeasurements(qm);
+
         for (double km : kms) {
             //Filter cap and sub measurements.
-            QualityMeasurements capFiltered = filterCapMeasurements(qm);
-            QualityMeasurements subFiltered = filterSubMeasurements(qm);
-
             List<QualityMeasurement> cm = capFiltered.getMeasurements(km);
             List<QualityMeasurement> sm = subFiltered.getMeasurements(km);
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MiddleBedHeightCalculation.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MiddleBedHeightCalculation.java	Tue Mar 10 17:01:42 2015 +0100
@@ -14,8 +14,8 @@
 import org.apache.log4j.Logger;
 
 import org.dive4elements.artifacts.Artifact;
-import org.dive4elements.river.model.BedHeightSingle;
-import org.dive4elements.river.model.BedHeightSingleValue;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
 import org.dive4elements.river.artifacts.access.BedHeightAccess;
 import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
@@ -30,7 +30,7 @@
     public CalculationResult calculate(BedHeightAccess access) {
         log.info("MiddleBedHeightCalculation.calculate");
 
-        int[] singleIds = access.getBedHeightSingleIDs();
+        int[] singleIds = access.getBedHeightIDs();
 
 
         if (log.isDebugEnabled()) {
@@ -42,20 +42,20 @@
             }
         }
 
-        List<BedHeightSingle> singles = getSingles(access, singleIds);
+        List<BedHeight> singles = getSingles(access, singleIds);
 
         return buildCalculationResult(access, singles);
     }
 
 
-    protected List<BedHeightSingle> getSingles(
+    protected List<BedHeight> getSingles(
         BedHeightAccess access,
         int[] ids
     ) {
-        List<BedHeightSingle> singles = new ArrayList<BedHeightSingle>();
+        List<BedHeight> singles = new ArrayList<BedHeight>();
 
         for (int id: ids) {
-            BedHeightSingle s = BedHeightSingle.getBedHeightSingleById(id);
+            BedHeight s = BedHeight.getBedHeightById(id);
 
             if (s != null) {
                 singles.add(s);
@@ -72,7 +72,7 @@
 
     protected CalculationResult buildCalculationResult(
         BedHeightAccess       access,
-        List<BedHeightSingle> singles
+        List<BedHeight> singles
     ) {
         log.info("MiddleBedHeightCalculation.buildCalculationResult");
 
@@ -81,7 +81,7 @@
 
         List<MiddleBedHeightData> data = new ArrayList<MiddleBedHeightData>();
 
-        for (BedHeightSingle single: singles) {
+        for (BedHeight single: singles) {
             MiddleBedHeightData d = prepareSingleData(single, kmLo, kmHi);
 
             if (d != null) {
@@ -97,14 +97,14 @@
 
 
     protected MiddleBedHeightData prepareSingleData(
-        BedHeightSingle single,
+        BedHeight single,
         double kmLo,
         double kmHi
     ) {
         log.debug("Prepare data for single: " + single.getDescription());
 
-        List<BedHeightSingleValue> values =
-            BedHeightSingleValue.getBedHeightSingleValues(single, kmLo, kmHi);
+        List<BedHeightValue> values =
+            BedHeightValue.getBedHeightValues(single, kmLo, kmHi);
 
         int year = single.getYear() != null ? single.getYear() : 0;
 
@@ -127,10 +127,9 @@
             oldElevModel,
             riverElevModel,
             type,
-            locationSystem,
-            single.getSoundingWidth());
+            locationSystem);
 
-        for (BedHeightSingleValue value: values) {
+        for (BedHeightValue value: values) {
             if (value.getHeight() != null) {
                 double uncert = value.getUncertainty() != null ?
                     value.getUncertainty().doubleValue() : Double.NaN;
@@ -143,7 +142,6 @@
                     uncert,
                     sounding,
                     gap,
-                    value.getWidth().doubleValue(),
                     false);
              }
             else {
@@ -152,7 +150,6 @@
                     0,
                     0,
                     0,
-                    0,
                     true);
             }
         }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MiddleBedHeightData.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/MiddleBedHeightData.java	Tue Mar 10 17:01:42 2015 +0100
@@ -38,10 +38,8 @@
     private TDoubleArrayList uncertainty;
     private TDoubleArrayList soundingWidth;
     private TDoubleArrayList dataGap;
-    private TDoubleArrayList width;
     private String type;
     private String locationSystem;
-    private Integer soundWidth;
     private String oldElevationModel;
     private String curElevationModel;
     private String riverElevationModel;
@@ -51,7 +49,7 @@
     protected MiddleBedHeightData(int year, int end, String eval, String desc,
         String curElevationModel, String oldElevationModel,
         String riverElevationModel, String type,
-        String locationSystem, Integer soundingWidth) {
+        String locationSystem) {
         this.year   = year;
         this.evaluatedBy = eval;
         this.description = desc;
@@ -60,25 +58,22 @@
         this.riverElevationModel = riverElevationModel;
         this.type = type;
         this.locationSystem = locationSystem;
-        this.soundWidth = soundingWidth;
 
         this.km            = new TDoubleArrayList();
         this.middleHeight  = new TDoubleArrayList();
         this.uncertainty   = new TDoubleArrayList();
         this.soundingWidth = new TDoubleArrayList();
         this.dataGap       = new TDoubleArrayList();
-        this.width         = new TDoubleArrayList();
         this.empty         = new ArrayList();
     }
 
     public void addAll(double station, double height, double uncertainty,
-        double soundingWidth, double dataGap, double width, boolean isEmpty) {
+        double soundingWidth, double dataGap, boolean isEmpty) {
         addKM(station);
         addMiddleHeight(height);
         addUncertainty(uncertainty);
         addSoundingWidth(soundingWidth);
         addDataGap(dataGap);
-        addWidth(width);
         addIsEmpty(isEmpty);
     }
 
@@ -115,9 +110,6 @@
         return this.locationSystem;
     }
 
-    public String getSoundingWidth() {
-        return this.soundWidth.toString();
-    }
     protected void addKM(double km) {
         this.km.add(km);
     }
@@ -170,15 +162,6 @@
         return (Boolean) empty.get(idx);
     }
 
-
-    protected void addWidth(double width) {
-        this.width.add(width);
-    }
-
-    public double getWidth(int idx) {
-        return width.get(idx);
-    }
-
     public int size() {
         return km.size();
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataCalculation.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadDataCalculation.java	Tue Mar 10 17:01:42 2015 +0100
@@ -176,7 +176,7 @@
         Integer sqTiId = access.getSQTiId();
 
         if (yearEpoch.equals("year")) {
-            years = access.getPeriod();
+            years = access.getYears();
         }
         else if (yearEpoch.equals("epoch") || yearEpoch.equals("off_epoch")) {
             epochs = access.getEpochs();
@@ -240,10 +240,8 @@
 
         SedimentDensity sd = getSedimentDensity();
 
-        int min = Math.min(years[0], years[1]);
-        int max = Math.max(years[0], years[1]);
-
-        for (int year = min; year <= max; ++year) {
+        for (int i = 0; i < years.length; i++) {
+            int year = years[i];
             Value.Filter filter = new And(notEpochs)
                 .add(new TimeRangeIntersects(year)).add(sqTiFilter);
             String period = Integer.toString(year);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/LogSQ.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/LogSQ.java	Tue Mar 10 17:01:42 2015 +0100
@@ -8,6 +8,8 @@
 
 package org.dive4elements.river.artifacts.model.sq;
 
+import java.util.Date;
+
 public class LogSQ extends SQ {
 
     public static final View LOG_SQ_VIEW = new View() {
@@ -20,12 +22,17 @@
         public double getQ(SQ sq) {
             return ((LogSQ)sq).getLogQ();
         }
+
+        @Override
+        public Date getDate(SQ sq) {
+            return sq.getDate();
+        }
     };
 
     public static final Factory LOG_SQ_FACTORY = new Factory() {
         @Override
-        public SQ createSQ(double s, double q) {
-            return new LogSQ(s, q);
+        public SQ createSQ(double s, double q, Date d) {
+            return new LogSQ(s, q, d);
         }
     };
 
@@ -37,8 +44,8 @@
     public LogSQ() {
     }
 
-    public LogSQ(double s, double q) {
-        super(s, q);
+    public LogSQ(double s, double q, Date d) {
+        super(s, q, d);
     }
 
     /** important: We cannot process negative s/q. */
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurement.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurement.java	Tue Mar 10 17:01:42 2015 +0100
@@ -10,6 +10,7 @@
 
 import java.util.List;
 import java.util.Map;
+import java.util.Date;
 
 import org.apache.log4j.Logger;
 
@@ -109,6 +110,10 @@
         return S_SS() + S_BL_S() + S_BL_FG() + S_BL_CG();
     }
 
+    public Date getDate() {
+        return  (Date)data.get("DATUM");
+    }
+
     @Override
     public String toString() {
         return "Measurement: " + data;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java	Tue Mar 10 17:01:42 2015 +0100
@@ -46,7 +46,8 @@
         "SELECT " +
             "m.Q_BPEGEL AS Q_BPEGEL,"+
             "m.TSCHWEB  AS TSCHWEB," +
-            "m.TSAND    AS TSAND " +
+            "m.TSAND    AS TSAND, " +
+            "m.DATUM    AS DATUM " +
         "FROM MESSUNG m " +
             "JOIN STATION   s ON m.STATIONID   = s.STATIONID " +
             "JOIN GEWAESSER r ON s.GEWAESSERID = r.GEWAESSERID " +
@@ -257,18 +258,13 @@
         SQ.Factory sqFactory
     ) {
         Session session = SedDBSessionHolder.HOLDER.get();
-        try {
-            List<Measurement> totals = loadTotals(
-                session, river, location, dateRange);
+        List<Measurement> totals = loadTotals(
+            session, river, location, dateRange);
 
-            List<Measurement> accumulated = loadFractions(
-                session, river, location, dateRange);
+        List<Measurement> accumulated = loadFractions(
+            session, river, location, dateRange);
 
-            return new Measurements(totals, accumulated, sqFactory);
-        }
-        finally {
-            session.close();
-        }
+        return new Measurements(totals, accumulated, sqFactory);
     }
 
     @SuppressWarnings("unchecked")
@@ -281,7 +277,8 @@
         SQLQuery query = session.createSQLQuery(SQL_TOTALS)
             .addScalar("Q_BPEGEL", StandardBasicTypes.DOUBLE)
             .addScalar("TSCHWEB",  StandardBasicTypes.DOUBLE)
-            .addScalar("TSAND",    StandardBasicTypes.DOUBLE);
+            .addScalar("TSAND",    StandardBasicTypes.DOUBLE)
+            .addScalar("DATUM",    StandardBasicTypes.DATE);
 
         query.setString("river_name", river);
         query.setDouble("location", location);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java	Tue Mar 10 17:01:42 2015 +0100
@@ -99,7 +99,8 @@
         List<SQ> result = new ArrayList<SQ>(measuments.size());
         int invalid = 0;
         for (Measurement measument: measuments) {
-            SQ sq = sqFactory.createSQ(extractor.getS(measument), measument.Q());
+            SQ sq = sqFactory.createSQ(extractor.getS(measument), measument.Q(),
+                    measument.getDate());
             if (sq.isValid()) {
                 result.add(sq);
             }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java	Tue Mar 10 17:01:42 2015 +0100
@@ -10,24 +10,27 @@
 
 import java.io.Serializable;
 
+import java.util.Date;
+
 
 /** Represents S/Q pairs. They are immutable! */
 public class SQ implements Serializable {
 
     public interface Factory {
-        SQ createSQ(double s, double q);
+        SQ createSQ(double s, double q, Date d);
     }
 
     public static final Factory SQ_FACTORY = new Factory() {
         @Override
-        public SQ createSQ(double s, double q) {
-            return new SQ(s, q);
+        public SQ createSQ(double s, double q, Date d) {
+            return new SQ(s, q, d);
         }
     };
 
     public interface View {
         double getS(SQ sq);
         double getQ(SQ sq);
+        Date getDate(SQ sq);
     }
 
     public static final View SQ_VIEW = new View() {
@@ -40,17 +43,24 @@
         public double getQ(SQ sq) {
             return sq.getQ();
         }
+
+        @Override
+        public Date getDate(SQ sq) {
+            return sq.getDate();
+        }
     };
 
     protected double s;
     protected double q;
+    protected Date d;
 
     public SQ() {
     }
 
-    public SQ(double s, double q) {
+    public SQ(double s, double q, Date d) {
         this.s = s;
         this.q = q;
+        this.d = d;
     }
 
 
@@ -62,6 +72,10 @@
         return q;
     }
 
+    public Date getDate() {
+        return d;
+    }
+
     public boolean isValid() {
         return !Double.isNaN(s) && !Double.isNaN(q);
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQFactory.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/StaticSQFactory.java	Tue Mar 10 17:01:42 2015 +0100
@@ -28,6 +28,17 @@
     private static final Logger log =
         Logger.getLogger(StaticSQFactory.class);
 
+    public static final String SQL_STATIONS_AT_RANGE =
+        "SELECT "+
+            "ms.id AS ms_id " +
+        "FROM measurement_station ms " +
+            "JOIN ranges ra ON ra.id = ms.range_id " +
+            "JOIN rivers r ON r.id = ra.river_id " +
+            "WHERE r.name = :river AND " +
+            "ms.range_id = (SELECT range_id " +
+                           "FROM measurement_station " +
+                           "WHERE id = :ms_id)";
+
     public static final String SQL_SQ =
         "SELECT " +
             "sq.description AS description,"+
@@ -63,6 +74,69 @@
     private StaticSQFactory() {
     }
 
+    /** Get SQ relations for a measurement station's location.
+     * Returns all SQRelations for the location of the station and
+     * not just for the station. E.g. for a "Geschiebemessstelle"
+     * and a "Schwebstoffmesstelle" at the same place.*/
+    public static StaticSQContainer getSQRelationsForLocation(
+        String river,
+        int measurementStation
+    ) {
+        Session session = SessionHolder.HOLDER.get();
+        Query query = session.createSQLQuery(SQL_STATIONS_AT_RANGE)
+            .setParameter("river", river)
+            .setParameter("ms_id", measurementStation);
+        /* Take the first container for the station requested. */
+        StaticSQContainer retval = getSQRelations(river, measurementStation);
+
+        /* And some others */
+        List<Integer> list = query.list();
+        if (list == null || list.isEmpty()) {
+            log.error("Did not even find one measurement station. Broken Query?");
+            return retval;
+        }
+
+        if (list.size() > 2) {
+            log.error("More then two measurement stations found at the same range. Bad Data!");
+            return retval;
+        }
+
+        for (Integer stationId: list) {
+            log.debug("Collecting SQ Relations for: "+ stationId);
+            if (stationId == measurementStation) {
+                /* Skip the same station */
+                continue;
+            }
+
+            StaticSQContainer additional = getSQRelations(river, stationId);
+            if (additional == null || additional.getSQRelations() == null) {
+                continue;
+            }
+
+            if (retval == null || retval.getSQRelations() == null || retval.getSQRelations().isEmpty()) {
+                /* Old one is empty, just take the new one. */
+                retval = additional;
+                continue;
+            }
+
+            for (StaticSQRelation rel: additional.getSQRelations()) {
+                /* Check if we already have one for this parameter.
+                 * This is highly unlikely in the data scheme of things. */
+                List<StaticSQRelation> old = retval.getRelationsByParameter(
+                        rel.getParameter());
+                if (old != null || !old.isEmpty()) {
+                    log.warn("Multiple SQ relation Parameters found for different " +
+                             "measurement_stations at the same range. This should not happen.");
+                    continue;
+                }
+                retval.addSQRelation(rel);
+            }
+
+        }
+        return retval;
+    }
+
+
     public static StaticSQContainer getSQRelations(
         String river,
         int measurementStation
@@ -75,7 +149,7 @@
             cacheKey = new StaticSQCacheKey(river, measurementStation);
             Element element = cache.get(cacheKey);
             if (element != null) {
-                log.debug("Got static bedheight values from cache");
+                log.debug("Got static sq relations from cache");
                 return (StaticSQContainer)element.getValue();
             }
         }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/AbstractChartService.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/AbstractChartService.java	Tue Mar 10 17:01:42 2015 +0100
@@ -76,11 +76,9 @@
     protected abstract JFreeChart createChart(Document data,
         GlobalContext globalContext, CallMeta callMeta);
 
-    protected void init() {
-    };
+    protected abstract void init();
 
-    protected void finish() {
-    };
+    protected abstract void finish();
 
     @Override
     public Service.Output process(Document data, GlobalContext globalContext,
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedKMChartService.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedKMChartService.java	Tue Mar 10 17:01:42 2015 +0100
@@ -134,7 +134,6 @@
             return doProcess(data, globalContext, callMeta);
         }
         finally {
-            SedDBSessionHolder.HOLDER.get().close();
             SedDBSessionHolder.release();
         }
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedloadKMChartService.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/BedloadKMChartService.java	Tue Mar 10 17:01:42 2015 +0100
@@ -134,7 +134,6 @@
             return doProcess(data, globalContext, callMeta);
         }
         finally {
-            SedDBSessionHolder.HOLDER.get().close();
             SedDBSessionHolder.release();
         }
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/D4EService.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/D4EService.java	Tue Mar 10 17:01:42 2015 +0100
@@ -60,9 +60,6 @@
     /** Called when processing done, close session. */
     protected void shutdown() {
         log.debug("shutdown");
-        Session session = SessionHolder.HOLDER.get();
-        session.close();
-
         SessionHolder.release();
     }
 }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeTablesOverview.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeTablesOverview.java	Tue Mar 10 17:01:42 2015 +0100
@@ -18,7 +18,6 @@
 import java.util.Locale;
 
 import org.apache.log4j.Logger;
-import org.hibernate.Session;
 import org.jfree.chart.ChartFactory;
 import org.jfree.chart.JFreeChart;
 import org.jfree.chart.plot.Marker;
@@ -68,19 +67,15 @@
     public static final DateFormat DATE_FORMAT = DateFormat.getDateInstance(
         DateFormat.SHORT, Locale.GERMANY);
 
-    private Session session;
 
     @Override
     protected void init() {
-        session = SessionHolder.acquire();
+        SessionHolder.acquire();
     }
 
     @Override
     protected void finish() {
-        if (session != null) {
-            session.close();
-            SessionHolder.release();
-        }
+        SessionHolder.release();
     }
 
     protected JFreeChart createChart(Document data,
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/FixingsKMChartService.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/FixingsKMChartService.java	Tue Mar 10 17:01:42 2015 +0100
@@ -193,7 +193,6 @@
             return doProcess(data, globalContext, callMeta);
         }
         finally {
-            SessionHolder.HOLDER.get().close();
             SessionHolder.release();
         }
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/SQKMChartService.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/SQKMChartService.java	Tue Mar 10 17:01:42 2015 +0100
@@ -147,7 +147,6 @@
             return doProcess(data, globalContext, callMeta);
         }
         finally {
-            SedDBSessionHolder.HOLDER.get().close();
             SedDBSessionHolder.release();
         }
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/SoundingsSelect.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/SoundingsSelect.java	Tue Mar 10 17:01:42 2015 +0100
@@ -18,7 +18,7 @@
 import org.dive4elements.artifacts.common.model.KVP;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
-import org.dive4elements.river.model.BedHeightSingle;
+import org.dive4elements.river.model.BedHeight;
 import org.dive4elements.river.model.River;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.resources.Resources;
@@ -120,8 +120,8 @@
         Element select,
         CallContext context
     ) {
-        List<BedHeightSingle> singles =
-            BedHeightSingle.getBedHeightSingles(river, kmLo, kmHi);
+        List<BedHeight> singles =
+            BedHeight.getBedHeights(river, kmLo, kmHi);
 
         if (singles != null) {
             int size = singles.size();
@@ -130,7 +130,7 @@
 
             NumberFormat nf = Formatter.getCalculationKm(context.getMeta());
             for (int i = 0; i < size; i++) {
-                BedHeightSingle s = singles.get(i);
+                BedHeight s = singles.get(i);
 
                 String id    = PREFIX_SINGLE + s.getId();
                 String value = s.getDescription();
@@ -204,7 +204,7 @@
     protected String getLabelForSingle(CallContext cc, String value) {
         String id = value.replace(PREFIX_SINGLE, "");
         try {
-            BedHeightSingle s = BedHeightSingle.getBedHeightSingleById(
+            BedHeight s = BedHeight.getBedHeightById(
                 Integer.parseInt(id));
 
             if (s != null) {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Tue Mar 10 17:01:42 2015 +0100
@@ -19,6 +19,7 @@
 
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.river.artifacts.access.RangeAccess;
 import org.dive4elements.river.artifacts.ChartArtifact;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.FixationArtifact;
@@ -108,25 +109,12 @@
     /**
      * Access the data (wkms) of an artifact, coded in mingle.
      */
-    public WKms getWKms(String mingle, CallContext context) {
+    public WKms getWKms(String mingle, CallContext context, double from, double to) {
         log.debug("WDifferencesState.getWKms " + mingle);
         String[] def  = mingle.split(";");
         String   uuid = def[0];
         String   name = def[1];
         int      idx  = Integer.parseInt(def[2]);
-
-        if (name.startsWith("staticwkms")) {
-            StaticWKmsArtifact staticWKms =
-                (StaticWKmsArtifact) RiverUtils.getArtifact(
-                    uuid,
-                    context);
-            log.debug("WDifferencesState obtain data from StaticWKms");
-            WKms wkms = staticWKms.getWKms(idx);
-            if (wkms == null)
-                log.error("No WKms from artifact.");
-            return wkms;
-        }
-
         D4EArtifact d4eArtifact = RiverUtils.getArtifact(
             uuid,
             context);
@@ -136,7 +124,17 @@
             return null;
         }
 
-        if (d4eArtifact instanceof WINFOArtifact) {
+        WKms retval = null;
+        if (d4eArtifact instanceof StaticWKmsArtifact) {
+            StaticWKmsArtifact staticWKms = (StaticWKmsArtifact) d4eArtifact;
+            log.debug("WDifferencesState obtain data from StaticWKms");
+            WKms wkms = staticWKms.getWKms(idx, 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 */
+        } else if (d4eArtifact instanceof WINFOArtifact) {
             log.debug("Get WKms from WINFOArtifact");
             WINFOArtifact flys = (WINFOArtifact) d4eArtifact;
 
@@ -147,25 +145,32 @@
             }
             else if (wkms.length < idx+1) {
                 log.warn("Not enough waterlevels in artifact.");
-                return new WQKms();
+                retval = new WQKms();
             }
-            return wkms[idx];
-        }
-        else if (d4eArtifact instanceof MINFOArtifact) {
-            log.debug("Get WKms from MINFOArtifact");
-            CalculationResult r = (CalculationResult)
-                d4eArtifact.compute(context, ComputeType.ADVANCE, false);
-        }
-        else if (d4eArtifact instanceof FixationArtifact) {
+            retval = wkms[idx];
+        } else if (d4eArtifact instanceof MINFOArtifact) {
+            log.warn("Get WKms from MINFOArtifact not implemented!");
+//            CalculationResult r = (CalculationResult)
+//                d4eArtifact.compute(context, ComputeType.ADVANCE, false);
+        } else if (d4eArtifact instanceof FixationArtifact) {
             log.debug ("Get WKms from FixationArtifact.");
             CalculationResult r = (CalculationResult)
                 d4eArtifact.compute(context, ComputeType.ADVANCE, false);
             FixRealizingResult frR = (FixRealizingResult) r.getData();
-            return frR.getWQKms()[idx];
+            retval = frR.getWQKms()[idx];
         }
 
-        log.error("Do not know how to handle (getWKms) minuend/subtrahend");
-        return null;
+
+        if (retval == null) {
+            log.error("Do not know how to handle (getWKms) minuend/subtrahend");
+        } else if (!Double.isNaN(from) && !Double.isNaN(to)) {
+            /* Filter out only the relevant data points for calulation results.*/
+            log.debug("Before filter: " + retval.size());
+            retval = retval.filteredKms(from, to);
+            log.debug("After filter: " + retval.size());
+        }
+
+        return retval;
     }
 
 
@@ -188,7 +193,9 @@
         }
         WINFOArtifact winfo = (WINFOArtifact) artifact;
         String id = getID();
-
+        RangeAccess rangeAccess = new RangeAccess(artifact);
+        double from = rangeAccess.getFrom();
+        double to = rangeAccess.getTo();
         // Load the Artifacts/facets that we want to subtract and display.
         // Expected format is:
         // [42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;0]#[1231f2-....]
@@ -213,9 +220,9 @@
             // e.g.:
             // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1
             WKms minuendWKms = getWKms(StringUtil.unbracket(datas[i+0]),
-                context);
+                context, from, to);
             WKms subtrahendWKms = getWKms(StringUtil.unbracket(datas[i+1]),
-                context);
+                context, from, to);
 
             String facetName = "diff ()";
             String minName = "min";
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadYearSelect.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadYearSelect.java	Tue Mar 10 17:01:42 2015 +0100
@@ -47,7 +47,7 @@
         SedimentLoadAccess access = new SedimentLoadAccess((D4EArtifact) artifact);
 
         // Second year should be later than first.
-        if (access.getPeriod() != null && access.getPeriod()[1] < access.getPeriod()[0])
+        if (access.getYears() != null && access.getYears()[1] < access.getYears()[0])
            throw new IllegalArgumentException("error_years_wrong");
 
         return true;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/SQStaticState.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/sq/SQStaticState.java	Tue Mar 10 17:01:42 2015 +0100
@@ -68,7 +68,7 @@
         }
         log.debug("Parsed measurement station: " + ms);
 
-        sqRelations = StaticSQFactory.getSQRelations(river, ms);
+        sqRelations = StaticSQFactory.getSQRelationsForLocation(river, ms);
         DateFormat df = new SimpleDateFormat("yyyy");
 
         for (StaticSQRelation.Parameter p: StaticSQRelation.Parameter.values()) {
@@ -143,7 +143,7 @@
             }
             log.debug("Parsed measurement station: " + ms);
 
-            sqRelations = StaticSQFactory.getSQRelations(river, ms);
+            sqRelations = StaticSQFactory.getSQRelationsForLocation(river, ms);
         }
 
         DateFormat df = new SimpleDateFormat("yyyy");
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DischargeGenerator.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DischargeGenerator.java	Tue Mar 10 17:01:42 2015 +0100
@@ -26,6 +26,10 @@
 
     private String I18N_AXIS_LABEL = "chart.discharge.curve.yaxis.cm.label";
 
+    private int wAxisIndex;
+    private int wInCmAxisIndex;
+    double pnpValue;
+
     public DischargeGenerator() {
     }
 
@@ -38,9 +42,9 @@
             return;
         }
 
-        double pnpValue = ((Number)pnp).doubleValue();
+        pnpValue = ((Number)pnp).doubleValue();
 
-        int wAxisIndex = diagramAttributes.getAxisIndex("W");
+        wAxisIndex = diagramAttributes.getAxisIndex("W");
         if (wAxisIndex == -1) {
             log.warn("No W axis found.");
             return;
@@ -67,7 +71,7 @@
         NumberAxis wInCmAxis = createWinCMAxis(wAxisIndex);
         wInCmAxis.setRange(axisRange);
 
-        int wInCmAxisIndex = plot.getRangeAxisCount();
+        wInCmAxisIndex = plot.getRangeAxisCount();
         plot.setRangeAxis(wInCmAxisIndex, wInCmAxis);
         combineYBounds(new DoubleBounds(dataRange), wInCmAxisIndex);
     }
@@ -100,5 +104,24 @@
 
         return axis;
     }
+
+     /** We need to override this to keep both axis synced. */
+    @Override
+    protected void autoZoom(XYPlot plot) {
+        super.autoZoom(plot);
+        IdentifiableNumberAxis idA = (IdentifiableNumberAxis) plot.getRangeAxis(wAxisIndex);
+        Range fixedRange = getRangeForAxisFromSettings(idA.getId());
+        if (fixedRange == null) {
+            return;
+        }
+        log.debug("Adjusting helper centimeter axis to fixed range.");
+        Range adjustedRange = inCm(
+            fixedRange,
+            pnpValue
+        );
+        IdentifiableNumberAxis wInCmAxis=
+            (IdentifiableNumberAxis) plot.getRangeAxis(wInCmAxisIndex);
+        wInCmAxis.setRange(adjustedRange);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightExporter.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightExporter.java	Tue Mar 10 17:01:42 2015 +0100
@@ -57,9 +57,6 @@
     public static final String CSV_SOUNDING_WIDTH =
         "export.bedheight_middle.csv.header.soundingwidth";
 
-    public static final String CSV_WIDTH =
-        "export.bedheight_middle.csv.header.width";
-
     public static final String CSV_LOCATIONS =
         "export.bedheight_middle.csv.header.locations";
 
@@ -78,9 +75,6 @@
     public static final String CSV_META_RIVER_ELEV_MODEL =
         "meta.bedheight.river.elevation";
 
-    public static final String CSV_META_SOUNDING_WIDTH =
-        "meta.bedheight.sounding.width";
-
     public static final String CSV_META_RANGE =
         "meta.bedheight.range";
 
@@ -131,14 +125,13 @@
         River river = RiverUtils.getRiver((D4EArtifact) master);
         String riverUnit = river.getWstUnit().getName();
         writer.writeNext(new String[] {
-            msg(CSV_KM, CSV_KM),
-            msg(CSV_SOUNDING, CSV_SOUNDING),
-            msg(CSV_HEIGHT, CSV_HEIGHT, new Object[] {riverUnit}),
-            msg(CSV_UNCERTAINTY, CSV_UNCERTAINTY),
-            msg(CSV_DATA_GAP, CSV_DATA_GAP),
-            msg(CSV_SOUNDING_WIDTH, CSV_SOUNDING_WIDTH),
-            msg(CSV_WIDTH, CSV_WIDTH),
-            msg(CSV_LOCATIONS, CSV_LOCATIONS)
+            msg(CSV_KM),
+            msg(CSV_SOUNDING),
+            msg(CSV_HEIGHT, new Object[] {riverUnit}),
+            msg(CSV_UNCERTAINTY),
+            msg(CSV_DATA_GAP),
+            msg(CSV_SOUNDING_WIDTH),
+            msg(CSV_LOCATIONS)
         });
     }
 
@@ -155,7 +148,6 @@
         NumberFormat uncertF = Formatter.getMiddleBedHeightUncert(context);
         NumberFormat gapF    = Formatter.getMiddleBedHeightDataGap(context);
         NumberFormat soundF  = Formatter.getMiddleBedHeightSounding(context);
-        NumberFormat widthF  = Formatter.getMiddleBedHeightWidth(context);
 
         heightF.setMaximumFractionDigits(1);
         soundF.setMaximumFractionDigits(1);
@@ -180,7 +172,6 @@
                     uncert,
                     gap,
                     sound,
-                    widthF.format(data.getWidth(i)),
                     RiverUtils.getLocationDescription(flys, data.getKM(i)),
                 });
         }
@@ -203,7 +194,6 @@
                      data.getOldElevationModel(),
                  msg(CSV_META_RIVER_ELEV_MODEL) + ": " +
                      data.getRiverElevationModel(),
-                 msg(CSV_META_SOUNDING_WIDTH) + ": " + data.getSoundingWidth(),
                  msg(CSV_META_RANGE) + ": " + data.getStations().min() +
                      " - " + data.getStations().max(),
                  msg(CSV_META_EVAL_BY) + ": " + data.getEvaluatedBy()
@@ -212,7 +202,7 @@
 
     @Override
     protected void writePDF(OutputStream out) {
-        log.error("TODO: Implement FlowVelocityExporter.writePDF");
+        log.error("TODO: Implement MiddleBedHeightExporter.writePDF");
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/SQRelationProcessor.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/SQRelationProcessor.java	Tue Mar 10 17:01:42 2015 +0100
@@ -9,15 +9,23 @@
 package org.dive4elements.river.exports.process;
 
 import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.text.DateFormat;
 
 import org.apache.log4j.Logger;
 
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.exports.DiagramGenerator;
 import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.jfree.RiverAnnotation;
 import org.dive4elements.river.themes.ThemeDocument;
 import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation;
+import org.jfree.chart.annotations.XYTextAnnotation;
 
 import org.dive4elements.river.jfree.JFreeUtil;
 
@@ -70,14 +78,29 @@
 
             SQ[] sqs = (SQ[]) data;
             series = new StyledXYSeries(desc, theme);
+            List<XYTextAnnotation> xy = new ArrayList<XYTextAnnotation>();
+
+            DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT,
+                Resources.getLocale(context.getMeta()));
 
             for (SQ sq: sqs) {
                 double q = sq.getQ();
                 double s = sq.getS();
                 if (s > 0d && q > 0d) {
                     series.add(q, s, false);
+                    // Annotate with measurement date
+                    if (sq.getDate() != null) {
+                        xy.add(new CollisionFreeXYTextAnnotation(dateFormat.format(sq.getDate()), q, s));
+                    }
                 }
             }
+
+            if (visible && theme.parseShowPointLabel()) {
+
+                RiverAnnotation annotation = new RiverAnnotation("Messdatum", null, null, theme);
+                annotation.setTextAnnotations(xy);
+                generator.addAnnotations(annotation);
+            }
         } else {
             log.error("Could not handle: " + facetName);
             return;
--- a/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java	Tue Mar 10 17:01:42 2015 +0100
@@ -30,6 +30,7 @@
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.sq.SQFractionResult;
 import org.dive4elements.river.artifacts.model.sq.SQResult;
+import org.dive4elements.river.artifacts.model.sq.SQ;
 import org.dive4elements.river.artifacts.model.sq.SQRelationJRDataSource;
 import org.dive4elements.river.artifacts.model.Parameters;
 import org.dive4elements.river.artifacts.model.DateRange;
@@ -102,6 +103,15 @@
     public static final String INFO_PARAM_F =
         "export.sqrelation.csv.info.param.f";
 
+    public static final String INFO_Q =
+        "export.sqrelation.csv.info.q";
+
+    public static final String INFO_S_KG =
+        "export.sqrelation.csv.info.s_kg";
+
+    public static final String INFO_DATE =
+        "export.sqrelation.csv.info.date";
+
     public static final String CSV_PARAMETER =
         "export.sqrelation.csv.header.parameter";
 
@@ -147,6 +157,15 @@
     public static final String CSV_SD =
         "export.sqrelation.csv.header.sd";
 
+    public static final String CSV_S_KG =
+        "export.sqrelation.csv.header.s_kg";
+
+    public static final String CSV_Q =
+        "export.sqrelation.csv.header.q";
+
+    public static final String CSV_DATE =
+        "export.sqrelation.csv.header.date";
+
     public static final String PDF_TITLE=
         "export.sqrelation.pdf.title";
 
@@ -184,7 +203,10 @@
             msg(CSV_N_TOTAL),
             msg(CSV_N_OUTLIERS),
             msg(CSV_C_DUAN),
-            msg(CSV_C_FERGUSON)
+            msg(CSV_C_FERGUSON),
+            msg(CSV_S_KG),
+            msg(CSV_Q),
+            msg(CSV_DATE)
         });
     }
 
@@ -207,7 +229,10 @@
                 msg(INFO_PARAM_C),
                 msg(INFO_PARAM_D),
                 msg(INFO_PARAM_E),
-                msg(INFO_PARAM_F)
+                msg(INFO_PARAM_F),
+                msg(INFO_S_KG),
+                msg(INFO_Q),
+                msg(INFO_DATE)
             });
 
         writeCSVHeader(writer);
@@ -229,6 +254,8 @@
         NumberFormat fThreeFormatter = Formatter.getFormatter(context, 3, 3);
         NumberFormat fTwoFormatter = Formatter.getFormatter(context, 2, 2);
         NumberFormat fZeroFormatter = Formatter.getFormatter(context, 0, 0);
+        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT,
+                Resources.getLocale(context.getMeta()));
 
         for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) {
             SQFractionResult fraction = result.getFraction(i);
@@ -256,19 +283,25 @@
             o  = String.valueOf(fraction.totalNumOutliers());
             t  = String.valueOf(fraction.numMeasurements());
 
-            retval.add(new String[] {
-                km,
-                name,
-                a,
-                b,
-                sd, // 4
-                max_q, // 5
-                r2, // 6
-                t, // 7
-                o, // 8
-                c_duan, // 9
-                c_ferguson // 10
-            });
+            for (SQ sq: fraction.getMeasurements()) {
+                retval.add(new String[] {
+                    km,
+                    name,
+                    a,
+                    b,
+                    sd, // 4
+                    max_q, // 5
+                    r2, // 6
+                    t, // 7
+                    o, // 8
+                    c_duan, // 9
+                    c_ferguson, // 10
+                    sqAFormatter.format(sq.getS()),
+                    fZeroFormatter.format(sq.getQ()),
+                    df.format(sq.getDate())
+                });
+            }
+
         }
         return retval;
     }
--- a/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java	Tue Mar 10 17:01:42 2015 +0100
@@ -415,13 +415,6 @@
     }
 
 
-    public static NumberFormat getMiddleBedHeightWidth(CallContext context) {
-        return getFormatter(
-                context,
-                MIDDLE_BED_HEIGHT_WIDTH_MIN_DIGITS,
-                MIDDLE_BED_HEIGHT_WIDTH_MAX_DIGITS);
-    }
-
     public static NumberFormat getFixDeltaWKM(CallContext context) {
         return getFormatter(
                 context,
--- a/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java	Tue Mar 10 17:01:42 2015 +0100
@@ -742,9 +742,9 @@
                 // e.g.:
                 // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1
                 WKms minuendWKms = wState.getWKms(StringUtil.unbracket(datas[i+0]),
-                    context);
+                    context, 0, 0);
                 WKms subtrahendWKms = wState.getWKms(StringUtil.unbracket(datas[i+1]),
-                    context);
+                    context, 0, 0);
                 if (minuendWKms != null && subtrahendWKms != null) {
                     diffs += StringUtil.wWrap(minuendWKms.getName())
                         + " - " + StringUtil.wWrap(subtrahendWKms.getName());
--- a/artifacts/src/main/resources/messages.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/resources/messages.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -44,6 +44,7 @@
 
 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
@@ -230,7 +231,6 @@
 meta.bedheight.type = Type
 meta.bedheight.cur.elevation = Current elevation model
 meta.bedheight.old.elevation = Old elevation model
-meta.bedheight.sounding.width = Sounding width
 meta.bedheight.range = Range
 meta.bedheight.location.system = Location system
 meta.bedheight.evalby = Evaluated by
@@ -430,7 +430,6 @@
 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.width = morphological active width [m]
 export.bedheight_middle.csv.header.locations = Location
 
 export.sedimentload.csv.header.coarse = Coarse gravel [{0}]
@@ -458,6 +457,9 @@
 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 = Discharge in [m\u00b3/s] as measured on measurement date
+export.sqrelation.csv.info.s_kg = Transport in [kg/s] as measured on measurement date
+export.sqrelation.csv.info.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
@@ -473,6 +475,9 @@
 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.pdf.mode = Load Discharge Relation
 export.minfo.bedquality.km = km
@@ -605,6 +610,7 @@
 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
--- a/artifacts/src/main/resources/messages_de.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/resources/messages_de.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -44,6 +44,7 @@
 
 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
@@ -230,7 +231,6 @@
 meta.bedheight.type = Aufnahmeart
 meta.bedheight.cur.elevation = H\u00f6hensystem
 meta.bedheight.old.elevation = urspr\u00fcngliches H\u00f6hensystem
-meta.bedheight.sounding.width = ausgewertete Peilbreite
 meta.bedheight.range = Strecke
 meta.bedheight.location.system = Lagesystem
 meta.bedheight.evalby = Auswerter
@@ -432,7 +432,6 @@
 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.width = morphologisch ausgewertete Breite [m]
 export.bedheight_middle.csv.header.locations = Streckendaten
 
 export.sedimentload.csv.header.coarse = Grober Kies/Steine [{0}]
@@ -460,6 +459,9 @@
 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 = Am Messdatum gemessener Abfluss in [m\u00b3/s]
+export.sqrelation.csv.info.s_kg = Am Messdatum gemessener Transport in [kg/s]
+export.sqrelation.csv.info.date = Datum dieser Messung
 export.sqrelation.csv.header.parameter = Parameter
 export.sqrelation.csv.header.station = Station
 export.sqrelation.csv.header.km = Fluss-Km
@@ -475,6 +477,9 @@
 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.pdf.mode = Transport-Abfluss Beziehung
 export.minfo.bedquality.km = km
@@ -609,6 +614,7 @@
 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
--- a/artifacts/src/main/resources/messages_de_DE.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/resources/messages_de_DE.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -44,6 +44,7 @@
 
 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
@@ -228,7 +229,6 @@
 meta.bedheight.type = Aufnahmeart
 meta.bedheight.cur.elevation = H\u00f6hensystem
 meta.bedheight.old.elevation = urspr\u00fcngliches H\u00f6hensystem
-meta.bedheight.sounding.width = ausgewertete Peilbreite
 meta.bedheight.range = Strecke
 meta.bedheight.location.system = Lagesystem
 meta.bedheight.evalby = Auswerter
@@ -428,7 +428,6 @@
 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.width = morphologisch ausgewertete Breite [m]
 export.bedheight_middle.csv.header.locations = Streckendaten
 
 export.sedimentload.csv.header.coarse = Grober Kies/Steine [{0}]
@@ -456,6 +455,9 @@
 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 = Am Messdatum gemessener Abfluss in [m\u00b3/s]
+export.sqrelation.csv.info.s_kg = Am Messdatum gemessener Transport in [kg/s]
+export.sqrelation.csv.info.date = Datum dieser Messung
 export.sqrelation.csv.header.parameter = Parameter
 export.sqrelation.csv.header.station = Station
 export.sqrelation.csv.header.km = Fluss-Km
@@ -471,6 +473,9 @@
 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.pdf.mode = Transport-Abfluss Beziehung
 export.minfo.bedquality.km = km
@@ -604,6 +609,7 @@
 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
--- a/artifacts/src/main/resources/messages_en.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/artifacts/src/main/resources/messages_en.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -44,6 +44,7 @@
 
 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
@@ -232,7 +233,6 @@
 meta.bedheight.type = Type
 meta.bedheight.cur.elevation = Current elevation model
 meta.bedheight.old.elevation = Old elevation model
-meta.bedheight.sounding.width = Sounding width
 meta.bedheight.range = Range
 meta.bedheight.location.system = Location system
 meta.bedheight.evalby = Evaluated by
@@ -432,7 +432,6 @@
 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.width = morphological active width [m]
 export.bedheight_middle.csv.header.locations = Location
 
 export.sedimentload.csv.header.coarse = Coarse gravel [{0}]
@@ -460,6 +459,9 @@
 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 = Discharge in [m\u00b3/s] as measured on measurement date
+export.sqrelation.csv.info.s_kg = Transport in [kg/s] as measured on measurement date
+export.sqrelation.csv.info.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
@@ -475,6 +477,9 @@
 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.pdf.mode = Load Discharge Relation
 export.minfo.bedquality.km = km
@@ -608,6 +613,7 @@
 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
--- a/backend/doc/documentation/de/importer-hydr-morph.tex	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/doc/documentation/de/importer-hydr-morph.tex	Tue Mar 10 17:01:42 2015 +0100
@@ -181,7 +181,7 @@
 unterdrückt werden.
 
 \subsubsection{Sohlhöhen (Peilungen)}
-Mit \textbf{-Dflys.backend.importer.skip.bed.height.single=true}
+Mit \textbf{-Dflys.backend.importer.skip.bed.height=true}
 kann der Import von Sohlhöhen-Peilungen unterdrückt werden.
 Es werden die CSV-Dateien aus dem Verzeichnis
 \textit{Morphologie/Sohlhoehen/Einzeljahre} geladen.
--- a/backend/doc/schema/oracle-minfo.sql	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/doc/schema/oracle-minfo.sql	Tue Mar 10 17:01:42 2015 +0100
@@ -35,13 +35,12 @@
 INSERT INTO bed_height_type VALUES (6, 'Modell');
 
 
-CREATE SEQUENCE BED_HEIGHT_SINGLE_ID_SEQ;
+CREATE SEQUENCE BED_HEIGHT_ID_SEQ;
 
-CREATE TABLE bed_height_single (
+CREATE TABLE bed_height (
     id                      NUMBER(38,0) NOT NULL,
     river_id                NUMBER(38,0) NOT NULL,
     year                    NUMBER(38,0),
-    sounding_width          NUMBER(38,0),
     type_id                 NUMBER(38,0) NOT NULL,
     location_system_id      NUMBER(38,0) NOT NULL,
     cur_elevation_model_id  NUMBER(38,0) NOT NULL,
@@ -50,29 +49,34 @@
     evaluation_by           VARCHAR(255),
     description             VARCHAR(255),
     PRIMARY KEY(id),
-    CONSTRAINT fk_bed_single_river_id FOREIGN KEY (river_id) REFERENCES rivers(id) ON DELETE CASCADE,
+    CONSTRAINT fk_bed_river_id FOREIGN KEY (river_id)
+        REFERENCES rivers(id) ON DELETE CASCADE,
     CONSTRAINT fk_type FOREIGN KEY (type_id) REFERENCES bed_height_type(id),
-    CONSTRAINT fk_location_system FOREIGN KEY (location_system_id) REFERENCES location_system(id),
-    CONSTRAINT fk_cur_elevation_model FOREIGN KEY (cur_elevation_model_id) REFERENCES elevation_model(id),
-    CONSTRAINT fk_old_elevation_model FOREIGN KEY (old_elevation_model_id) REFERENCES elevation_model(id),
-    CONSTRAINT fk_range FOREIGN KEY (range_id) REFERENCES ranges(id) ON DELETE CASCADE
+    CONSTRAINT fk_location_system FOREIGN KEY (location_system_id)
+        REFERENCES location_system(id),
+    CONSTRAINT fk_cur_elevation_model FOREIGN KEY (cur_elevation_model_id)
+        REFERENCES elevation_model(id),
+    CONSTRAINT fk_old_elevation_model FOREIGN KEY (old_elevation_model_id)
+        REFERENCES elevation_model(id),
+    CONSTRAINT fk_range FOREIGN KEY (range_id)
+        REFERENCES ranges(id) ON DELETE CASCADE
 );
 
 
-CREATE SEQUENCE BED_SINGLE_VALUES_ID_SEQ;
+CREATE SEQUENCE BED_HEIGHT_VALUES_ID_SEQ;
 
-CREATE TABLE bed_height_single_values (
+CREATE TABLE bed_height_values (
     id                      NUMBER(38,0) NOT NULL,
-    bed_height_single_id    NUMBER(38,0) NOT NULL,
+    bed_height_id           NUMBER(38,0) NOT NULL,
     station                 DOUBLE PRECISION NOT NULL,
     height                  DOUBLE PRECISION,
     uncertainty             DOUBLE PRECISION,
     data_gap                DOUBLE PRECISION,
     sounding_width          DOUBLE PRECISION,
-    width                   DOUBLE PRECISION,
     PRIMARY KEY(id),
-    UNIQUE (station, bed_height_single_id),
-    CONSTRAINT fk_bed_single_values_parent FOREIGN KEY (bed_height_single_id) REFERENCES bed_height_single(id) ON DELETE CASCADE
+    UNIQUE (station, bed_height_id),
+    CONSTRAINT fk_bed_values_parent FOREIGN KEY (bed_height_id)
+        REFERENCES bed_height(id) ON DELETE CASCADE
 );
 
 
--- a/backend/doc/schema/postgresql-minfo.sql	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/doc/schema/postgresql-minfo.sql	Tue Mar 10 17:01:42 2015 +0100
@@ -35,13 +35,12 @@
 INSERT INTO bed_height_type VALUES (6, 'Modell');
 
 
-CREATE SEQUENCE BED_HEIGHT_SINGLE_ID_SEQ;
+CREATE SEQUENCE BED_HEIGHT_ID_SEQ;
 
-CREATE TABLE bed_height_single (
+CREATE TABLE bed_height (
     id                      int NOT NULL,
     river_id                int NOT NULL,
     year                    int,
-    sounding_width          int,
     type_id                 int NOT NULL,
     location_system_id      int NOT NULL,
     cur_elevation_model_id  int NOT NULL,
@@ -50,29 +49,34 @@
     evaluation_by           VARCHAR(255),
     description             VARCHAR(255),
     PRIMARY KEY(id),
-    CONSTRAINT fk_bed_single_river_id FOREIGN KEY (river_id) REFERENCES rivers(id) ON DELETE CASCADE,
+    CONSTRAINT fk_bed_river_id FOREIGN KEY (river_id)
+        REFERENCES rivers(id) ON DELETE CASCADE,
     CONSTRAINT fk_type FOREIGN KEY (type_id) REFERENCES bed_height_type(id),
-    CONSTRAINT fk_location_system FOREIGN KEY (location_system_id) REFERENCES location_system(id),
-    CONSTRAINT fk_cur_elevation_model FOREIGN KEY (cur_elevation_model_id) REFERENCES elevation_model(id),
-    CONSTRAINT fk_old_elevation_model FOREIGN KEY (old_elevation_model_id) REFERENCES elevation_model(id),
-    CONSTRAINT fk_range FOREIGN KEY (range_id) REFERENCES ranges(id) ON DELETE CASCADE
+    CONSTRAINT fk_location_system FOREIGN KEY (location_system_id)
+        REFERENCES location_system(id),
+    CONSTRAINT fk_cur_elevation_model FOREIGN KEY (cur_elevation_model_id)
+        REFERENCES elevation_model(id),
+    CONSTRAINT fk_old_elevation_model FOREIGN KEY (old_elevation_model_id)
+        REFERENCES elevation_model(id),
+    CONSTRAINT fk_range FOREIGN KEY (range_id)
+        REFERENCES ranges(id) ON DELETE CASCADE
 );
 
 
-CREATE SEQUENCE BED_SINGLE_VALUES_ID_SEQ;
+CREATE SEQUENCE BED_HEIGHT_VALUES_ID_SEQ;
 
-CREATE TABLE bed_height_single_values (
+CREATE TABLE bed_height_values (
     id                      int NOT NULL,
-    bed_height_single_id    int NOT NULL,
+    bed_height_id    int NOT NULL,
     station                 NUMERIC NOT NULL,
     height                  NUMERIC,
     uncertainty             NUMERIC,
     data_gap                NUMERIC,
     sounding_width          NUMERIC,
-    width                   NUMERIC,
     PRIMARY KEY(id),
-    UNIQUE (station, bed_height_single_id),
-    CONSTRAINT fk_bed_single_values_parent FOREIGN KEY (bed_height_single_id) REFERENCES bed_height_single(id) ON DELETE CASCADE
+    UNIQUE (station, bed_height_id),
+    CONSTRAINT fk_bed_values_parent FOREIGN KEY (bed_height_id)
+        REFERENCES bed_height(id) ON DELETE CASCADE
 );
 
 
--- a/backend/src/main/java/org/dive4elements/river/backend/FLYSCredentials.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/backend/FLYSCredentials.java	Tue Mar 10 17:01:42 2015 +0100
@@ -14,8 +14,8 @@
 import org.dive4elements.river.model.AnnotationType;
 import org.dive4elements.river.model.Attribute;
 import org.dive4elements.river.model.AxisKind;
-import org.dive4elements.river.model.BedHeightSingle;
-import org.dive4elements.river.model.BedHeightSingleValue;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
 import org.dive4elements.river.model.BedHeightType;
 import org.dive4elements.river.model.Building;
 import org.dive4elements.river.model.BoundaryKind;
@@ -151,8 +151,8 @@
         AnnotationType.class,
         Attribute.class,
         AxisKind.class,
-        BedHeightSingle.class,
-        BedHeightSingleValue.class,
+        BedHeight.class,
+        BedHeightValue.class,
         BedHeightType.class,
         Building.class,
         BoundaryKind.class,
--- a/backend/src/main/java/org/dive4elements/river/backend/SedDBSessionHolder.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/backend/SedDBSessionHolder.java	Tue Mar 10 17:01:42 2015 +0100
@@ -13,39 +13,16 @@
 import org.hibernate.Session;
 import org.hibernate.SessionFactory;
 
-public class SedDBSessionHolder
+public class SedDBSessionHolder extends SessionHolder
 {
     private static Logger log =
         Logger.getLogger(SedDBSessionHolder.class);
 
-    public static final ThreadLocal<Session> HOLDER =
-        new ThreadLocal<Session>() {
-            @Override
-            protected Session initialValue() {
-                return create();
-            }
-        };
-
-    private SedDBSessionHolder() {
-    }
-
     public synchronized static Session create() {
         log.debug("create");
         SessionFactory sessionFactory =
             SessionFactoryProvider.getSedDBSessionFactory();
         return sessionFactory.openSession();
     }
-
-    public static Session acquire() {
-        log.debug("acquire");
-        Session session = create();
-        HOLDER.set(session);
-        return session;
-    }
-
-    public static void release() {
-        log.debug("release");
-        HOLDER.remove();
-    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/backend/SessionHolder.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/backend/SessionHolder.java	Tue Mar 10 17:01:42 2015 +0100
@@ -23,11 +23,13 @@
         new ThreadLocal<Session>() {
             @Override
             protected Session initialValue() {
-                return create();
+                Session session = create();
+                log.debug("Initial session value: " + session.hashCode());
+                return session;
             }
         };
 
-    private SessionHolder() {
+    protected SessionHolder() {
     }
 
     public synchronized static Session create() {
@@ -38,14 +40,20 @@
     }
 
     public static Session acquire() {
-        log.debug("acquire");
         Session session = create();
+        log.debug("acquired session: " + session.hashCode());
         HOLDER.set(session);
         return session;
     }
 
     public static void release() {
-        log.debug("release");
+        Session session = HOLDER.get();
+        if (session != null) {
+            log.debug("releasing session: " + session.hashCode());
+            session.close();
+        } else {
+            log.error("release() called on NULL session.");
+        }
         HOLDER.remove();
     }
 }
--- a/backend/src/main/java/org/dive4elements/river/importer/Config.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/Config.java	Tue Mar 10 17:01:42 2015 +0100
@@ -67,8 +67,8 @@
     public static final String SKIP_FLOOD_PROTECTION =
         "flys.backend.importer.skip.flood.protection";
 
-    public static final String SKIP_BED_HEIGHT_SINGLE =
-        "flys.backend.importer.skip.bed.height.single";
+    public static final String SKIP_BED_HEIGHT =
+        "flys.backend.importer.skip.bed.height";
 
     public static final String SKIP_DA66S =
         "flys.backend.importer.skip.da66s";
@@ -210,8 +210,8 @@
         return getFlag(SKIP_DA66S);
     }
 
-    public boolean skipBedHeightSingle() {
-        return getFlag(SKIP_BED_HEIGHT_SINGLE);
+    public boolean skipBedHeight() {
+        return getFlag(SKIP_BED_HEIGHT);
     }
 
     public boolean skipSedimentDensity() {
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeight.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeight.java	Tue Mar 10 17:01:42 2015 +0100
@@ -8,45 +8,189 @@
 
 package org.dive4elements.river.importer;
 
+import java.util.ArrayList;
+import java.util.List;
 
-import java.sql.SQLException;
+import org.apache.log4j.Logger;
 
-import org.hibernate.exception.ConstraintViolationException;
+import org.hibernate.Session;
+import org.hibernate.Query;
 
+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;
 
 
-public interface ImportBedHeight {
-
-    String getDescription();
-
-    void addValue(ImportBedHeightValue value);
-
-    void storeDependencies(River river)
-    throws SQLException, ConstraintViolationException;
-
-    Object getPeer(River river);
-
-    int getValueCount();
-
-    void setYear(int year);
+public class ImportBedHeight
+{
+    private static Logger log = Logger.getLogger(ImportBedHeight.class);
 
-    void setTimeInterval(ImportTimeInterval timeInterval);
-
-    void setSoundingWidth(int soundingWidth);
-
-    void setDescription(String description);
-
-    void setEvaluationBy(String evaluationBy);
+    protected Integer year;
 
-    void setRange(ImportRange range);
-
-    void setType(ImportBedHeightType type);
+    protected String evaluationBy;
+    protected String description;
 
-    void setLocationSystem(ImportLocationSystem locationSystem);
+    protected ImportRange          range;
+    protected ImportBedHeightType  type;
+    protected ImportLocationSystem locationSystem;
+    protected ImportElevationModel curElevationModel;
+    protected ImportElevationModel oldElevationModel;
 
-    void setCurElevationModel(ImportElevationModel model);
+    protected List<ImportBedHeightValue> values;
 
-    void setOldElevationModel(ImportElevationModel model);
+    protected BedHeight peer;
+
+
+    public ImportBedHeight(String description) {
+        this.description = description;
+        this.values      = new ArrayList<ImportBedHeightValue>();
+    }
+
+
+    public String getDescription() {
+        return description;
+    }
+
+    public int getValueCount() {
+        return values.size();
+    }
+
+
+    public void setYear(int year) {
+        this.year = year;
+    }
+
+    public void setTimeInterval(ImportTimeInterval timeInterval) {
+        // do nothing
+    }
+
+    public void setEvaluationBy(String evaluationBy) {
+        this.evaluationBy = evaluationBy;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public void setRange(ImportRange range) {
+        this.range = range;
+    }
+
+    public void setType(ImportBedHeightType type) {
+        this.type = type;
+    }
+
+    public void setLocationSystem(ImportLocationSystem locationSystem) {
+        this.locationSystem = locationSystem;
+    }
+
+    public void setCurElevationModel(ImportElevationModel curElevationModel) {
+        this.curElevationModel = curElevationModel;
+    }
+
+    public void setOldElevationModel(ImportElevationModel oldElevationModel) {
+        this.oldElevationModel = oldElevationModel;
+    }
+
+    public void addValue(ImportBedHeightValue value) {
+        values.add((ImportBedHeightValue) value);
+    }
+
+    public void storeDependencies(River river) {
+        log.info("Store dependencies for single: '" + getDescription() + "'");
+
+        if (type != null) {
+            type.storeDependencies();
+        }
+
+        if (locationSystem != null) {
+            locationSystem.storeDependencies();
+        }
+
+        if (curElevationModel != null) {
+            curElevationModel.storeDependencies();
+        }
+
+        if (oldElevationModel != null) {
+            oldElevationModel.storeDependencies();
+        }
+
+        BedHeight peer = getPeer(river);
+
+        if (peer != null) {
+            for (ImportBedHeightValue value: values) {
+                value.storeDependencies(peer);
+            }
+        }
+
+        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();
+
+            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.");
+
+                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);
+            }
+        }
+
+        return peer;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightSingle.java	Wed Feb 18 17:17:20 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +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.importer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.model.BedHeightSingle;
-import org.dive4elements.river.model.BedHeightType;
-import org.dive4elements.river.model.ElevationModel;
-import org.dive4elements.river.model.Range;
-import org.dive4elements.river.model.River;
-
-
-public class ImportBedHeightSingle implements ImportBedHeight
-{
-    private static Logger log = Logger.getLogger(ImportBedHeightSingle.class);
-
-    protected Integer year;
-    protected int soundingWidth;
-
-    protected String evaluationBy;
-    protected String description;
-
-    protected ImportRange          range;
-    protected ImportBedHeightType  type;
-    protected ImportLocationSystem locationSystem;
-    protected ImportElevationModel curElevationModel;
-    protected ImportElevationModel oldElevationModel;
-
-    protected List<ImportBedHeightSingleValue> values;
-
-    protected BedHeightSingle peer;
-
-
-    public ImportBedHeightSingle(String description) {
-        this.description = description;
-        this.values      = new ArrayList<ImportBedHeightSingleValue>();
-    }
-
-
-    public String getDescription() {
-        return description;
-    }
-
-    public int getValueCount() {
-        return values.size();
-    }
-
-
-    public void setYear(int year) {
-        this.year = year;
-    }
-
-    public void setTimeInterval(ImportTimeInterval timeInterval) {
-        // do nothing
-    }
-
-    public void setSoundingWidth(int soundingWidth) {
-        this.soundingWidth = soundingWidth;
-    }
-
-    public void setEvaluationBy(String evaluationBy) {
-        this.evaluationBy = evaluationBy;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public void setRange(ImportRange range) {
-        this.range = range;
-    }
-
-    public void setType(ImportBedHeightType type) {
-        this.type = type;
-    }
-
-    public void setLocationSystem(ImportLocationSystem locationSystem) {
-        this.locationSystem = locationSystem;
-    }
-
-    public void setCurElevationModel(ImportElevationModel curElevationModel) {
-        this.curElevationModel = curElevationModel;
-    }
-
-    public void setOldElevationModel(ImportElevationModel oldElevationModel) {
-        this.oldElevationModel = oldElevationModel;
-    }
-
-    @Override
-    public void addValue(ImportBedHeightValue value) {
-        values.add((ImportBedHeightSingleValue) value);
-    }
-
-    @Override
-    public void storeDependencies(River river) {
-        log.info("Store dependencies for single: '" + getDescription() + "'");
-
-        if (type != null) {
-            type.storeDependencies();
-        }
-
-        if (locationSystem != null) {
-            locationSystem.storeDependencies();
-        }
-
-        if (curElevationModel != null) {
-            curElevationModel.storeDependencies();
-        }
-
-        if (oldElevationModel != null) {
-            oldElevationModel.storeDependencies();
-        }
-
-        BedHeightSingle peer = getPeer(river);
-
-        if (peer != null) {
-            for (ImportBedHeightSingleValue value: values) {
-                value.storeDependencies(peer);
-            }
-        }
-
-        Session session = ImporterSession.getInstance().getDatabaseSession();
-        session.flush();
-    }
-
-    @Override
-    public BedHeightSingle 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();
-
-            Query query = session.createQuery(
-                "from BedHeightSingle where " +
-                "river=:river and year=:year and soundingWidth=:soundingWidth " +
-                "and type=:type and locationSystem=:locationSystem and " +
-                "curElevationModel=:curElevationModel and range=:range");
-
-            query.setParameter("river", river);
-            query.setParameter("year", year);
-            query.setParameter("soundingWidth", soundingWidth);
-            query.setParameter("type", theType);
-            query.setParameter("locationSystem", locationSystem.getPeer());
-            query.setParameter("curElevationModel", theCurModel);
-            query.setParameter("range", range.getPeer(river));
-
-            List<BedHeightSingle> bedHeights = query.list();
-            if (bedHeights.isEmpty()) {
-                log.info("Create new BedHeightSingle DB instance.");
-
-                peer = new BedHeightSingle(
-                    river,
-                    year,
-                    soundingWidth,
-                    theType,
-                    locationSystem.getPeer(),
-                    theCurModel,
-                    oldElevationModel != null ? oldElevationModel.getPeer() : null,
-                    range.getPeer(river),
-                    evaluationBy,
-                    description
-                );
-
-                session.save(peer);
-            }
-            else {
-                peer = bedHeights.get(0);
-            }
-        }
-
-        return peer;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightSingleValue.java	Wed Feb 18 17:17:20 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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.importer;
-
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.model.BedHeightSingle;
-import org.dive4elements.river.model.BedHeightSingleValue;
-
-
-public class ImportBedHeightSingleValue implements ImportBedHeightValue {
-
-    private static final Logger log =
-        Logger.getLogger(ImportBedHeightSingleValue.class);
-
-
-    protected ImportBedHeightSingle bedHeight;
-
-    protected Double station;
-    protected Double height;
-    protected Double uncertainty;
-    protected Double dataGap;
-    protected Double soundingWidth;
-    protected Double width;
-
-    protected BedHeightSingleValue peer;
-
-
-    public ImportBedHeightSingleValue(
-        ImportBedHeightSingle bedHeight,
-        Double station,
-        Double height,
-        Double uncertainty,
-        Double dataGap,
-        Double soundingWidth,
-        Double width
-    ) {
-        this.bedHeight     = bedHeight;
-        this.station       = station;
-        this.height        = height;
-        this.uncertainty   = uncertainty;
-        this.dataGap       = dataGap;
-        this.soundingWidth = soundingWidth;
-        this.width         = width;
-    }
-
-
-    public void storeDependencies(BedHeightSingle bedHeight) {
-        getPeer(bedHeight);
-    }
-
-
-    /**
-     * Add this value to database or return database bound Value, assuring
-     * that the BedHeightSingle exists in db already.
-     */
-    public BedHeightSingleValue getPeer(BedHeightSingle bedHeight) {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance().getDatabaseSession();
-
-            Query query = session.createQuery(
-                "from BedHeightSingleValue where " +
-                "   bedHeight=:bedHeight and " +
-                "   station=:station and " +
-                "   height=:height and " +
-                "   uncertainty=:uncertainty and " +
-                "   dataGap=:dataGap and " +
-                "   soundingWidth=:soundingWidth and " +
-                "   width=:width");
-
-            query.setParameter("bedHeight", bedHeight);
-            query.setParameter("station", station);
-            query.setParameter("height", height);
-            query.setParameter("uncertainty", uncertainty);
-            query.setParameter("dataGap", dataGap);
-            query.setParameter("soundingWidth", soundingWidth);
-            query.setParameter("width", width);
-
-            List<BedHeightSingleValue> values = query.list();
-            if (values.isEmpty()) {
-                peer = new BedHeightSingleValue(
-                    bedHeight,
-                    station,
-                    height,
-                    uncertainty,
-                    dataGap,
-                    soundingWidth,
-                    width
-                );
-                session.save(peer);
-            }
-            else {
-                peer = values.get(0);
-            }
-        }
-
-        return 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	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightValue.java	Tue Mar 10 17:01:42 2015 +0100
@@ -8,8 +8,98 @@
 
 package org.dive4elements.river.importer;
 
+import java.util.List;
 
-public interface ImportBedHeightValue {
+import org.apache.log4j.Logger;
 
+import org.hibernate.Session;
+import org.hibernate.Query;
+
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
+
+
+public class ImportBedHeightValue {
+
+    private static final Logger log =
+        Logger.getLogger(ImportBedHeightValue.class);
+
+
+    protected ImportBedHeight bedHeight;
+
+    protected Double station;
+    protected Double height;
+    protected Double uncertainty;
+    protected Double dataGap;
+    protected Double soundingWidth;
+
+    protected BedHeightValue peer;
+
+
+    public ImportBedHeightValue(
+        ImportBedHeight bedHeight,
+        Double station,
+        Double height,
+        Double uncertainty,
+        Double dataGap,
+        Double soundingWidth
+    ) {
+        this.bedHeight     = bedHeight;
+        this.station       = station;
+        this.height        = height;
+        this.uncertainty   = uncertainty;
+        this.dataGap       = dataGap;
+        this.soundingWidth = soundingWidth;
+    }
+
+
+    public void storeDependencies(BedHeight bedHeight) {
+        getPeer(bedHeight);
+    }
+
+
+    /**
+     * 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 and " +
+                "   height=:height and " +
+                "   uncertainty=:uncertainty and " +
+                "   dataGap=:dataGap and " +
+                "   soundingWidth=:soundingWidth");
+
+            query.setParameter("bedHeight", bedHeight);
+            query.setParameter("station", station);
+            query.setParameter("height", height);
+            query.setParameter("uncertainty", uncertainty);
+            query.setParameter("dataGap", dataGap);
+            query.setParameter("soundingWidth", soundingWidth);
+
+            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);
+            }
+        }
+
+        return 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	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java	Tue Mar 10 17:01:42 2015 +0100
@@ -14,7 +14,7 @@
 
 import org.dive4elements.river.importer.parsers.AnnotationClassifier;
 import org.dive4elements.river.importer.parsers.AnnotationsParser;
-import org.dive4elements.river.importer.parsers.BedHeightSingleParser;
+import org.dive4elements.river.importer.parsers.BedHeightParser;
 import org.dive4elements.river.importer.parsers.CrossSectionParser;
 import org.dive4elements.river.importer.parsers.DA50Parser;
 import org.dive4elements.river.importer.parsers.DA66Parser;
@@ -164,9 +164,7 @@
     /** Wst-structures from waterlevel-difference-csv files. */
     protected List<ImportWst> waterlevelDifferences;
 
-    protected List<ImportBedHeight> bedHeightSingles;
-
-    protected List<ImportBedHeight> bedHeightEpochs;
+    protected List<ImportBedHeight> bedHeights;
 
     protected List<ImportSedimentDensity> sedimentDensities;
 
@@ -458,12 +456,12 @@
         File bedHeightDir = new File(minfoDir, BED_HEIGHT_DIR);
         File singlesDir   = new File(bedHeightDir, BED_HEIGHT_SINGLE_DIR);
 
-        if (Config.INSTANCE.skipBedHeightSingle()) {
+        if (Config.INSTANCE.skipBedHeight()) {
             log.info("skip parsing bed height single.");
         }
         else {
             log.info("Parse bed height single.");
-            parseBedHeightSingles(singlesDir);
+            parseBedHeights(singlesDir);
         }
     }
 
@@ -818,7 +816,7 @@
     }
 
 
-    protected void parseBedHeightSingles(File dir) throws IOException {
+    protected void parseBedHeights(File dir) throws IOException {
         log.debug("Parse bed height singles");
 
         File[] files = dir.listFiles();
@@ -828,13 +826,13 @@
             return;
         }
 
-        BedHeightSingleParser parser = new BedHeightSingleParser();
+        BedHeightParser parser = new BedHeightParser();
 
         for (File file: files) {
             parser.parse(file);
         }
 
-        bedHeightSingles = parser.getBedHeights();
+        bedHeights = parser.getBedHeights();
     }
 
     public void parseFloodWater() throws IOException {
@@ -1442,29 +1440,24 @@
 
 
     public void storeBedHeight() {
-        if (!Config.INSTANCE.skipBedHeightSingle()) {
-            log.info("store bed heights single");
-            storeBedHeightSingle();
-        }
-    }
-
-
-    private void storeBedHeightSingle() {
-        River river = getPeer();
+        if (!Config.INSTANCE.skipBedHeight()) {
+            log.info("store bed heights");
+            River river = getPeer();
 
-        if (bedHeightSingles != null) {
-            for (ImportBedHeight tmp: bedHeightSingles) {
-                ImportBedHeightSingle single = (ImportBedHeightSingle) tmp;
-
-                String desc = single.getDescription();
+            if (bedHeights != null) {
+                for (ImportBedHeight tmp: bedHeights) {
+                    ImportBedHeight single = (ImportBedHeight) tmp;
 
-                log.debug("name: " + desc);
+                    String desc = single.getDescription();
 
-                single.storeDependencies(river);
+                    log.debug("name: " + desc);
+
+                    single.storeDependencies(river);
+                }
             }
-        }
-        else {
-            log.info("No single bed heights to store.");
+            else {
+                log.info("No bed heights to store.");
+            }
         }
     }
 
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java	Tue Mar 10 17:01:42 2015 +0100
@@ -32,6 +32,7 @@
 import org.apache.log4j.Logger;
 
 import org.dive4elements.river.importer.ImportBedHeight;
+import org.dive4elements.river.importer.ImportBedHeightValue;
 import org.dive4elements.river.importer.ImportBedHeightType;
 import org.dive4elements.river.importer.ImportElevationModel;
 import org.dive4elements.river.importer.ImportLocationSystem;
@@ -43,7 +44,7 @@
 import org.dive4elements.river.backend.utils.EpsilonComparator;
 import org.dive4elements.river.backend.utils.DateUtil;
 
-public abstract class BedHeightParser {
+public class BedHeightParser {
 
     private static final Logger log =
         Logger.getLogger(BedHeightParser.class);
@@ -68,13 +69,10 @@
         Pattern.compile("^Lagesystem: (.*).*");
 
     public static final Pattern META_CUR_ELEVATION_SYSTEM =
-        Pattern.compile("^H.hensystem:\\s(\\w++) (.* )??\\[(.*)\\].*");
+        Pattern.compile("^H.hensystem:\\s(.*)?? \\[(.*)\\].*");
 
     public static final Pattern META_OLD_ELEVATION_SYSTEM =
-        Pattern.compile("^urspr.ngliches H.hensystem:\\s(\\w++) (.* )??\\[(.*)\\].*");
-
-    public static final Pattern META_SOUNDING_WIDTH =
-        Pattern.compile("^ausgewertete Peilbreite: (\\d*).*");
+        Pattern.compile("^urspr.ngliches H.hensystem:\\s(.*)?? \\[(.*)\\].*");
 
     public static final Pattern META_RANGE =
         Pattern.compile("^Strecke:\\D*(\\d++.?\\d*) ?- ?(\\d++.?\\d*).*");
@@ -92,13 +90,10 @@
     protected List<ImportBedHeight> bedHeights;
 
 
-    protected abstract ImportBedHeight newImportBedHeight(String description);
+    protected ImportBedHeight newImportBedHeight(String description) {
+        return new ImportBedHeight(description);
+    }
 
-    /** Handle a line of file that contains data (in contrast to comments, meta). */
-    protected abstract void handleDataLine(
-        ImportBedHeight importBedHeight,
-        String          line
-    );
 
     protected TreeSet<Double> kmExists;
 
@@ -173,9 +168,6 @@
         else if (handleMetaTimeInterval(obj, meta)) {
             return;
         }
-        else if (handleMetaSoundingWidth(obj, meta)) {
-            return;
-        }
         else if (handleMetaComment(obj, meta)) {
             return;
         }
@@ -250,28 +242,6 @@
     }
 
 
-    protected boolean handleMetaSoundingWidth(ImportBedHeight obj, String line) {
-        Matcher m = META_SOUNDING_WIDTH.matcher(line);
-
-        if (m.matches()) {
-            String tmp = m.group(1);
-
-            try {
-                obj.setSoundingWidth(Integer.valueOf(tmp));
-                return true;
-            }
-            catch (NumberFormatException e) {
-                log.warn("BHP: Could not parse sounding width in line '" + line +
-                    "'. -> Set default value '0'");
-            }
-            obj.setSoundingWidth(0);
-            return true;
-        }
-
-        return false;
-    }
-
-
     protected boolean handleMetaComment(ImportBedHeight obj, String line) {
         Matcher m = META_COMMENTS.matcher(line);
 
@@ -378,11 +348,10 @@
 
         if (m.matches()) {
             String name = m.group(1);
-            String num  = m.group(2);
-            String unit = m.group(3);
+            String unit = m.group(2);
 
             obj.setCurElevationModel(new ImportElevationModel(
-                name + " " + num,
+                name,
                 new ImportUnit(unit)
             ));
 
@@ -401,11 +370,10 @@
 
         if (m.matches()) {
             String name = m.group(1);
-            String num  = m.group(2);
-            String unit = m.group(3);
+            String unit = m.group(2);
 
             obj.setOldElevationModel(new ImportElevationModel(
-                name + " " + num,
+                name,
                 new ImportUnit(unit)
             ));
 
@@ -414,5 +382,94 @@
 
         return false;
     }
+
+    protected void handleDataLine(ImportBedHeight obj, String line) {
+        String[] values = line.split(SEPERATOR_CHAR, -1);
+
+        if (values == null) {
+            log.warn("BSP: Error while parsing data line: '" + line + "'");
+            return;
+        }
+
+        Double km;
+
+        try {
+            km = new Double(nf.parse(values[0]).doubleValue());
+
+            Double key = Double.valueOf(km);
+
+            if (kmExists.contains(key)) {
+                log.warn("duplicate station '" + km + "': -> ignored");
+                return;
+            }
+
+            kmExists.add(key);
+        }
+        catch (ParseException e) {
+            // We expect a lot of ";;;;;;" lines.
+            return;
+        }
+
+        // Handle gaps like "10,0;;;;;".
+        if (values.length <= 2) {
+            // Do not import line without useful data
+            if (values.length < 2) {
+                return;
+            }
+            if (values[1].length() == 0) {
+                return;
+            }
+        }
+
+        Double height = null;
+        if (values[1].length() > 0) {
+            try {
+                height = new Double(nf.parse(values[1]).doubleValue());
+            }
+            catch (ParseException e) {
+                log.warn("BSP: unparseable height " + values[1]);
+            }
+        }
+
+        Double uncertainty = null;
+        if (values[2].length() > 0) {
+            try {
+                uncertainty = new Double(nf.parse(values[2]).doubleValue());
+            }
+            catch (ParseException e) {
+                log.warn("BSP: unparseable uncertainty value " + values[2]);
+            }
+        }
+
+        Double dataGap = null;
+        if (values[3].length() > 0) {
+            try {
+                dataGap = new Double(nf.parse(values[3]).doubleValue());
+            }
+            catch (ParseException e) {
+                log.warn("BSP: unparseable data gap " + values[3]);
+            }
+        }
+
+        Double soundingWidth = null;
+        if (values[4].length() > 0) {
+            try {
+                soundingWidth = new Double(nf.parse(values[4]).doubleValue());
+            }
+            catch (ParseException e) {
+                log.warn("BSP: unparseable sounding width " + values[4]);
+            }
+        }
+
+        ImportBedHeightValue value = new ImportBedHeightValue(
+            (ImportBedHeight) obj,
+            km,
+            height,
+            uncertainty,
+            dataGap,
+            soundingWidth);
+
+        obj.addValue(value);
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightSingleParser.java	Wed Feb 18 17:17:20 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +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.importer.parsers;
-
-import java.text.ParseException;
-
-import org.apache.log4j.Logger;
-
-import org.dive4elements.river.importer.ImportBedHeight;
-import org.dive4elements.river.importer.ImportBedHeightSingle;
-import org.dive4elements.river.importer.ImportBedHeightSingleValue;
-
-
-public class BedHeightSingleParser extends BedHeightParser {
-
-    private static final Logger log =
-        Logger.getLogger(BedHeightSingleParser.class);
-
-
-    @Override
-    protected ImportBedHeight newImportBedHeight(String description) {
-        return new ImportBedHeightSingle(description);
-    }
-
-
-    /**
-     * Create ImportBedHeightSingleValue from a line of csv file, add
-     * it to the ImportBedHeight.
-     */
-    @Override
-    protected void handleDataLine(ImportBedHeight obj, String line) {
-        String[] values = line.split(SEPERATOR_CHAR, -1);
-
-        if (values == null) {
-            log.warn("BSP: Error while parsing data line: '" + line + "'");
-            return;
-        }
-
-        Double km;
-
-        try {
-            km = new Double(nf.parse(values[0]).doubleValue());
-
-            Double key = Double.valueOf(km);
-
-            if (kmExists.contains(key)) {
-                log.warn("duplicate station '" + km + "': -> ignored");
-                return;
-            }
-
-            kmExists.add(key);
-        }
-        catch (ParseException e) {
-            // We expect a lot of ";;;;;;" lines.
-            return;
-        }
-
-        // Handle gaps like "10,0;;;;;".
-        if (values.length <= 2) {
-            // Do not import line without useful data
-            if (values.length < 2) {
-                return;
-            }
-            if (values[1].length() == 0) {
-                return;
-            }
-        }
-
-        Double height = null;
-        if (values[1].length() > 0) {
-            try {
-                height = new Double(nf.parse(values[1]).doubleValue());
-            }
-            catch (ParseException e) {
-                log.warn("BSP: unparseable height " + values[1]);
-            }
-        }
-
-        Double uncertainty = null;
-        if (values[2].length() > 0) {
-            try {
-                uncertainty = new Double(nf.parse(values[2]).doubleValue());
-            }
-            catch (ParseException e) {
-                log.warn("BSP: unparseable uncertainty value " + values[2]);
-            }
-        }
-
-        Double dataGap = null;
-        if (values[3].length() > 0) {
-            try {
-                dataGap = new Double(nf.parse(values[3]).doubleValue());
-            }
-            catch (ParseException e) {
-                log.warn("BSP: unparseable data gap " + values[3]);
-            }
-        }
-
-        Double soundingWidth = null;
-        if (values[4].length() > 0) {
-            try {
-                soundingWidth = new Double(nf.parse(values[4]).doubleValue());
-            }
-            catch (ParseException e) {
-                log.warn("BSP: unparseable sounding width " + values[4]);
-            }
-        }
-
-        Double width = null;
-        if (values[5].length() > 0) {
-            try {
-                width = new Double(nf.parse(values[5]).doubleValue());
-            }
-            catch (ParseException e) {
-                log.warn("BSP: unparseable width " + values[5]);
-            }
-        }
-
-        ImportBedHeightSingleValue value = new ImportBedHeightSingleValue(
-            (ImportBedHeightSingle) obj,
-            km,
-            height,
-            uncertainty,
-            dataGap,
-            soundingWidth,
-            width);
-
-        obj.addValue(value);
-    }
-}
-// 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/model/BedHeight.java	Tue Mar 10 17:01:42 2015 +0100
@@ -0,0 +1,266 @@
+/* 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.model;
+
+import java.io.Serializable;
+
+import java.util.ArrayList;
+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.GenerationType;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.OneToMany;
+
+import org.hibernate.Session;
+import org.hibernate.Query;
+
+import org.dive4elements.river.backend.SessionHolder;
+
+
+@Entity
+@Table(name = "bed_height")
+public class BedHeight implements Serializable {
+
+    private Integer id;
+    private Integer year;
+
+    private String evaluationBy;
+    private String description;
+
+    private River river;
+
+    private BedHeightType  type;
+
+    private LocationSystem locationSystem;
+
+    private ElevationModel curElevationModel;
+
+    private ElevationModel oldElevationModel;
+
+    private Range range;
+
+    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(
+        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;
+        this.curElevationModel = curElevationModel;
+        this.oldElevationModel = oldElevationModel;
+        this.range             = range;
+        this.evaluationBy      = evaluationBy;
+        this.description       = description;
+    }
+
+
+    @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")
+    @Column(name = "id")
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "river_id" )
+    public River getRiver() {
+        return river;
+    }
+
+    public void setRiver(River river) {
+        this.river = river;
+    }
+
+    @Column(name = "year")
+    public Integer getYear() {
+        return year;
+    }
+
+    public void setYear(Integer year) {
+        this.year = year;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "type_id")
+    public BedHeightType getType() {
+        return type;
+    }
+
+    public void setType(BedHeightType type) {
+        this.type = type;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "location_system_id")
+    public LocationSystem getLocationSystem() {
+        return locationSystem;
+    }
+
+    public void setLocationSystem(LocationSystem locationSystem) {
+        this.locationSystem = locationSystem;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "cur_elevation_model_id")
+    public ElevationModel getCurElevationModel() {
+        return curElevationModel;
+    }
+
+    public void setCurElevationModel(ElevationModel curElevationModel) {
+        this.curElevationModel = curElevationModel;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "old_elevation_model_id")
+    public ElevationModel getOldElevationModel() {
+        return oldElevationModel;
+    }
+
+    public void setOldElevationModel(ElevationModel oldElevationModel) {
+        this.oldElevationModel = oldElevationModel;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "range_id")
+    public Range getRange() {
+        return range;
+    }
+
+    public void setRange(Range range) {
+        this.range = range;
+    }
+
+    @Column(name = "evaluation_by")
+    public String getEvaluationBy() {
+        return evaluationBy;
+    }
+
+    public void setEvaluationBy(String evaluationBy) {
+        this.evaluationBy = evaluationBy;
+    }
+
+    @Column(name = "description")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @OneToMany
+    @JoinColumn(name = "bed_height_id")
+    public List<BedHeightValue> getValues() {
+        return values;
+    }
+
+    public void setValues(List<BedHeightValue> values) {
+        this.values = values;
+    }
+
+
+    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");
+
+        query.setParameter("river", river);
+
+        // TODO Do km range filtering in SQL statement
+
+        List<BedHeight> singles = query.list();
+        List<BedHeight> good    = new ArrayList<BedHeight>();
+
+        for (BedHeight s: singles) {
+            for (BedHeightValue value: s.getValues()) {
+                double station = value.getStation().doubleValue();
+
+                if (station >= kmLo && station <= kmHi) {
+                    good.add(s);
+                    break;
+                }
+            }
+        }
+
+        return good;
+    }
+
+
+    public static BedHeight getBedHeightById(int id) {
+        Session session = SessionHolder.HOLDER.get();
+
+        Query query = session.createQuery(
+            "from BedHeight where id=:id");
+
+        query.setParameter("id", id);
+
+        List<BedHeight> singles = query.list();
+
+        return singles != null ? singles.get(0) : null;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/BedHeightSingle.java	Wed Feb 18 17:17:20 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +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.model;
-
-import java.io.Serializable;
-
-import java.util.ArrayList;
-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.GenerationType;
-import javax.persistence.JoinColumn;
-import javax.persistence.OneToOne;
-import javax.persistence.OneToMany;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.backend.SessionHolder;
-
-
-@Entity
-@Table(name = "bed_height_single")
-public class BedHeightSingle implements Serializable {
-
-    private Integer id;
-    private Integer year;
-    private Integer soundingWidth;
-
-    private String evaluationBy;
-    private String description;
-
-    private River river;
-
-    private BedHeightType  type;
-
-    private LocationSystem locationSystem;
-
-    private ElevationModel curElevationModel;
-
-    private ElevationModel oldElevationModel;
-
-    private Range range;
-
-    private List<BedHeightSingleValue> values;
-
-
-    public BedHeightSingle() {
-    }
-
-
-    public BedHeightSingle(
-        River          river,
-        Integer        year,
-        Integer        soundingWidth,
-        BedHeightType  type,
-        LocationSystem locationSystem,
-        ElevationModel curElevationModel,
-        Range          range
-    ) {
-        this(
-            river,
-            year,
-            soundingWidth,
-            type,
-            locationSystem,
-            curElevationModel,
-            null,
-            range,
-            null,
-            null);
-    }
-
-
-    public BedHeightSingle(
-        River          river,
-        Integer        year,
-        Integer        soundingWidth,
-        BedHeightType  type,
-        LocationSystem locationSystem,
-        ElevationModel curElevationModel,
-        ElevationModel oldElevationModel,
-        Range          range,
-        String         evaluationBy,
-        String         description
-    ) {
-        this.river             = river;
-        this.year              = year;
-        this.soundingWidth     = soundingWidth;
-        this.type              = type;
-        this.locationSystem    = locationSystem;
-        this.curElevationModel = curElevationModel;
-        this.oldElevationModel = oldElevationModel;
-        this.range             = range;
-        this.evaluationBy      = evaluationBy;
-        this.description       = description;
-    }
-
-
-    @Id
-    @SequenceGenerator(
-        name           = "SEQUENCE_BED_HEIGHT_SINGLE_ID_SEQ",
-        sequenceName   = "BED_HEIGHT_SINGLE_ID_SEQ",
-        allocationSize = 1)
-    @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_BED_HEIGHT_SINGLE_ID_SEQ")
-    @Column(name = "id")
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    @OneToOne
-    @JoinColumn(name = "river_id" )
-    public River getRiver() {
-        return river;
-    }
-
-    public void setRiver(River river) {
-        this.river = river;
-    }
-
-    @Column(name = "year")
-    public Integer getYear() {
-        return year;
-    }
-
-    public void setYear(Integer year) {
-        this.year = year;
-    }
-
-    @Column(name = "sounding_width")
-    public Integer getSoundingWidth() {
-        return soundingWidth;
-    }
-
-    public void setSoundingWidth(Integer soundingWidth) {
-        this.soundingWidth = soundingWidth;
-    }
-
-    @OneToOne
-    @JoinColumn(name = "type_id")
-    public BedHeightType getType() {
-        return type;
-    }
-
-    public void setType(BedHeightType type) {
-        this.type = type;
-    }
-
-    @OneToOne
-    @JoinColumn(name = "location_system_id")
-    public LocationSystem getLocationSystem() {
-        return locationSystem;
-    }
-
-    public void setLocationSystem(LocationSystem locationSystem) {
-        this.locationSystem = locationSystem;
-    }
-
-    @OneToOne
-    @JoinColumn(name = "cur_elevation_model_id")
-    public ElevationModel getCurElevationModel() {
-        return curElevationModel;
-    }
-
-    public void setCurElevationModel(ElevationModel curElevationModel) {
-        this.curElevationModel = curElevationModel;
-    }
-
-    @OneToOne
-    @JoinColumn(name = "old_elevation_model_id")
-    public ElevationModel getOldElevationModel() {
-        return oldElevationModel;
-    }
-
-    public void setOldElevationModel(ElevationModel oldElevationModel) {
-        this.oldElevationModel = oldElevationModel;
-    }
-
-    @OneToOne
-    @JoinColumn(name = "range_id")
-    public Range getRange() {
-        return range;
-    }
-
-    public void setRange(Range range) {
-        this.range = range;
-    }
-
-    @Column(name = "evaluation_by")
-    public String getEvaluationBy() {
-        return evaluationBy;
-    }
-
-    public void setEvaluationBy(String evaluationBy) {
-        this.evaluationBy = evaluationBy;
-    }
-
-    @Column(name = "description")
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    @OneToMany
-    @JoinColumn(name = "bed_height_single_id")
-    public List<BedHeightSingleValue> getValues() {
-        return values;
-    }
-
-    public void setValues(List<BedHeightSingleValue> values) {
-        this.values = values;
-    }
-
-
-    public static List<BedHeightSingle> getBedHeightSingles(
-        River  river,
-        double kmLo,
-        double kmHi
-    ) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeightSingle where river=:river");
-
-        query.setParameter("river", river);
-
-        // TODO Do km range filtering in SQL statement
-
-        List<BedHeightSingle> singles = query.list();
-        List<BedHeightSingle> good    = new ArrayList<BedHeightSingle>();
-
-        for (BedHeightSingle s: singles) {
-            for (BedHeightSingleValue value: s.getValues()) {
-                double station = value.getStation().doubleValue();
-
-                if (station >= kmLo && station <= kmHi) {
-                    good.add(s);
-                    break;
-                }
-            }
-        }
-
-        return good;
-    }
-
-
-    public static BedHeightSingle getBedHeightSingleById(int id) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeightSingle where id=:id");
-
-        query.setParameter("id", id);
-
-        List<BedHeightSingle> singles = query.list();
-
-        return singles != null ? singles.get(0) : null;
-    }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/BedHeightSingleValue.java	Wed Feb 18 17:17:20 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +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.model;
-
-import java.util.List;
-
-import java.io.Serializable;
-//import java.math.BigDecimal;
-
-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.GenerationType;
-import javax.persistence.JoinColumn;
-import javax.persistence.OneToOne;
-
-import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.backend.SessionHolder;
-
-
-@Entity
-@Table(name = "bed_height_single_values")
-public class BedHeightSingleValue
-implements   Serializable
-{
-    private static Logger log =
-        Logger.getLogger(BedHeightSingleValue.class);
-
-    private Integer id;
-
-    private BedHeightSingle bedHeight;
-
-    private Double station;
-    private Double height;
-    private Double uncertainty;
-    private Double dataGap;
-    private Double soundingWidth;
-    private Double width;
-
-
-    public BedHeightSingleValue() {
-    }
-
-    public BedHeightSingleValue(
-        BedHeightSingle bedHeight,
-        Double station,
-        Double height,
-        Double uncertainty,
-        Double dataGap,
-        Double soundingWidth,
-        Double width
-    ) {
-        this.bedHeight     = bedHeight;
-        this.station       = station;
-        this.height        = height;
-        this.uncertainty   = uncertainty;
-        this.dataGap       = dataGap;
-        this.soundingWidth = soundingWidth;
-        this.width         = width;
-    }
-
-    @Id
-    @SequenceGenerator(
-        name           = "SEQUENCE_BED_SINGLE_VALUE_ID_SEQ",
-        sequenceName   = "BED_SINGLE_VALUES_ID_SEQ",
-        allocationSize = 1)
-    @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_BED_SINGLE_VALUE_ID_SEQ")
-    @Column(name = "id")
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    @OneToOne
-    @JoinColumn(name = "bed_height_single_id" )
-    public BedHeightSingle getBedHeight() {
-        return bedHeight;
-    }
-
-    public void setBedHeight(BedHeightSingle bedHeight) {
-        this.bedHeight = bedHeight;
-    }
-
-    @Column(name = "station")
-    public Double getStation() {
-        return station;
-    }
-
-    public void setStation(Double station) {
-        this.station = station;
-    }
-
-    @Column(name = "height")
-    public Double getHeight() {
-        return height;
-    }
-
-    public void setHeight(Double height) {
-        this.height = height;
-    }
-
-    @Column(name="uncertainty")
-    public Double getUncertainty() {
-        return uncertainty;
-    }
-
-    public void setUncertainty(Double uncertainty) {
-        this.uncertainty = uncertainty;
-    }
-
-    @Column(name="data_gap")
-    public Double getDataGap() {
-        return dataGap;
-    }
-
-    public void setDataGap(Double dataGap) {
-        this.dataGap = dataGap;
-    }
-
-    @Column(name="sounding_width")
-    //    public BigDecimal getSoundingWidth() {
-    public Double getSoundingWidth() {
-        return soundingWidth;
-    }
-
-    //public void setSoundingWidth(BigDecimal soundingWidth) {
-    public void setSoundingWidth(Double soundingWidth) {
-        this.soundingWidth = soundingWidth;
-    }
-
-    @Column(name="width")
-    public Double getWidth() {
-        return width;
-    }
-
-    public void setWidth(Double width) {
-        this.width = width;
-    }
-
-
-    public static List<BedHeightSingleValue> getBedHeightSingleValues(
-        BedHeightSingle single,
-        double kmLo,
-        double kmHi
-    ) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeightSingleValue 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();
-    }
-}
-// 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/model/BedHeightValue.java	Tue Mar 10 17:01:42 2015 +0100
@@ -0,0 +1,162 @@
+/* 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.model;
+
+import java.util.List;
+
+import java.io.Serializable;
+
+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.GenerationType;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+
+import org.apache.log4j.Logger;
+
+import org.hibernate.Session;
+import org.hibernate.Query;
+
+import org.dive4elements.river.backend.SessionHolder;
+
+
+@Entity
+@Table(name = "bed_height_values")
+public class BedHeightValue
+implements   Serializable
+{
+    private static Logger log =
+        Logger.getLogger(BedHeightValue.class);
+
+    private Integer id;
+
+    private BedHeight bedHeight;
+
+    private Double station;
+    private Double height;
+    private Double uncertainty;
+    private Double dataGap;
+    private Double soundingWidth;
+
+
+    public BedHeightValue() {
+    }
+
+    public BedHeightValue(
+        BedHeight bedHeight,
+        Double station,
+        Double height,
+        Double uncertainty,
+        Double dataGap,
+        Double soundingWidth
+    ) {
+        this.bedHeight     = bedHeight;
+        this.station       = station;
+        this.height        = height;
+        this.uncertainty   = uncertainty;
+        this.dataGap       = dataGap;
+        this.soundingWidth = soundingWidth;
+    }
+
+    @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")
+    @Column(name = "id")
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    @OneToOne
+    @JoinColumn(name = "bed_height_id" )
+    public BedHeight getBedHeight() {
+        return bedHeight;
+    }
+
+    public void setBedHeight(BedHeight bedHeight) {
+        this.bedHeight = bedHeight;
+    }
+
+    @Column(name = "station")
+    public Double getStation() {
+        return station;
+    }
+
+    public void setStation(Double station) {
+        this.station = station;
+    }
+
+    @Column(name = "height")
+    public Double getHeight() {
+        return height;
+    }
+
+    public void setHeight(Double height) {
+        this.height = height;
+    }
+
+    @Column(name="uncertainty")
+    public Double getUncertainty() {
+        return uncertainty;
+    }
+
+    public void setUncertainty(Double uncertainty) {
+        this.uncertainty = uncertainty;
+    }
+
+    @Column(name="data_gap")
+    public Double getDataGap() {
+        return dataGap;
+    }
+
+    public void setDataGap(Double dataGap) {
+        this.dataGap = dataGap;
+    }
+
+    @Column(name="sounding_width")
+    public Double getSoundingWidth() {
+        return soundingWidth;
+    }
+
+    public void setSoundingWidth(Double soundingWidth) {
+        this.soundingWidth = soundingWidth;
+    }
+
+
+    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");
+
+        query.setParameter("single", single);
+        query.setParameter("kmLo", new Double(kmLo));
+        query.setParameter("kmHi", new Double(kmHi));
+
+        return query.list();
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Tue Mar 10 17:01:42 2015 +0100
@@ -1413,5 +1413,7 @@
     String lower_time();
 
     String upper_time();
+
+    String no_data_for_year();
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -751,3 +751,5 @@
 
 lower_time = from
 upper_time = to
+
+no_data_for_year = No data available for: $1
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -743,3 +743,5 @@
 
 lower_time = von
 upper_time = bis
+
+no_data_for_year = F\u00fcr das Jahr $1 liegen keine Daten vor.
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Wed Feb 18 17:17:20 2015 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Tue Mar 10 17:01:42 2015 +0100
@@ -780,3 +780,5 @@
 
 lower_time = from
 upper_time = to
+
+no_data_for_year = No data available for: $1
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterMatrixPanel.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterMatrixPanel.java	Tue Mar 10 17:01:42 2015 +0100
@@ -135,9 +135,6 @@
                 value.setHeight(20);
 
                 cols.addMember(value);
-                HTML hr = new HTML("<hr>");
-                hr.setHeight("3px");
-                cols.addMember(hr);
             }
 
             row.addMember(parameter);
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadEpochPanel.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadEpochPanel.java	Tue Mar 10 17:01:42 2015 +0100
@@ -33,6 +33,7 @@
 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.services.SedimentLoadInfoService;
 import org.dive4elements.river.client.client.services.SedimentLoadInfoServiceAsync;
 import org.dive4elements.river.client.client.ui.AbstractUIProvider;
@@ -52,6 +53,8 @@
     protected SedimentLoadInfoServiceAsync sedLoadInfoService =
         GWT.create(SedimentLoadInfoService.class);
 
+    protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
+
     protected ListGrid elements;
     private TextItem start;
     private TextItem end;
@@ -206,6 +209,35 @@
         sedLoadTable.setEmptyMessage(MSG.empty_table());
         sedLoadTable.setCanReorderFields(false);
 
+        /* Input support pins */
+        String baseUrl = GWT.getHostPageBaseURL();
+        ListGridField pinFrom = new ListGridField ("fromIcon", MESSAGES.from());
+        pinFrom.setWidth (30);
+        pinFrom.setType (ListGridFieldType.ICON);
+        pinFrom.setCellIcon(baseUrl + MESSAGES.markerGreen());
+
+        ListGridField pinTo = new ListGridField ("toIcon", MESSAGES.to());
+        pinTo.setType (ListGridFieldType.ICON);
+        pinTo.setWidth (30);
+        pinTo.setCellIcon(baseUrl + MESSAGES.markerRed());
+
+        pinFrom.addRecordClickHandler (new RecordClickHandler () {
+            @Override
+            public void onRecordClick (RecordClickEvent e) {
+                Record r = e.getRecord();
+                start.setValue(r.getAttribute("date"));
+            }
+        });
+
+        pinTo.addRecordClickHandler (new RecordClickHandler () {
+            @Override
+            public void onRecordClick (RecordClickEvent e) {
+                Record r = e.getRecord();
+                end.setValue(r.getAttribute("date"));
+            }
+        });
+
+
         ListGridField date = new ListGridField("date", MSG.year());
         date.setType(ListGridFieldType.TEXT);
         date.setWidth(100);
@@ -215,7 +247,7 @@
         descr.setType(ListGridFieldType.TEXT);
         descr.setWidth("*");
 
-        sedLoadTable.setFields(date, descr);
+        sedLoadTable.setFields(pinFrom, pinTo, date, descr);
         return sedLoadTable;
     }
 
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadPeriodPanel.java	Wed Feb 18 17:17:20 2015 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadPeriodPanel.java	Tue Mar 10 17:01:42 2015 +0100
@@ -12,7 +12,9 @@
 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;
@@ -24,8 +26,11 @@
 import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.layout.HLayout;
 import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
 
 import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.FLYSConstants;
 import org.dive4elements.river.client.client.services.SedimentLoadInfoService;
 import org.dive4elements.river.client.client.services.SedimentLoadInfoServiceAsync;
 import org.dive4elements.river.client.client.ui.AbstractUIProvider;
@@ -45,35 +50,26 @@
     protected SedimentLoadInfoServiceAsync sedLoadInfoService =
         GWT.create(SedimentLoadInfoService.class);
 
-    private TextItem start;
-    private TextItem end;
+    protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
+
+    private TextItem yearsItem;
 
     private ListGrid sedLoadTable;
 
+    protected List<String> validYears;
+
     public SedLoadPeriodPanel () {
     }
 
     @Override
     public Canvas createOld(DataList dataList) {
         List<Data> items = dataList.getAll();
-        Data start = getData(items, "start");
-        Data end = getData(items, "end");
-        DataItem[] startItem = start.getItems();
-        DataItem[] endItem = end.getItems();
-
-        String v1 = startItem[0].getStringValue();
-        String v2 = endItem[0].getStringValue();
+        Data years = getData(items, "years");
+        DataItem[] yearsItems = years.getItems();
 
-        int v1i = 0;
-        int v2i = 0;
-        try {
-            v1i = Integer.parseInt(v1);
-            v2i = Integer.parseInt(v2);
-        }
-        catch (NumberFormatException nfe) {
-            GWT.log(nfe.toString());
-        }
-        Label old = new Label(v1i + " - " + v2i);
+        String v1 = yearsItems[0].getStringValue().replace(" ", ", ");
+
+        Label old = new Label(v1);
         HLayout layout = new HLayout();
         layout.setWidth("400px");
 
@@ -90,6 +86,11 @@
     }
 
     @Override
+    public List<String> validate() {
+        return validateYears();
+    }
+
+    @Override
     public Canvas create(DataList data) {
         VLayout layout = new VLayout();
 
@@ -126,7 +127,21 @@
         descr.setType(ListGridFieldType.TEXT);
         descr.setWidth("*");
 
-        sedLoadTable.setFields(date, descr);
+        String baseUrl = GWT.getHostPageBaseURL();
+        ListGridField pinFrom = new ListGridField ("fromIcon",  MESSAGES.selection());
+        pinFrom.setWidth (60);
+        pinFrom.setType (ListGridFieldType.ICON);
+        pinFrom.setCellIcon(baseUrl + MESSAGES.markerGreen());
+
+        pinFrom.addRecordClickHandler (new RecordClickHandler () {
+            @Override
+            public void onRecordClick (RecordClickEvent e) {
+                Record r = e.getRecord();
+                appendYear(r.getAttribute("date"));
+            }
+        });
+
+        sedLoadTable.setFields(pinFrom, date, descr);
         return sedLoadTable;
     }
 
@@ -138,14 +153,9 @@
 
         DynamicForm form = new DynamicForm();
         form.setNumCols(4);
-        start = new TextItem(MSG.from());
-        start.setValidators(new IsIntegerValidator());
-        end = new TextItem(MSG.to());
-        end.setValidators(new IsIntegerValidator());
-        form.setFields(start, end);
-//        inputPanel.setToTitle(MSG.to());
-//        inputPanel.setFromTitle(MSG.from());
-//        inputPanel.setShowTitle(false);
+        yearsItem = new TextItem(MSG.years());
+        yearsItem.setValidators(new IsIntegerValidator());
+        form.setFields(yearsItem);
 
         layout.addMember(title);
         layout.addMember(form);
@@ -155,45 +165,66 @@
 
     @Override
     protected Data[] getData() {
-        int v1;
-        int v2;
-        try {
-            v1 = Integer.parseInt(start.getValueAsString());
-            v2 = Integer.parseInt(end.getValueAsString());
-        }
-        catch(NumberFormatException nfe) {
-            // warn the user...
-            return new Data[0];
-        }
-        if (validateRange(v1, v2)) {
+        validateYears();
+        if (yearsItem != null && !yearsItem.getValueAsString().isEmpty()) {
             List<Data> data = new ArrayList<Data>();
 
-            DataItem startItem = new DefaultDataItem("start", "start", start.getValueAsString());
-            DataItem endItem   = new DefaultDataItem("end", "end", end.getValueAsString());
+            DataItem yearsdata = new DefaultDataItem("years", "years", yearsItem.getValueAsString().trim());
             data.add(new DefaultData(
-                "start",
+                "years",
                 null,
                 null,
-                new DataItem[] { startItem }));
-            data.add(new DefaultData(
-                "end",
-                null,
-                null,
-                new DataItem[] { endItem }));
+                new DataItem[] { yearsdata }));
 
             return data.toArray(new Data[data.size()]);
         }
         return new Data[0];
     }
 
-    protected boolean validateRange(int v1, int v2) {
-        // TODO: Set useful years for validation. Current range is between start
-        // of gregorian calendar and a year in the future...
-        if ((v1 > 1582 && v1 < 2100)
-            && (v2 > 1582 && v2 < 2100)) {
-            return true;
+    protected List<String> validateYears() {
+        List<String> errors = new ArrayList<String>();
+        NumberFormat nf     = NumberFormat.getDecimalFormat();
+
+        if (yearsItem.getValueAsString() == null ||
+                yearsItem.getValueAsString().trim().isEmpty()) {
+            errors.add(MESSAGES.empty_filter());
+            return errors;
         }
-        return false;
+
+        String [] sValues = yearsItem.getValueAsString().trim().split(" ");
+        String filtered = "";
+        int goodValues = 0;
+        for (String sValue: sValues) {
+            int value;
+            try {
+                value = Integer.parseInt(sValue);
+            } catch (NumberFormatException e) {
+                errors.add(MESSAGES.wrongFormat());
+                continue;
+            }
+            boolean isGood = false;
+            for (String validYear: validYears) {
+                /* No list contains for strings? */
+                if (sValue.equals(validYear)) {
+                    isGood = true;
+                    break;
+                }
+            }
+            if (!isGood) {
+                String tmp = MESSAGES.no_data_for_year();
+                tmp = tmp.replace("$1", sValue);
+                errors.add(tmp);
+                continue;
+            }
+            goodValues++;
+            if (goodValues > 1) {
+                filtered += " " + Integer.toString(value);
+            } else {
+                filtered = Integer.toString(value);
+            }
+        }
+
+        return errors;
     }
 
    protected void fetchSedimentLoadData() {
@@ -207,6 +238,7 @@
         String river = artifact.getArtifactDescription().getRiver();
 
         String sq_ti_id = "";
+        validYears = new ArrayList<String>(data.length);
         for (int i = 0; i < data.length; i++) {
             Data str = getData(data[i].getAll(), "sq_ti_id");
             if (str != null) {
@@ -246,7 +278,16 @@
         for(SedimentLoadInfoObject sl: sedLoad) {
             SedimentLoadInfoRecord rec = new SedimentLoadInfoRecord(sl);
             sedLoadTable.addData(rec);
+            validYears.add(rec.getDate());
         }
     }
 
+    protected void appendYear (String year) {
+        String oldYears = yearsItem.getValueAsString();
+        if (oldYears != null && !oldYears.isEmpty()) {
+            yearsItem.setValue(oldYears.trim() + " " + year);
+        } else {
+            yearsItem.setValue(year);
+        }
+    }
 }

http://dive4elements.wald.intevation.org