changeset 8961:8a1c6e2ad48b

Implemented datacage for min/max bedheights. Allow to add min/max bed heights as themes to charts.
author gernotbelger
date Wed, 28 Mar 2018 14:35:01 +0200
parents 66ce19d2c5f1
children 708f210ff242
files artifacts/doc/conf/meta-data.xml artifacts/doc/conf/themes.xml artifacts/doc/conf/themes/default.xml artifacts/doc/conf/themes/second.xml artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightMinMaxFacet.java artifacts/src/main/java/org/dive4elements/river/exports/process/BedHeightProcessor.java 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
diffstat 10 files changed, 352 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/meta-data.xml	Wed Mar 28 14:34:55 2018 +0200
+++ b/artifacts/doc/conf/meta-data.xml	Wed Mar 28 14:35:01 2018 +0200
@@ -261,6 +261,9 @@
 
                   <dc:comment> S-INFO </dc:comment>
                   <dc:when test="$out = 'sinfo_flowdepth_minfo_heights'">
+                    <dc:variable name="bed_height_type" expr="''"/>
+                    <dc:variable name="bed_height_descr_prefix" expr="''"/>
+                    <dc:variable name="bedheight_count" expr="'bedh_height_count'"/>
                     <dc:call-macro name="bed-heights-single"/>
                   </dc:when>
                   <dc:when test="$out = 'sinfo_flowdepth_waterlevels'">
@@ -427,7 +430,7 @@
                     <dc:when test="$out = 'map'">
                       <dc:call-macro name="flood-map"/>
                     </dc:when>
-                    
+
                     <dc:when test="$out = 'sinfo_flowdepth_waterlevels'">
                       <dc:call-macro name="longitudinal-section-fix-vollmer_q"/>
                       <!-- TODO: 'Frühere Berechnungen//Bezugswasserstände' -->
@@ -592,35 +595,35 @@
           ($facet_name = 'longitudinal_section.w' or
            $facet_name = 'longitudinal_section.q')
         ">
-          <dc:call-macro name="longitudinal-section-fix-vollmer_macro"/>
+        <dc:call-macro name="longitudinal-section-fix-vollmer_macro"/>
       </dc:filter>
     </dc:macro>
 
     <dc:macro name="longitudinal-section-fix-vollmer_q">
       <dc:filter expr="$a_state = 'state.fix.vollmer.compute' and $facet_name = 'longitudinal_section.q'">
-          <dc:call-macro name="longitudinal-section-fix-vollmer_macro"/>
+        <dc:call-macro name="longitudinal-section-fix-vollmer_macro"/>
       </dc:filter>
     </dc:macro>
 
     <dc:macro name="longitudinal-section-fix-vollmer_macro">
-        <dc:if test="dc:has-result()">
-          <waterlevels_fix_vollmer>
-            <dc:call-macro name="collection-group">
-              <waterlevels description="{dc:group-key()}">
-                <dc:for-each>
-                  <dc:element name="${facet_name}">
-                    <dc:attribute name="description" value="${facet_description}"/>
-                    <dc:attribute name="ids" value="${facet_num}"/>
-                    <dc:attribute name="factory" value="fixanalysis"/>
-                    <dc:attribute name="target_out" value="${out}"/>
-                    <dc:attribute name="artifact-id" value="${a_gid}"/>
-                    <dc:attribute name="out" value="longitudinal_section"/>
-                  </dc:element>
-                </dc:for-each>
-              </waterlevels>
-            </dc:call-macro>
-          </waterlevels_fix_vollmer>
-        </dc:if>
+      <dc:if test="dc:has-result()">
+        <waterlevels_fix_vollmer>
+          <dc:call-macro name="collection-group">
+            <waterlevels description="{dc:group-key()}">
+              <dc:for-each>
+                <dc:element name="${facet_name}">
+                  <dc:attribute name="description" value="${facet_description}"/>
+                  <dc:attribute name="ids" value="${facet_num}"/>
+                  <dc:attribute name="factory" value="fixanalysis"/>
+                  <dc:attribute name="target_out" value="${out}"/>
+                  <dc:attribute name="artifact-id" value="${a_gid}"/>
+                  <dc:attribute name="out" value="longitudinal_section"/>
+                </dc:element>
+              </dc:for-each>
+            </waterlevels>
+          </dc:call-macro>
+        </waterlevels_fix_vollmer>
+      </dc:if>
     </dc:macro>
 
     <dc:macro name="longitudinal-section-fix">
@@ -1601,6 +1604,13 @@
           <dc:call-macro name="flow_velocity_models"/>
         </flow_velocities>
       </minfo>
+
+      <sinfo>
+        <bed_heights_minmax>
+          <dc:call-macro name="minfo-heights-max"/>
+          <dc:call-macro name="minfo-heights-min"/>
+        </bed_heights_minmax>
+      </sinfo>
     </dc:macro>
 
     <dc:macro name="longitudinal-section-user-prototype">
@@ -1953,11 +1963,11 @@
           <dc:for-each>
             <dc:choose>
               <dc:when test="dc:group-key() = $b1year">
-                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b1id}#bedheight-single-{$b2id}" info="{$b1desc}#{$b2desc}" description="{$b1desc} - {$b2desc}"/>
+                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b1id}-{$b1desc}#bedheight-single-{$b2id}-{$b2desc}" info="{$b1desc}#{$b2desc}" description="{$b1desc} - {$b2desc}"/>
               </dc:when>
               <dc:when test="dc:group-key() = 'sonstige'">
-                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b1id}#bedheight-single-{$b2id}" info="{$b1desc}#{$b2desc}" description="{$b1desc} - {$b2desc}"/>
-                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b2id}#bedheight-single-{$b1id}" info="{$b2desc}#{$b1desc}" description="{$b2desc} - {$b1desc}"/>
+                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b1id}-{$b1desc}#bedheight-single-{$b2id}-{$b2desc}" info="{$b1desc}#{$b2desc}" description="{$b1desc} - {$b2desc}"/>
+                <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$b2id}-{$b1desc}#bedheight-single-{$b1id}-{$b2desc}" info="{$b2desc}#{$b1desc}" description="{$b2desc} - {$b1desc}"/>
               </dc:when>
             </dc:choose>
           </dc:for-each>
@@ -1967,14 +1977,39 @@
 
     <dc:macro name="minfo-heights">
       <bedheights>
+        <dc:variable name="bed_height_type" expr="''">
+          <!-- REMARK: empty type for the former, 'normal' bed height -->
+        </dc:variable>
+        <dc:variable name="bed_height_descr_prefix" expr="''"/>
+        <dc:variable name="bedheight_count" expr="'bedh_height_count'"/>
         <dc:call-macro name="bed-heights-single"/>
         <dc:call-macro name="bed-heights-epoch"/>
       </bedheights>
     </dc:macro>
 
+    <dc:macro name="minfo-heights-max">
+      <bedheights_max>
+        <dc:variable name="bed_height_type" expr="'Max'"/>
+        <dc:variable name="bed_height_descr_prefix" expr="'KL-'"/>
+        <dc:variable name="bedheight_count" expr="'bedh_max_count'"/>
+        <dc:call-macro name="bed-heights-single"/>
+        <dc:call-macro name="bed-heights-epoch"/>
+      </bedheights_max>
+    </dc:macro>
+
+    <dc:macro name="minfo-heights-min">
+      <bedheights_min>
+        <dc:variable name="bed_height_type" expr="'Min'"/>
+        <dc:variable name="bed_height_descr_prefix" expr="'TW-'"/>
+        <dc:variable name="bedheight_count" expr="'bedh_min_count'"/>
+        <dc:call-macro name="bed-heights-single"/>
+        <dc:call-macro name="bed-heights-epoch"/>
+      </bedheights_min>
+    </dc:macro>
+
     <dc:macro name="bed-heights-factory">
       <dc:for-each>
-        <height factory="bedheight" target_out="{$out}" ids="bedheight-single-{$bedh_id}-{$bedh_year}" info="{$info}" description="{$bedh_descr}"/>
+        <height factory="bedheight" target_out="{$out}" ids="bedheight-single{$bed_height_type}-{$bedh_id}-{$bedh_year}-{$bed_height_descr_prefix}{$bedh_descr}" info="{$info}" description="{$bed_height_descr_prefix}{$bedh_descr}"/>
       </dc:for-each>
     </dc:macro>
 
@@ -1983,13 +2018,15 @@
         <dc:context>
           <dc:call-macro name="bed-heights-statement"/>
           <dc:filter expr="not(contains($bedh_descr, 'Epoche'))">
-            <dc:if test="dc:has-result()">
-              <dc:group expr="dc:coalesce($bedh_year, 'sonstige')">
-                <heights name="{dc:group-key()}">
-                  <dc:call-macro name="bed-heights-factory"/>
-                </heights>
-              </dc:group>
-            </dc:if>
+            <dc:filter expr="dc:column($bedheight_count) > 0">
+              <dc:if test="dc:has-result()">
+                <dc:group expr="dc:coalesce($bedh_year, 'sonstige')">
+                  <heights name="{dc:group-key()}">
+                    <dc:call-macro name="bed-heights-factory"/>
+                  </heights>
+                </dc:group>
+              </dc:if>
+            </dc:filter>
           </dc:filter>
         </dc:context>
       </single>
@@ -2000,7 +2037,9 @@
         <dc:context>
           <dc:call-macro name="bed-heights-statement"/>
           <dc:filter expr="contains($bedh_descr, 'Epoche')">
-            <dc:call-macro name="bed-heights-factory"/>
+            <dc:filter expr="dc:column($bedheight_count) > 0">
+              <dc:call-macro name="bed-heights-factory"/>
+            </dc:filter>
           </dc:filter>
         </dc:context>
       </epoch>
@@ -2008,7 +2047,7 @@
 
     <dc:macro name="sounding-width-factory">
       <dc:for-each>
-        <height factory="bedheight" target_out="{$out}" ids="bedheight-soundings-{$bedh_id}-{$bedh_year}" info="{$info}" description="{$bedh_descr}"/>
+        <height factory="bedheight" target_out="{$out}" ids="bedheight-soundings-{$bedh_id}-{$bedh_year}-{$bedh_descr}" info="{$info}" description="{$bedh_descr}"/>
       </dc:for-each>
     </dc:macro>
 
@@ -2034,25 +2073,30 @@
 
     <dc:macro name="bed-heights-statement">
       <dc:statement>
-        SELECT bhs.id AS bedh_id,
-        bhs.year AS bedh_year,
-        bhs.description AS bedh_descr,
-        bhs.description || '&lt;BR&gt;Jahr: ' || bhs.year ||
-        '&lt;BR&gt;Aufnahmeart: ' || bht.name ||
-        '&lt;BR&gt;Lagesystem: ' || ls.name ||
-        '&lt;BR&gt;Höhensystem: ' || cur_em.name ||
-        '&lt;BR&gt;ursprüngliches Höhensystem: ' || old_em.name ||
-        '&lt;BR&gt;Strecke: ' || round(r.a, 1) || '-' || round(r.b, 1) ||
-        '&lt;BR&gt;Auswerter: ' || bhs.evaluation_by AS info
-        FROM bed_height bhs
-        JOIN bed_height_type bht ON bht.id =
-        bhs.type_id
-        JOIN location_system ls ON ls.id = location_system_id
-        JOIN elevation_model cur_em ON cur_em.id = cur_elevation_model_id
-        LEFT JOIN elevation_model old_em
-        ON old_em.id = old_elevation_model_id
-        LEFT JOIN ranges r ON r.id = range_id
-        WHERE bhs.river_id = ${river_id}
+         SELECT bhs.id AS bedh_id,
+         bhs.year AS bedh_year,
+         bhs.description AS bedh_descr,
+         bhs.description || '&lt;BR&gt;Jahr: ' || bhs.year ||
+         '&lt;BR&gt;Aufnahmeart: ' || bht.name ||
+         '&lt;BR&gt;Lagesystem: ' || ls.name ||
+         '&lt;BR&gt;Höhensystem: ' || cur_em.name ||
+         '&lt;BR&gt;ursprüngliches Höhensystem: ' || old_em.name ||
+         '&lt;BR&gt;Strecke: ' || round(r.a, 1) || '-' || round(r.b, 1) ||
+         '&lt;BR&gt;Auswerter: ' || bhs.evaluation_by AS info,
+         bhv.height_count AS bedh_height_count,
+         bhv.min_count AS bedh_min_count,
+         bhv.max_count AS bedh_max_count
+         FROM bed_height bhs
+         JOIN bed_height_type bht ON bht.id = bhs.type_id
+         JOIN location_system ls ON ls.id = location_system_id
+         JOIN elevation_model cur_em ON cur_em.id = cur_elevation_model_id
+         LEFT JOIN elevation_model old_em
+         ON old_em.id = old_elevation_model_id
+         LEFT JOIN ranges r ON r.id = range_id
+         LEFT JOIN (SELECT bed_height_id, COUNT(height) AS height_count, COUNT(min_height) AS min_count, COUNT(max_height) AS max_count
+           FROM bed_height_values GROUP BY bed_height_id
+         ) bhv ON bhs.id = bhv.bed_height_id
+         WHERE bhs.river_id = ${river_id}
       </dc:statement>
     </dc:macro>
 
@@ -3080,8 +3124,8 @@
           w.description AS wst_description,
           COALESCE(wc.name, '') AS wst_column_name,
           wr.a AS deffrom,
-          wr.b AS defto,
-          w.sinfo_selection
+          wr.b AS defto,
+          w.sinfo_selection
           FROM wst_columns wc
           JOIN wsts w ON wc.wst_id = w.id
           JOIN wst_ranges wr ON wc.id = wr.wst_column_id
--- a/artifacts/doc/conf/themes.xml	Wed Mar 28 14:34:55 2018 +0200
+++ b/artifacts/doc/conf/themes.xml	Wed Mar 28 14:35:01 2018 +0200
@@ -406,6 +406,9 @@
         <mapping from="porosity" to="Porosity" />
 
         <!--  Mappings for S-INFO -->
+        <mapping from="bedheight_min" to="SInfoBedHeightMin" />
+        <mapping from="bedheight_max" to="SInfoBedHeightMax" />
+        
         <mapping from="sinfo_facet_flow_depth.filtered" to="SInfoFlowDepth" />
         <mapping from="sinfo_facet_flow_depth_with_tkh.filtered" to="SInfoFlowDepthWithTkh" />
         <mapping from="sinfo_facet_flow_depth_min.filtered" to="SInfoFlowDepthMin" />
--- a/artifacts/doc/conf/themes/default.xml	Wed Mar 28 14:34:55 2018 +0200
+++ b/artifacts/doc/conf/themes/default.xml	Wed Mar 28 14:35:01 2018 +0200
@@ -2873,6 +2873,24 @@
         </fields>
     </theme>
 
+    <!-- S-INFO Data-Themes -->
+    <theme name="SInfoBedHeightMin">
+        <inherits>
+            <inherit from="LongitudinalSectionW" />
+        </inherits>
+        <fields>
+            <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+        </fields>
+    </theme>      
+    <theme name="SInfoBedHeightMax">
+        <inherits>
+            <inherit from="LongitudinalSectionW" />
+        </inherits>
+        <fields>
+            <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 0" />
+        </fields>
+    </theme>
+
     <!-- S-INFO Flow-Depth Themes -->
     <theme name="SInfoFlowDepth">
         <inherits>
--- a/artifacts/doc/conf/themes/second.xml	Wed Mar 28 14:34:55 2018 +0200
+++ b/artifacts/doc/conf/themes/second.xml	Wed Mar 28 14:35:01 2018 +0200
@@ -2861,6 +2861,24 @@
         </fields>
     </theme>
 
+    <!-- S-INFO Data-Themes -->
+    <theme name="SInfoBedHeightMin">
+        <inherits>
+            <inherit from="LongitudinalSectionW" />
+        </inherits>
+        <fields>
+            <field name="linecolor" type="Color" display="Linienfarbe" default="0, 255, 0" />
+        </fields>
+    </theme>      
+    <theme name="SInfoBedHeightMax">
+        <inherits>
+            <inherit from="LongitudinalSectionW" />
+        </inherits>
+        <fields>
+            <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 0" />
+        </fields>
+    </theme>
+
     <!-- S-INFO Flow-Depth Themes -->
     <theme name="SInfoFlowDepth">
         <inherits>
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java	Wed Mar 28 14:34:55 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/BedHeightsArtifact.java	Wed Mar 28 14:35:01 2018 +0200
@@ -12,47 +12,42 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-import org.w3c.dom.Document;
-
 import org.dive4elements.artifactdatabase.state.DefaultOutput;
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifactdatabase.state.FacetActivity;
+import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.ArtifactFactory;
-import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.minfo.BedHeightFacet;
-import org.dive4elements.river.artifacts.model.minfo.BedHeightFactory;
+import org.dive4elements.river.artifacts.model.minfo.BedHeightMinMaxFacet;
+import org.dive4elements.river.artifacts.model.minfo.BedHeightMinMaxFacet.BedHeightValueType;
 import org.dive4elements.river.artifacts.model.minfo.BedHeightSoundingWidthFacet;
+import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.artifacts.states.StaticState;
-
-import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.exports.process.BedHeightProcessor;
+import org.w3c.dom.Document;
 
-public class BedHeightsArtifact
-extends      AbstractStaticStateArtifact
-implements   FacetTypes
-{
+public class BedHeightsArtifact extends AbstractStaticStateArtifact implements FacetTypes {
     /** The log for this class. */
-    private static Logger log =
-        Logger.getLogger(BedHeightsArtifact.class);
+    private static Logger log = Logger.getLogger(BedHeightsArtifact.class);
 
     /** Artifact name. */
     private static final String NAME = "bedheights";
 
     static {
         // TODO: Move to configuration.
-        FacetActivity.Registry.getInstance()
-            .register(NAME, FacetActivity.INACTIVE);
+        FacetActivity.Registry.getInstance().register(NAME, FacetActivity.INACTIVE);
     }
 
-    public static final String STATIC_STATE_NAME =
-        "state.additional_bedheights.static";
+    public static final String STATIC_STATE_NAME = "state.additional_bedheights.static";
 
-    /** Data Item name to know whether we are Heighmarks and receive
-     * some data slightly different. */
-    public static final String DATA_HEIGHT_TYPE =
-        "height_marks";
+    /**
+     * Data Item name to know whether we are Heighmarks and receive
+     * some data slightly different.
+     */
+    public static final String DATA_HEIGHT_TYPE = "height_marks";
 
     /**
      * Trivial Constructor.
@@ -70,74 +65,61 @@
      * Gets called from factory, to set things up.
      */
     @Override
-    public void setup(
-        String          identifier,
-        ArtifactFactory factory,
-        Object          context,
-        CallMeta        callMeta,
-        Document        data,
-        List<Class>     loadFacets)
-    {
+    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
+            final List<Class> loadFacets) {
         log.debug("BedHeightsArtifact.setup");
 
         if (log.isDebugEnabled()) {
             log.debug(XMLUtils.toString(data));
         }
 
-        String code = getDatacageIDValue(data);
-
-        if (code != null) {
-            String [] parts = code.split("-");
-
-            if (parts.length >= 3) {
-                // The setting is a bit complicated:
-                // This artifact can spawn epoch type bedheight facets,
-                // 'singlevalue'/singleyear bedheight facets or
-                // sounding-width facets. The type is indicated by
-                // the ids-param which comes from datacage.
-
-                String name = parts[0];
-                String type = parts[1];
-                String facetType = BEDHEIGHT;
-                if (type.equals("soundings")) {
-                    type = "singlevalues";
-                    facetType = BEDHEIGHT_SOUNDING_WIDTH;
-                }
-                addStringData("height_id", parts[2]);
-                addStringData("type", type);
-                String btype = type;
-                int hId = Integer.parseInt(parts[2]);
+        final String code = getDatacageIDValue(data);
 
-                if (type.equals("singlevalues")) {
-                    btype = "single";
-                }
-
-                String bedHName = BedHeightFactory.getHeightName(btype, hId);
+        createFacets(callMeta, code);
 
-                Facet facet =  null;
-                if (facetType.equals(BEDHEIGHT_SOUNDING_WIDTH)) {
-                    bedHName = Resources.getMsg(
-                        callMeta,
-                        "facet.bedheight.sounding_width",
-                        new Object[] { bedHName });
-                    facet = new BedHeightSoundingWidthFacet(
-                        facetType, bedHName);
-                }
-                else {
-                    facet = new BedHeightFacet(facetType, bedHName);
-                }
+        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+    }
 
-
-                ArrayList<Facet> facets = new ArrayList<Facet>(1);
-                facets.add(facet);
+    private void createFacets(final CallMeta callMeta, final String code) {
+        if (code == null)
+            return;
 
-                addFacets(STATIC_STATE_NAME, facets);
-            }
-            else {
-                log.error("Invalid datacage ID '" + code + "'");
-            }
+        final String[] parts = code.split("-", 5);
+        if (parts.length < 5) {
+            log.error("Invalid datacage ID '" + code + "'");
+            return;
         }
-        super.setup(identifier, factory, context, callMeta, data, loadFacets);
+
+        // String name = parts[0];
+
+        // type may only be 'single' or 'soundings'
+        final String type = parts[1];
+
+        final String heightId = parts[2];
+        // final int hId = Integer.parseInt(heightId);
+
+        // final String year = parts[3];
+        final String bedHName = parts[4];
+
+        addStringData("height_id", heightId);
+        if (type.equals("soundings"))
+            addStringData("type", "singlevalues");
+        else
+            addStringData("type", type);
+
+        final ArrayList<Facet> facets = new ArrayList<>(1);
+
+        if ("soundings".equals(type)) {
+            final String description = Resources.getMsg(callMeta, "facet.bedheight.sounding_width", new Object[] { bedHName });
+            facets.add(new BedHeightSoundingWidthFacet(BEDHEIGHT_SOUNDING_WIDTH, description));
+        } else if ("single".equals(type))
+            facets.add(new BedHeightFacet(BEDHEIGHT, bedHName));
+        else if ("singleMin".equals(type))
+            facets.add(new BedHeightMinMaxFacet(BedHeightProcessor.FACET_BED_HEIGHTS_MIN, bedHName, BedHeightValueType.min));
+        else if ("singleMax".equals(type))
+            facets.add(new BedHeightMinMaxFacet(BedHeightProcessor.FACET_BED_HEIGHTS_MAX, bedHName, BedHeightValueType.max));
+
+        addFacets(STATIC_STATE_NAME, facets);
     }
 
     @Override
@@ -145,14 +127,10 @@
 
         log.debug("initStaticState " + getName() + " " + identifier());
 
-        StaticState state = new StaticState(STATIC_STATE_NAME);
-        DefaultOutput output = new DefaultOutput(
-                "general",
-                "general",
-                "image/png",
-                "chart");
+        final StaticState state = new StaticState(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", "chart");
 
-        List<Facet> facets = getFacets(STATIC_STATE_NAME);
+        final List<Facet> facets = getFacets(STATIC_STATE_NAME);
         output.addFacets(facets);
         state.addOutput(output);
 
@@ -160,20 +138,15 @@
     }
 
     @Override
-    protected void initialize(
-        Artifact artifact,
-        Object context,
-        CallMeta meta
-    ) {
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
         // do not clone facets, etc. from master artifact
 
         log.debug("initialize");
-        importData((D4EArtifact)artifact, "river");
-        importData((D4EArtifact)artifact, "ld_from");
-        importData((D4EArtifact)artifact, "ld_to");
+        importData((D4EArtifact) artifact, "river");
+        importData((D4EArtifact) artifact, "ld_from");
+        importData((D4EArtifact) artifact, "ld_to");
 
         log.debug("ld_from " + getDataAsString("ld_from"));
         log.debug("ld_to " + getDataAsString("ld_to"));
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightMinMaxFacet.java	Wed Mar 28 14:35:01 2018 +0200
@@ -0,0 +1,123 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.model.minfo;
+
+import java.util.List;
+
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.access.BedHeightAccess;
+import org.dive4elements.river.artifacts.model.BlackboardDataFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.model.BedHeight;
+import org.dive4elements.river.model.BedHeightValue;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * More or less the same as {@link BedHeightFacet}, but was necessary to copy because else we break the old
+ * serialization.
+ *
+ * @author Gernot Belger
+ */
+public class BedHeightMinMaxFacet extends BlackboardDataFacet implements FacetTypes {
+
+    private static final long serialVersionUID = 1L;
+
+    public static enum BedHeightValueType {
+        min {
+            @Override
+            public Double getValue(final BedHeightValue bedheightValue) {
+                return bedheightValue.getMinHeight();
+            }
+        },
+        max {
+            @Override
+            public Double getValue(final BedHeightValue bedheightValue) {
+                return bedheightValue.getMaxHeight();
+            }
+        },
+        value {
+            @Override
+            public Double getValue(final BedHeightValue bedheightValue) {
+                return bedheightValue.getHeight();
+            }
+        };
+
+        public abstract Double getValue(final BedHeightValue bedheightValue);
+    }
+
+    private final BedHeightValueType valueType;
+
+    public BedHeightMinMaxFacet(final String name, final String description, final BedHeightValueType valueType) {
+        super(0, name, description);
+
+        this.valueType = valueType;
+
+        this.metaData.put("X", "chart.longitudinal.section.xaxis.label");
+        this.metaData.put("Y", "chart.bedheight_middle.section.yaxis.label");
+    }
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact
+     *            the owner artifact.
+     * @param context
+     *            the CallContext (ignored).
+     *
+     * @return the data.
+     */
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
+
+        final BedHeightAccess access = new BedHeightAccess((D4EArtifact) artifact);
+
+        final BedHeight single = BedHeight.getBedHeightById(access.getHeightId());
+
+        final List<BedHeightValue> bedheightValues = BedHeightValue.getBedHeightValues(single, access.getFrom(true), access.getTo(true));
+
+        final TDoubleArrayList stations = new TDoubleArrayList(bedheightValues.size());
+        final TDoubleArrayList values = new TDoubleArrayList(bedheightValues.size());
+
+        for (final BedHeightValue bedheightValue : bedheightValues) {
+
+            final Double station = bedheightValue.getStation();
+            final Double value = this.valueType.getValue(bedheightValue);
+
+            if (station != null && value != null) {
+                stations.add(station);
+                values.add(value);
+            }
+        }
+
+        this.addMetaData(Resources.getMsg(context.getMeta(), "meta.bedheight.cur.elevation"), single.getCurElevationModel().getName());
+
+        if (single.getOldElevationModel() != null)
+            this.addMetaData(Resources.getMsg(context.getMeta(), "meta.bedheight.old.elevation"), single.getOldElevationModel().getName());
+
+        this.addMetaData(Resources.getMsg(context.getMeta(), "meta.bedheight.river.elevation"), access.getRiver().getWstUnit().getName());
+
+        return new double[][] { stations.toNativeArray(), values.toNativeArray() };
+    }
+
+    /**
+     * Create a deep copy of this Facet.
+     *
+     * @return a deep copy.
+     */
+    @Override
+    public BedHeightMinMaxFacet deepCopy() {
+        final BedHeightMinMaxFacet copy = new BedHeightMinMaxFacet(this.name, this.description, this.valueType);
+        copy.set(this);
+        return copy;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedHeightProcessor.java	Wed Mar 28 14:34:55 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedHeightProcessor.java	Wed Mar 28 14:35:01 2018 +0200
@@ -35,6 +35,10 @@
     public static final String I18N_AXIS_LABEL =
         "chart.bedheight_middle.section.yaxis.label";
 
+    public final static String FACET_BED_HEIGHTS_MIN = "bedheight_min";
+
+    public final static String FACET_BED_HEIGHTS_MAX = "bedheight_min";
+    
     protected static final double GAP_TOLERANCE = 0.101d;
 
     protected String yAxisLabel;
@@ -101,6 +105,8 @@
     @Override
     public boolean canHandle(String facetType) {
         return FacetTypes.BEDHEIGHT.equals(facetType)
+            || FACET_BED_HEIGHTS_MIN.equals(facetType)
+            || FACET_BED_HEIGHTS_MAX.equals(facetType)
             || FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT1.equals(facetType)
             || FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT2.equals(facetType)
             || FacetTypes.BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED.equals(
@@ -127,4 +133,4 @@
                 I18N_AXIS_LABEL,
                 new Object[] { unit });
     }
-}
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Wed Mar 28 14:34:55 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Wed Mar 28 14:35:01 2018 +0200
@@ -1473,5 +1473,10 @@
     String sinfo_flowdepthminmax_export();
 
     String sinfo_flowdepthdevelopment_export();
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
\ No newline at end of file
+
+    String bed_heights_minmax();
+
+    String bedheights_max();
+
+    String bedheights_min();
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Wed Mar 28 14:34:55 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Wed Mar 28 14:35:01 2018 +0200
@@ -782,4 +782,8 @@
 sinfo_d50s = Korndurchmesser
 
 sinfo_flowdepthminmax_export = min/max Flie\u00dftiefen Export
-sinfo_flowdepthdevelopment_export = Flie\u00dftiefenentwicklung Export
\ No newline at end of file
+sinfo_flowdepthdevelopment_export = Flie\u00dftiefenentwicklung Export
+
+bed_heights_minmax = Minimale/maximale Sohlh\u00f6he
+bedheights_max = Kammlage
+bedheights_min = Talweg
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Wed Mar 28 14:34:55 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Wed Mar 28 14:35:01 2018 +0200
@@ -782,4 +782,8 @@
 sinfo_d50s = Korndurchmesser
 
 sinfo_flowdepthminmax_export = min/max Flie\u00dftiefen Export
-sinfo_flowdepthdevelopment_export = Flie\u00dftiefenentwicklung Export
\ No newline at end of file
+sinfo_flowdepthdevelopment_export = Flie\u00dftiefenentwicklung Export
+
+bed_heights_minmax = Minimale/maximale Sohlh\u00f6he
+bedheights_max = Kammlage
+bedheights_min = Talweg
\ No newline at end of file

http://dive4elements.wald.intevation.org