changeset 9425:3f49835a00c3

Extended CrossSectionFacet so it may fetch different data from within the artifact result. Also allows to have acces to the potentially already computed artifact result via its normal computation cache.
author gernotbelger
date Fri, 17 Aug 2018 15:31:02 +0200
parents da19f1f58d72
children b6e595f1696f
files artifacts/src/main/java/org/dive4elements/river/artifacts/FixationArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/ManualPointsArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/WaterLineArtifact.java artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractCalculationResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionWaterLineFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/DataFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/RelativePointFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/DischargeLongitudinalSection.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/ManualPointsSingleState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticWQKmsState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelInfoState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelSelectState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/ExtremeCompute.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixRealizingCompute.java
diffstat 22 files changed, 637 insertions(+), 849 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/FixationArtifact.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/FixationArtifact.java	Fri Aug 17 15:31:02 2018 +0200
@@ -8,34 +8,29 @@
 
 package org.dive4elements.river.artifacts;
 
-import org.dive4elements.artifacts.CallContext;
+import java.io.Serializable;
 
-import org.dive4elements.river.artifacts.geom.Lines;
-
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.WKms;
 import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult;
-
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
 
-import org.dive4elements.river.model.FastCrossSectionLine;
-
-import org.apache.log4j.Logger;
-
 /**
  * The default fixation analysis artifact.
  *
  * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
-public class FixationArtifact
-extends      D4EArtifact
-implements   WaterLineArtifact
-{
+public class FixationArtifact extends D4EArtifact implements WaterLineArtifact {
+
+    private static final long serialVersionUID = 1L;
+
     /** The log for this class. */
     private static Logger log = Logger.getLogger(FixationArtifact.class);
 
     /** The name of the artifact. */
-    public static final String ARTIFACT_NAME = "fixanalysis";
+    private static final String ARTIFACT_NAME = "fixanalysis";
 
     /* FacetActivity for this artifact is registered in FixAnalysisCompute . */
 
@@ -58,33 +53,22 @@
 
     /** Calculate waterlines against a cross section. */
     @Override
-    public Lines.LineData getWaterLines(
-        int                  facetIdx,
-        FastCrossSectionLine      csl,
-        double                      d,
-        double                      w,
-        CallContext           context
-    ) {
-        FixRealizingResult result = (FixRealizingResult)
-            ((CalculationResult)this.compute(
-                context, ComputeType.ADVANCE, false)).getData();
+    public double getWaterLevel(final ComputeType type, final String hash, final String stateId, final double currentKm, final Serializable waterLineIndex,
+            final double nextKm, final double prevKm, final CallContext context) {
+        final FixRealizingResult result = (FixRealizingResult) ((CalculationResult) this.compute(context, ComputeType.ADVANCE, false)).getData();
 
-        WKms wkms = result.getWQKms()[facetIdx];
+        final int wstIndex = (Integer) waterLineIndex;
 
-        double km = csl.getKm();
+        final WKms wkms = result.getWQKms()[wstIndex];
 
         // Find W at km.
-        double wAtKm;
-
-        wAtKm = StaticWKmsArtifact.getWAtKm(wkms, km);
+        final double wAtKm = StaticWKmsArtifact.getWAtKm(wkms, currentKm);
 
         if (wAtKm == -1 || Double.isNaN(wAtKm)) {
-            log.warn("Waterlevel at km " + km + " unknown.");
-            return new Lines.LineData(new double[][] {{}}, 0d, 0d);
+            log.warn("Waterlevel at km " + currentKm + " unknown.");
+            return Double.NaN;
         }
 
-        // This should be FixRealizationResult, which can be getWQKms()ed
-        return Lines.createWaterLines(csl.getPoints(), wAtKm);
+        return wAtKm;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/ManualPointsArtifact.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/ManualPointsArtifact.java	Fri Aug 17 15:31:02 2018 +0200
@@ -8,33 +8,28 @@
 
 package org.dive4elements.river.artifacts;
 
-import java.awt.geom.Point2D;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.log4j.Logger;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.w3c.dom.Document;
-
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.ArtifactFactory;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.CallMeta;
-import org.dive4elements.river.artifacts.geom.Lines;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.states.DefaultState;
-import org.dive4elements.river.model.FastCrossSectionLine;
-
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.w3c.dom.Document;
 
 /**
  * Artifact to store user-added points and water lines.
  */
-public class ManualPointsArtifact
-extends      StaticD4EArtifact
-implements   FacetTypes, WaterLineArtifact
-{
+public class ManualPointsArtifact extends StaticD4EArtifact implements FacetTypes, WaterLineArtifact {
+
     private static final long serialVersionUID = 7096025125474986011L;
 
     /** The log for this class. */
@@ -43,116 +38,101 @@
     /** The name of the artifact. */
     public static final String ARTIFACT_NAME = "manualpoints";
 
-
     public ManualPointsArtifact() {
         log.debug("ManualPointsArtifact.ManualPointsArtifact()");
     }
 
-
     /**
      * 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("ManualPointsArtifact.setup");
         super.setup(identifier, factory, context, callMeta, data, loadFacets);
         initialize(null, context, callMeta);
     }
 
-
     /** Return the name of this artifact. */
     @Override
     public String getName() {
         return ARTIFACT_NAME;
     }
 
-
     /** Access state data storing the jsonstring with points. */
-    public String getPointsData(String facetName) {
+    public String getPointsData(final String facetName) {
         return getDataAsString(facetName + ".data");
     }
 
-
     /**
      * Access state data storing the jsonstring with lines.
-     * @param facetName Name of facet or null if the so far
-     *                  only known case should be picked.
+     *
+     * @param facetName
+     *            Name of facet or null if the so far
+     *            only known case should be picked.
      * @return (String) value of data element (expect json).
      */
-    public String getLinesData(String facetName) {
+    private String getLinesData(final String facetName) {
         if (facetName == null)
             return getDataAsString("cross_section.manualpoints.lines");
         // TODO .lineS?
         return getDataAsString(facetName + ".line");
     }
 
-
     /** Setup state and facet. */
     @Override
-    protected void initialize(
-        Artifact artifact,
-        Object context,
-        CallMeta meta
-    ) {
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
         log.debug("ManualPointsArtifact.initialize");
-        List<Facet> fs = new ArrayList<Facet>();
+        final List<Facet> fs = new ArrayList<>();
 
-        DefaultState state = (DefaultState) getCurrentState(context);
+        final DefaultState state = (DefaultState) getCurrentState(context);
         state.computeInit(this, hash(), context, meta, fs);
         if (!fs.isEmpty()) {
             log.debug("Facets to add in ManualPointsArtifact.initialize .");
             addFacets(getCurrentStateId(), fs);
-        }
-        else {
-            log.debug("No facets to add in ManualPointsArtifact.initialize ("
-                    + state.getID() + ").");
+        } else {
+            log.debug("No facets to add in ManualPointsArtifact.initialize (" + state.getID() + ").");
         }
     }
 
-
     /**
      * Get value of line at index.
-     * @param index index in json array defining lines.
+     *
+     * @param index
+     *            index in json array defining lines.
      * @return water height of line at given index.
      */
-    protected double getLine(int index) {
+    private double getLine(final int index) {
         try {
-            JSONArray lines = new JSONArray(getLinesData(null));
-            JSONArray array = lines.getJSONArray(index);
+            final JSONArray lines = new JSONArray(getLinesData(null));
+            final JSONArray array = lines.getJSONArray(index);
 
             return array.getDouble(0);
         }
-        catch(JSONException e){
-            log.error("Could not decode json for line.");
+        catch (final JSONException e) {
+            log.error("Could not decode json for line.", e);
             return 0d;
         }
     }
 
-
     /**
      * Get the water line "surface".
-     * @param index index of facets data.
-     * @param csl 'ground' against which to determine water surface.
-     * @param a (ignored in this implementation).
-     * @param b (ignored in this implementation).
-     * @param context (ignored in this implementation).
+     *
+     * @param index
+     *            index of facets data.
+     * @param csl
+     *            'ground' against which to determine water surface.
+     * @param a
+     *            (ignored in this implementation).
+     * @param b
+     *            (ignored in this implementation).
+     * @param context
+     *            (ignored in this implementation).
      */
     @Override
-    public Lines.LineData getWaterLines(
-            int                  index,
-            FastCrossSectionLine csl,
-            double a, double b,
-            CallContext context
-            ) {
-        List<Point2D> points = csl.getPoints();
-        return Lines.createWaterLines(points, getLine(index));
+    public double getWaterLevel(final ComputeType type, final String hash, final String stateId, final double currentKm, final Serializable waterLineIndex,
+            final double nextKm, final double prevKm, final CallContext context) {
+        final int index = (int) waterLineIndex;
+        return getLine(index);
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java	Fri Aug 17 15:31:02 2018 +0200
@@ -8,43 +8,31 @@
 
 package org.dive4elements.river.artifacts;
 
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
 import org.dive4elements.artifactdatabase.state.DefaultOutput;
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifactdatabase.state.FacetActivity;
 import org.dive4elements.artifactdatabase.state.State;
-
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.ArtifactFactory;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.CallMeta;
-
 import org.dive4elements.artifacts.common.utils.XMLUtils;
-
-import org.dive4elements.river.artifacts.geom.Lines;
-
 import org.dive4elements.river.artifacts.math.Distance;
 import org.dive4elements.river.artifacts.math.Linear;
-
 import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.RelativePointFacet;
 import org.dive4elements.river.artifacts.model.WKms;
 import org.dive4elements.river.artifacts.model.WKmsFacet;
 import org.dive4elements.river.artifacts.model.WKmsFactory;
-
 import org.dive4elements.river.artifacts.resources.Resources;
-
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
 import org.dive4elements.river.artifacts.states.StaticState;
-
-import org.dive4elements.river.model.FastCrossSectionLine;
-
-import java.awt.geom.Point2D;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
 import org.w3c.dom.Document;
 
 /**
@@ -54,34 +42,28 @@
  * This artifact neglects (Static)D4EArtifacts capabilities of interaction
  * with the StateEngine by overriding the getState*-methods.
  */
-public class StaticWKmsArtifact
-extends      StaticD4EArtifact
-implements   FacetTypes, WaterLineArtifact
-{
+public class StaticWKmsArtifact extends StaticD4EArtifact implements FacetTypes, WaterLineArtifact {
     /** The log for this class. */
-    private static Logger log =
-        Logger.getLogger(StaticWKmsArtifact.class);
+    private static Logger log = Logger.getLogger(StaticWKmsArtifact.class);
 
     private static final String NAME = "staticwkms";
 
     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_wkms.static";
+    public static final String STATIC_STATE_NAME = "state.additional_wkms.static";
 
-    /** Data Item name to know whether we are Heighmarks and reveive
-     * some data slightly different. */
-    public static final String DATA_HEIGHT_TYPE =
-        "height_marks";
+    /**
+     * Data Item name to know whether we are Heighmarks and reveive
+     * some data slightly different.
+     */
+    public static final String DATA_HEIGHT_TYPE = "height_marks";
 
     /** One and only state to be in. */
     protected transient State state = null;
 
-
     /**
      * Trivial Constructor.
      */
@@ -98,40 +80,34 @@
      * 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("StaticWKmsArtifact.setup");
 
-        state = new StaticState(STATIC_STATE_NAME);
+        this.state = new StaticState(STATIC_STATE_NAME);
 
         if (log.isDebugEnabled()) {
             log.debug(XMLUtils.toString(data));
         }
 
-        List<Facet> fs = new ArrayList<Facet>();
-        String code = getDatacageIDValue(data);
+        final List<Facet> fs = new ArrayList<>();
+        final String code = getDatacageIDValue(data);
 
         // TODO Go for JSON, one day.
-        //ex.: flood_protection-wstv-114-12
+        // ex.: flood_protection-wstv-114-12
         if (code != null) {
-            String [] parts = code.split("-");
+            final String[] parts = code.split("-");
 
             if (parts.length >= 4) {
                 int col = -1;
-                int wst = Integer.parseInt(parts[3]);
+                final int wst = Integer.parseInt(parts[3]);
 
                 if (!parts[2].equals("A")) {
                     col = Integer.parseInt(parts[2]);
                 }
 
                 addStringData("col_pos", parts[2]);
-                addStringData("wst_id",  parts[3]);
+                addStringData("wst_id", parts[3]);
 
                 String wkmsName;
                 if (col >= 0) {
@@ -140,8 +116,7 @@
                     // but slower execution (it wrappes based on kind
                     // which can be fetched in same sql query).
                     wkmsName = WKmsFactory.getWKmsNameWWrapped(col, wst);
-                }
-                else {
+                } else {
                     wkmsName = WKmsFactory.getWKmsNameWWrapped(wst);
                 }
 
@@ -149,33 +124,25 @@
                 if (parts[0].equals(HEIGHTMARKS_POINTS)) {
                     name = HEIGHTMARKS_POINTS;
                     addStringData(DATA_HEIGHT_TYPE, "true");
-                }
-                else if (parts[0].equals("additionalsmarks")) {
+                } else if (parts[0].equals("additionalsmarks")) {
                     name = STATIC_WKMS_MARKS;
-                }
-                else if (parts[0].equals("delta_w")) {
+                } else if (parts[0].equals("delta_w")) {
                     name = STATIC_DELTA_W;
-                }
-                else if (parts[0].equals("delta_w_cma")) {
+                } else if (parts[0].equals("delta_w_cma")) {
                     name = STATIC_DELTA_W_CMA;
-                }
-                else {
+                } else {
                     name = STATIC_WKMS;
                 }
 
-                String facetDescription = Resources.getMsg(
-                    callMeta, wkmsName, wkmsName);
-                Facet wKmsFacet = new WKmsFacet(
-                    name,
-                    facetDescription);
-                Facet csFacet = new CrossSectionWaterLineFacet(0,
-                    facetDescription);
-                Facet rpFacet = new RelativePointFacet(facetDescription);
+                final String facetDescription = Resources.getMsg(callMeta, wkmsName, wkmsName);
+                final Facet wKmsFacet = new WKmsFacet(name, facetDescription);
+                final Facet csFacet = new CrossSectionWaterLineFacet(0, facetDescription, null, null, null, null);
+                final Facet rpFacet = new RelativePointFacet(facetDescription);
 
                 fs.add(wKmsFacet);
                 fs.add(csFacet);
                 fs.add(rpFacet);
-                addFacets(state.getID(), fs);
+                addFacets(this.state.getID(), fs);
             }
         }
 
@@ -183,119 +150,109 @@
         super.setup(identifier, factory, context, callMeta, data, loadFacets);
     }
 
-
     /**
      * Initialize the static state with output.
+     *
      * @return static state
      */
     protected State spawnState() {
-        state = new StaticState(STATIC_STATE_NAME);
-        List<Facet> fs = getFacets(STATIC_STATE_NAME);
-        DefaultOutput output = new DefaultOutput(
-            "general",
-            "general", "image/png",
-            fs,
-            "chart");
+        this.state = new StaticState(STATIC_STATE_NAME);
+        final List<Facet> fs = getFacets(STATIC_STATE_NAME);
+        final DefaultOutput output = new DefaultOutput("general", "general", "image/png", fs, "chart");
 
-        state.getOutputs().add(output);
-        return state;
+        this.state.getOutputs().add(output);
+        return this.state;
     }
 
-
     /**
      * Called via setup.
      *
-     * @param artifact The master-artifact.
+     * @param artifact
+     *            The master-artifact.
      */
     @Override
-    protected void initialize(
-        Artifact artifact,
-        Object context,
-        CallMeta meta)
-    {
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
         log.debug("StaticWKmsArtifact.initialize");
-        D4EArtifact winfo = (D4EArtifact) artifact;
+        final D4EArtifact winfo = (D4EArtifact) artifact;
         // TODO: The river is of no interest, so far.
         addData("river", winfo.getData("river"));
     }
 
-
     /**
      * Get a list containing the one and only State.
-     * @param  context ignored.
+     *
+     * @param context
+     *            ignored.
      * @return list with one and only state.
      */
     @Override
-    protected List<State> getStates(Object context) {
-        ArrayList<State> states = new ArrayList<State>();
+    protected List<State> getStates(final Object context) {
+        final ArrayList<State> states = new ArrayList<>();
         states.add(getState());
         return states;
     }
 
-
     /**
      * Get the "current" state (there is but one).
-     * @param cc ignored.
+     *
+     * @param cc
+     *            ignored.
      * @return the "current" (only possible) state.
      */
     @Override
-    public State getCurrentState(Object cc) {
+    public State getCurrentState(final Object cc) {
         return getState();
     }
 
-
     /**
      * Get the only possible state.
+     *
      * @return the state.
      */
     protected State getState() {
         return getState(null, null);
     }
 
-
     /**
      * Get the state.
-     * @param context ignored.
-     * @param stateID ignored.
+     *
+     * @param context
+     *            ignored.
+     * @param stateID
+     *            ignored.
      * @return the state.
      */
     @Override
-    protected State getState(Object context, String stateID) {
-        return (state != null)
-            ? state
-            : spawnState();
+    protected State getState(final Object context, final String stateID) {
+        return (this.state != null) ? this.state : spawnState();
     }
 
-
     /**
      * Get WKms from factory.
-     * @param idx param is not needed (TODO?)
+     *
+     * @param idx
+     *            param is not needed (TODO?)
      * @return WKms according to parameterization (can be null);
      */
-    public WKms getWKms(int idx) {
+    public WKms getWKms() {
         log.debug("StaticWKmsArtifact.getWKms");
 
-        return WKmsFactory.getWKms(
-            Integer.parseInt(getDataAsString("col_pos")),
-            Integer.parseInt(getDataAsString("wst_id")));
+        return WKmsFactory.getWKms(Integer.parseInt(getDataAsString("col_pos")), Integer.parseInt(getDataAsString("wst_id")));
     }
 
-    public WKms getWKms(int idx, double from, double to) {
+    public WKms getWKms(final double from, final double to) {
         log.debug("StaticWKmsArtifact.getWKms");
 
-        return WKmsFactory.getWKms(
-            Integer.parseInt(getDataAsString("col_pos")),
-            Integer.parseInt(getDataAsString("wst_id")),
-            from, to);
+        return WKmsFactory.getWKms(Integer.parseInt(getDataAsString("col_pos")), Integer.parseInt(getDataAsString("wst_id")), from, to);
     }
 
     /**
      * Returns W at Km of WKms, linearly interpolated.
      * Returns -1 if not found.
      */
-    public static double getWAtKmLin(WKms wkms, double km) {
+    public static double getWAtKmLin(final WKms wkms, final double km) {
         // Uninformed search.
-        int size = wkms.size();
+        final int size = wkms.size();
         if (size == 0) {
             return -1;
         }
@@ -304,70 +261,59 @@
         boolean kmIncreasing;
         if (size == 1) {
             kmIncreasing = true;
-        }
-        else {
-            kmIncreasing = (wkms.getKm(0) < wkms.getKm(wkms.size()-1))
-                ? true : false;
+        } else {
+            kmIncreasing = (wkms.getKm(0) < wkms.getKm(wkms.size() - 1)) ? true : false;
         }
         if (kmIncreasing) {
             while (idx < size && wkms.getKm(idx) < km) {
                 idx++;
             }
-        }
-        else {
-            idx = wkms.size() -1;
+        } else {
+            idx = wkms.size() - 1;
             while (idx > 0 && wkms.getKm(idx) > km) {
                 idx--;
             }
         }
 
-       if (wkms.getKm(idx) == km) {
-           return wkms.getW(idx);
-       }
+        if (wkms.getKm(idx) == km) {
+            return wkms.getW(idx);
+        }
 
-        if (idx == size -1 || idx == 0) {
+        if (idx == size - 1 || idx == 0) {
             return -1;
         }
 
         // Do linear interpolation.
-        int mod = kmIncreasing ? -1 : +1;
-        return Linear.linear(
-            km,
-            wkms.getKm(idx+mod),
-            wkms.getKm(idx),
-            wkms.getW(idx+mod),
-            wkms.getW(idx)
-        );
+        final int mod = kmIncreasing ? -1 : +1;
+        return Linear.linear(km, wkms.getKm(idx + mod), wkms.getKm(idx), wkms.getW(idx + mod), wkms.getW(idx));
     }
 
-
     /**
      * Get the W at a specific km, only if it is closer to km than to any of
      * the other given km.
      * Return Double.NaN otherwise
      *
-     * @param wkms WKms in which to search for a spatially close W value.
-     * @param km the input km, which is compared to values from wkms.
-     * @param next the next available input km (-1 if unavailable).
-     * @param prev the previous available input km (-1 if unavailable).
+     * @param wkms
+     *            WKms in which to search for a spatially close W value.
+     * @param km
+     *            the input km, which is compared to values from wkms.
+     * @param next
+     *            the next available input km (-1 if unavailable).
+     * @param prev
+     *            the previous available input km (-1 if unavailable).
      *
      * @return W in wkms that is closer to km than to next and prev,
      *         or Double.NaN.
      */
-    public double getWAtCloseKm(
-        WKms wkms,
-        double km,
-        double next,
-        double prev
-    ) {
+    public double getWAtCloseKm(final WKms wkms, final double km, final double next, final double prev) {
         // TODO symbolic "-1" pr next/prev is a bad idea (tm), as we compare
-        //      distances to these values later.
+        // distances to these values later.
         // TODO issue888
 
-        int size = wkms.size();
+        final int size = wkms.size();
         for (int i = 0; i < size; i++) {
-            double wkmsKm = wkms.getKm(i);
-            double dist = Distance.distance(wkmsKm, km);
+            final double wkmsKm = wkms.getKm(i);
+            final double dist = Distance.distance(wkmsKm, km);
             if (dist == 0d) {
                 return wkms.getW(i);
             }
@@ -377,19 +323,18 @@
             //
             // Standard case:
             // ----------|----X-----|-------
-            //     (1)    (2)    (3)   (4)
+            // (1) (2) (3) (4)
             //
             // With prev==-1
             // -1 ------X-------|------
-            //    (5)      (6)     (7)
+            // (5) (6) (7)
             //
             // With next==-1
             //
             // ---|-----X----- -1
-            // (8)  (9)   (10)
+            // (8) (9) (10)
 
-            if (dist <= Distance.distance(wkmsKm, prev)
-                && dist <= Distance.distance(wkmsKm, next)) {
+            if (dist <= Distance.distance(wkmsKm, prev) && dist <= Distance.distance(wkmsKm, next)) {
                 return wkms.getW(i);
             }
         }
@@ -397,70 +342,62 @@
         return Double.NaN;
     }
 
-
     /**
      * Returns W at Km of WKms, searching linearly.
      * Returns -1 if not found.
-     * @param wkms the WKms object to search for given km.
-     * @param km The searched km.
+     *
+     * @param wkms
+     *            the WKms object to search for given km.
+     * @param km
+     *            The searched km.
      * @return W at given km if in WKms, -1 if not found.
      */
-    public static double getWAtKm(WKms wkms, double km) {
+    public static double getWAtKm(final WKms wkms, final double km) {
+
         // Uninformed search, intolerant.
-        double TOLERANCE = 0.0d;
-        int size = wkms.size();
+        final double TOLERANCE = 0.0d;
+        final int size = wkms.size();
+        if (size == 0)
+            return Double.NaN;
+
         for (int i = 0; i < size; i++) {
             if (Distance.within(wkms.getKm(i), km, TOLERANCE)) {
                 return wkms.getW(i);
             }
         }
 
-        return -1;
+        return Double.NaN;
     }
 
-
     /**
      * Get points of line describing the surface of water at cross section.
      *
-     * @param idx Index of facet and in wkms array.
-     * @param csl FastCrossSectionLine to compute water surface agains.
-     * @param next The km of the next crosssectionline.
-     * @param prev The km of the previous crosssectionline.
-     * @param context Ignored in this implementation.
+     * @param idx
+     *            Index of facet and in wkms array.
+     * @param csl
+     *            FastCrossSectionLine to compute water surface agains.
+     * @param next
+     *            The km of the next crosssectionline.
+     * @param prev
+     *            The km of the previous crosssectionline.
+     * @param context
+     *            Ignored in this implementation.
      *
      * @return an array holding coordinates of points of surface of water (
      *         in the form {{x1, x2}, {y1, y2}} ).
      */
     @Override
-    public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl,
-        double next, double prev, CallContext context
-    ) {
-        log.debug("getWaterLines(" + idx + ")/" + identifier());
+    public double getWaterLevel(final ComputeType type, final String hash, final String stateId, final double currentKm, final Serializable waterLineIndex,
+            final double nextKm, final double prevKm, final CallContext context) {
 
-        List<Point2D> points = csl.getPoints();
-
-        WKms wkms = getWKms(0);
-
-        double km = csl.getKm();
+        final WKms wkms = getWKms();
 
         // Find W at km.
-        double wAtKm;
 
         // If heightmarks, only deliver if data snaps.
-        if (getDataAsString(DATA_HEIGHT_TYPE) != null &&
-            getDataAsString(DATA_HEIGHT_TYPE).equals("true")) {
-            wAtKm = getWAtCloseKm(wkms, km, next, prev);
-        }
-        else {
-            wAtKm = getWAtKm(wkms, km);
-        }
+        if (getDataAsString(DATA_HEIGHT_TYPE) != null && getDataAsString(DATA_HEIGHT_TYPE).equals("true"))
+            return getWAtCloseKm(wkms, currentKm, nextKm, prevKm);
 
-        if (wAtKm == -1 || Double.isNaN(wAtKm)) {
-            log.warn("Waterlevel at km " + km + " unknown.");
-            return new Lines.LineData(new double[][] {{}}, 0d, 0d);
-        }
-
-        return Lines.createWaterLines(points, wAtKm);
+        return getWAtKm(wkms, currentKm);
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java	Fri Aug 17 15:31:02 2018 +0200
@@ -8,36 +8,26 @@
 
 package org.dive4elements.river.artifacts;
 
-import java.awt.geom.Point2D;
-
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.w3c.dom.Document;
-
 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.CallContext;
 import org.dive4elements.artifacts.CallMeta;
-
 import org.dive4elements.artifacts.common.utils.XMLUtils;
-
-import org.dive4elements.river.artifacts.geom.Lines;
-
 import org.dive4elements.river.artifacts.model.FacetTypes;
-import org.dive4elements.river.model.FastCrossSectionLine;
 import org.dive4elements.river.artifacts.model.WKms;
-import org.dive4elements.river.artifacts.model.WQKms;
 import org.dive4elements.river.artifacts.model.WKmsFactory;
+import org.dive4elements.river.artifacts.model.WQKms;
 import org.dive4elements.river.artifacts.model.WQKmsFactory;
-
 import org.dive4elements.river.artifacts.states.DefaultState;
-
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.w3c.dom.Document;
 
 /**
  * Artifact to access additional "waterlevel/discharge"-type of data, like
@@ -46,34 +36,23 @@
  * This artifact neglects (Static)D4EArtifacts capabilities of interaction
  * with the StateEngine by overriding the getState*-methods.
  */
-public class StaticWQKmsArtifact
-extends      StaticD4EArtifact
-implements   FacetTypes, WaterLineArtifact
-{
+public class StaticWQKmsArtifact extends StaticD4EArtifact implements FacetTypes, WaterLineArtifact {
     /** The log for this class. */
-    private static Logger log =
-        Logger.getLogger(StaticWQKmsArtifact.class);
+    private static Logger log = Logger.getLogger(StaticWQKmsArtifact.class);
 
-    public static final String STATIC_STATE_NAME =
-        "state.additional_wqkms.static";
+    public static final String STATIC_STATE_NAME = "state.additional_wqkms.static";
 
     private static final String NAME = "staticwqkms";
 
     static {
         // TODO: Move to configuration.
-        FacetActivity.Registry.getInstance().register(
-            NAME,
-            new FacetActivity() {
-                @Override
-                public Boolean isInitialActive(
-                    Artifact artifact,
-                    Facet    facet,
-                    String   outputName
-                ) {
-                    String fname = facet.getName();
-                    return (fname.equals(STATIC_WQKMS)
-                        || fname.equals(STATIC_WQKMS_W));
-                }});
+        FacetActivity.Registry.getInstance().register(NAME, new FacetActivity() {
+            @Override
+            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String outputName) {
+                final String fname = facet.getName();
+                return (fname.equals(STATIC_WQKMS) || fname.equals(STATIC_WQKMS_W));
+            }
+        });
     }
 
     /**
@@ -83,7 +62,6 @@
         log.debug("StaticWQKmsArtifact.StaticWQKmsArtifact");
     }
 
-
     /**
      * Gets called from factory, to set things up.
      *
@@ -92,14 +70,8 @@
      * case handling.
      */
     @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("StaticWQKmsArtifact.setup");
 
         // Store the 'ids' (from datacage).
@@ -107,23 +79,22 @@
             log.debug("StaticWQKmsArtifact.setup" + XMLUtils.toString(data));
         }
 
-        String code = getDatacageIDValue(data);
+        final String code = getDatacageIDValue(data);
         addStringData("ids", code);
         if (code != null) {
-            String [] parts = code.split("-");
+            final String[] parts = code.split("-");
 
             if (parts.length >= 1) {
-                boolean official = parts[0].toLowerCase()
-                    .startsWith("official");
+                final boolean official = parts[0].toLowerCase().startsWith("official");
                 addStringData("official", official ? "1" : "0");
             }
 
             if (parts.length >= 4) {
-                int col = Integer.parseInt(parts[2]);
-                int wst = Integer.parseInt(parts[3]);
+                final int col = Integer.parseInt(parts[2]);
+                final int wst = Integer.parseInt(parts[3]);
 
                 addStringData("col_pos", parts[2]);
-                addStringData("wst_id",  parts[3]);
+                addStringData("wst_id", parts[3]);
             }
         }
 
@@ -131,70 +102,65 @@
         super.setup(identifier, factory, context, callMeta, data, loadFacets);
     }
 
-
     /**
      * Called via setup.
      *
-     * @param artifact The master-artifact.
+     * @param artifact
+     *            The master-artifact.
      */
     @Override
-    protected void initialize(
-        Artifact artifact,
-        Object context,
-        CallMeta meta)
-    {
+    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
         log.debug("StaticWQKmsArtifact.initialize");
-        D4EArtifact flys = (D4EArtifact) artifact;
+        final D4EArtifact flys = (D4EArtifact) artifact;
         // TODO: The river is of no interest, so far., also use importData
         importData(flys, "river");
 
-        List<Facet> fs = new ArrayList<Facet>();
+        final List<Facet> fs = new ArrayList<>();
 
-        DefaultState state = (DefaultState) getCurrentState(context);
+        final DefaultState state = (DefaultState) getCurrentState(context);
         state.computeInit(this, hash(), context, meta, fs);
         if (!fs.isEmpty()) {
             log.debug("Facets to add in StaticWQKmsArtifact.initialize .");
             addFacets(getCurrentStateId(), fs);
-        }
-        else {
-            log.debug("No facets to add in StaticWQKmsArtifact.initialize ("
-                + state.getID() + ").");
+        } else {
+            log.debug("No facets to add in StaticWQKmsArtifact.initialize (" + state.getID() + ").");
         }
     }
 
-
     /**
      * Get WQKms from factory.
+     *
      * @return WQKms according to parameterization (can be null);
      */
     public WQKms getWQKms() {
         log.debug("StaticWQKmsArtifact.getWQKms");
 
-        int col = Integer.parseInt(getDataAsString("col_pos"));
-        int wst = Integer.parseInt(getDataAsString("wst_id"));
+        final int col = Integer.parseInt(getDataAsString("col_pos"));
+        final int wst = Integer.parseInt(getDataAsString("wst_id"));
 
         /** TODO do not run twice against db to do this. */
-        String wkmsName = WKmsFactory.getWKmsName(col, wst);
+        final String wkmsName = WKmsFactory.getWKmsName(col, wst);
 
-        WQKms res = WQKmsFactory.getWQKms(col, wst);
+        final WQKms res = WQKmsFactory.getWQKms(col, wst);
         res.setName(wkmsName);
         return res;
     }
 
     /**
      * Get WQKms from factory.
+     *
      * @return WQKms according to parameterization (can be null);
      */
     public WQKms getWQKms(final double from, final double to) {
         log.debug("StaticWQKmsArtifact.getWQKms");
-        
-        int col = Integer.parseInt(getDataAsString("col_pos"));
-        int wst = Integer.parseInt(getDataAsString("wst_id"));
-        
+
+        final int col = Integer.parseInt(getDataAsString("col_pos"));
+        final int wst = Integer.parseInt(getDataAsString("wst_id"));
+
         /** TODO do not run twice against db to do this. */
-        String wkmsName = WKmsFactory.getWKmsName(col, wst);
-        
-        WQKms res = WQKmsFactory.getWQKms(col, wst, from, to);
+        final String wkmsName = WKmsFactory.getWKmsName(col, wst);
+
+        final WQKms res = WQKmsFactory.getWQKms(col, wst, from, to);
         res.setName(wkmsName);
         return res;
     }
@@ -205,52 +171,38 @@
         return NAME;
     }
 
-
     /**
      * Get points of line describing the surface of water at cross section.
      *
-     * @param idx Index of facet and in wkms array.
-     * @param csl FastCrossSectionLine to compute water surface agains.
-     * @param next The km of the next crosssectionline.
-     * @param prev The km of the previous crosssectionline.
-     * @param context Ignored in this implementation.
+     * @param idx
+     *            Index of facet and in wkms array.
+     * @param csl
+     *            FastCrossSectionLine to compute water surface agains.
+     * @param next
+     *            The km of the next crosssectionline.
+     * @param prev
+     *            The km of the previous crosssectionline.
+     * @param context
+     *            Ignored in this implementation.
      *
      * @return an array holding coordinates of points of surface of water (
      *         in the form {{x1, x2}, {y1, y2}} ).
      */
     @Override
-    public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl,
-        double next, double prev, CallContext context
-    ) {
-        log.debug("getWaterLines(" + idx + ")/" + identifier());
+    public double getWaterLevel(final ComputeType type, final String hash, final String stateId, final double currentKm, final Serializable waterLineIndex,
+            final double nextKm, final double prevKm, final CallContext context) {
 
-        List<Point2D> points = csl.getPoints();
-
-        WKms wkms = getWQKms();
-
-        double km = csl.getKm();
+        final WKms wkms = getWQKms();
 
         // Find W at km.
-        double wAtKm;
+        final double wAtKm = StaticWKmsArtifact.getWAtKm(wkms, currentKm);
 
-        // If heightmarks, only deliver if data snaps.
-        /*
-        if (getDataAsString(DATA_HEIGHT_TYPE) != null &&
-            getDataAsString(DATA_HEIGHT_TYPE).equals("true")) {
-            wAtKm = getWAtCloseKm(wkms, km, next, prev);
-        }
-        else {
-        */
-            wAtKm = StaticWKmsArtifact.getWAtKm(wkms, km);
-        //}
-
-        if (wAtKm == -1 || Double.isNaN(wAtKm)) {
-            log.warn("Waterlevel at km " + km + " unknown.");
-            return new Lines.LineData(new double[][] {{}}, 0d, 0d);
+        if (Double.isNaN(wAtKm)) {
+            log.warn("Waterlevel at km " + currentKm + " unknown.");
+            return Double.NaN;
         }
 
-        return Lines.createWaterLines(points, wAtKm);
+        return wAtKm;
     }
     // TODO implement deepCopy.
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java	Fri Aug 17 15:31:02 2018 +0200
@@ -8,28 +8,27 @@
 
 package org.dive4elements.river.artifacts;
 
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
 import org.dive4elements.artifactdatabase.data.StateData;
-
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifactdatabase.state.FacetActivity;
-
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
-
 import org.dive4elements.artifacts.common.utils.StringUtils;
-
 import org.dive4elements.river.artifacts.access.Calculation4Access;
+import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
 import org.dive4elements.river.artifacts.access.RangeAccess;
 import org.dive4elements.river.artifacts.access.RiverAccess;
-import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
-import org.dive4elements.river.artifacts.geom.Lines;
-
+import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.Calculation1;
 import org.dive4elements.river.artifacts.model.Calculation2;
 import org.dive4elements.river.artifacts.model.Calculation3;
 import org.dive4elements.river.artifacts.model.Calculation4;
 import org.dive4elements.river.artifacts.model.Calculation5;
-import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.DischargeTables;
 import org.dive4elements.river.artifacts.model.FacetTypes;
@@ -38,38 +37,22 @@
 import org.dive4elements.river.artifacts.model.WW;
 import org.dive4elements.river.artifacts.model.WstValueTable;
 import org.dive4elements.river.artifacts.model.WstValueTableFactory;
-
 import org.dive4elements.river.artifacts.model.extreme.ExtremeResult;
-
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
-
 import org.dive4elements.river.model.DischargeTable;
-import org.dive4elements.river.model.FastCrossSectionLine;
 import org.dive4elements.river.model.Gauge;
 import org.dive4elements.river.model.River;
-
 import org.dive4elements.river.utils.DoubleUtil;
 import org.dive4elements.river.utils.RiverUtils;
 
 import gnu.trove.TDoubleArrayList;
 
-import java.awt.geom.Point2D;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-
-
 /**
  * The default WINFO artifact.
  *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class WINFOArtifact
-extends      D4EArtifact
-implements   FacetTypes, WaterLineArtifact {
+public class WINFOArtifact extends D4EArtifact implements FacetTypes, WaterLineArtifact {
 
     /** The log for this class. */
     private static Logger log = Logger.getLogger(WINFOArtifact.class);
@@ -78,40 +61,28 @@
     public static final String ARTIFACT_NAME = "winfo";
 
     /** XPath */
-    public static final String XPATH_STATIC_UI =
-        "/art:result/art:ui/art:static";
+    public static final String XPATH_STATIC_UI = "/art:result/art:ui/art:static";
 
-    /** The default number of steps between the start end end of a selected Q
-     * range. */
+    /**
+     * The default number of steps between the start end end of a selected Q
+     * range.
+     */
     public static final int DEFAULT_Q_STEPS = 30;
 
-    private static final String [] INACTIVES = new String[] {
-        LONGITUDINAL_Q,
-        DURATION_Q,
-        STATIC_WQKMS_Q
-    };
+    private static final String[] INACTIVES = new String[] { LONGITUDINAL_Q, DURATION_Q, STATIC_WQKMS_Q };
 
     static {
         // TODO: Move to configuration.
-        FacetActivity.Registry.getInstance().register(
-            ARTIFACT_NAME,
-            new FacetActivity() {
-                @Override
-                public Boolean isInitialActive(
-                    Artifact artifact,
-                    Facet    facet,
-                    String   outputName
-                ) {
-                    String fname = facet.getName();
-                    if ((fname.equals(MAINVALUES_Q)
-                        || fname.equals(MAINVALUES_W))
-                        && outputName.equals("computed_discharge_curve"))
-                    {
-                        return Boolean.FALSE;
-                    }
-                    return !StringUtils.contains(fname, INACTIVES);
+        FacetActivity.Registry.getInstance().register(ARTIFACT_NAME, new FacetActivity() {
+            @Override
+            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String outputName) {
+                final String fname = facet.getName();
+                if ((fname.equals(MAINVALUES_Q) || fname.equals(MAINVALUES_W)) && outputName.equals("computed_discharge_curve")) {
+                    return Boolean.FALSE;
                 }
-            });
+                return !StringUtils.contains(fname, INACTIVES);
+            }
+        });
     }
 
     /**
@@ -120,8 +91,6 @@
     public WINFOArtifact() {
     }
 
-
-
     /**
      * Returns the name of the concrete artifact.
      *
@@ -132,15 +101,12 @@
         return ARTIFACT_NAME;
     }
 
-    protected static boolean reportGeneratedWs(
-        Calculation report,
-        double []   ws
-    ) {
+    protected static boolean reportGeneratedWs(final Calculation report, final double[] ws) {
         if (ws == null || ws.length < 2) {
             return false;
         }
 
-        double  lastW = ws[0];
+        double lastW = ws[0];
         boolean alreadyReported = false;
 
         for (int i = 1; i < ws.length; ++i) {
@@ -149,8 +115,7 @@
                     alreadyReported = true;
                     report.addProblem("more.than.one.q.for.w", ws[i]);
                 }
-            }
-            else {
+            } else {
                 alreadyReported = false;
             }
             lastW = ws[i];
@@ -159,7 +124,6 @@
         return true;
     }
 
-
     //
     // METHODS FOR RETRIEVING COMPUTED DATA FOR DIFFERENT CHART TYPES
     //
@@ -183,60 +147,59 @@
      *
      * @return an array of data triples that consist of W, Q and Kms.
      */
-    public CalculationResult getWaterlevelData(CallContext context)
-    {
+    public CalculationResult getWaterlevelData(final CallContext context) {
         log.debug("WINFOArtifact.getWaterlevelData");
 
-        String calculationMode = getDataAsString("calculation_mode");
+        final String calculationMode = getDataAsString("calculation_mode");
 
         // If this WINFO-Artifact has a calculation trait.
-        if (calculationMode != null) 
-        {
+        if (calculationMode != null) {
             if (calculationMode.equals("calc.discharge.longitudinal.section"))
                 return getDischargeLongitudinalSectionData();
 
-            if (calculationMode.equals("calc.extreme.curve")) 
-                return (CalculationResult)this.compute(context, ComputeType.ADVANCE, false);
+            if (calculationMode.equals("calc.extreme.curve"))
+                return (CalculationResult) this.compute(context, ComputeType.ADVANCE, false);
 
-            if (calculationMode.equals("calc.w.differences")) 
-                return (CalculationResult)this.compute(context, ComputeType.ADVANCE, true);
-            
+            if (calculationMode.equals("calc.w.differences"))
+                return (CalculationResult) this.compute(context, ComputeType.ADVANCE, true);
+
             log.warn("Unhandled calculation_mode " + calculationMode);
         }
-        
+
         // Otherwise get it from parameterization.
-        // TODO: wrong comment: now always a waterlevle computation is executed; actually there is a calc_mode for that, why dont check?
+        // TODO: wrong comment: now always a waterlevle computation is executed; actually there is a calc_mode for that, why
+        // dont check?
         return computeWaterlevelData();
     }
 
     /** Execu5tes the calculation of 'waterlevel', fetches all input data from this artifact */
     private CalculationResult computeWaterlevelData() {
         final double[] kms = new ComputationRangeAccess(this).getKms();
-        if (kms == null) 
+        if (kms == null)
             return error(new WQKms[0], "no.kms.selected");
 
         return computeWaterlevelData(kms);
     }
-    
-    /** 
+
+    /**
      * Execu5tes the calculation of 'waterlevel'.
      * Allows to override the stations for which the calculation is done. All other inputs are fetched from this artifact.
      */
     public final CalculationResult computeWaterlevelData(final double kms[]) {
 
         final River river = new RiverAccess(this).getRiver();
-        if (river == null) 
+        if (river == null)
             return error(new WQKms[0], "no.river.selected");
 
-        double[] qs   = getQs();
-        double[] ws   = null;
+        double[] qs = getQs();
+        double[] ws = null;
 
-        Calculation report = new Calculation();
+        final Calculation report = new Calculation();
 
         if (qs == null) {
             log.debug("Determine Q values based on a set of W values.");
-            ws   = getWs();
-            double [][] qws = getQsForWs(ws, report);
+            ws = getWs();
+            final double[][] qws = getQsForWs(ws, report);
             if (qws == null || qws.length == 0) {
                 return error(new WQKms[0], "converting.ws.to.qs.failed");
             }
@@ -247,13 +210,13 @@
             }
         }
 
-        WstValueTable wst = WstValueTableFactory.getTable(river);
+        final WstValueTable wst = WstValueTableFactory.getTable(river);
         if (wst == null) {
             return error(new WQKms[0], "no.wst.for.selected.river");
         }
 
-        RangeAccess rangeAccess = new RangeAccess(this);
-        double [] range = rangeAccess.getKmRange();
+        final RangeAccess rangeAccess = new RangeAccess(this);
+        final double[] range = rangeAccess.getKmRange();
         if (range == null) {
             return error(new WQKms[0], "no.range.found");
         }
@@ -263,46 +226,39 @@
         if (isFreeQ() || isFreeW()) {
             refKm = range[0];
             log.debug("'free' calculation (km " + refKm + ")");
-        }
-        else {
-            Gauge gauge = river.determineRefGauge(
-                range, rangeAccess.isRange());
+        } else {
+            final Gauge gauge = river.determineRefGauge(range, rangeAccess.isRange());
 
             if (gauge == null) {
-                return error(
-                    new WQKms[0], "no.gauge.found.for.km", range[0]);
+                return error(new WQKms[0], "no.gauge.found.for.km", range[0]);
             }
 
             refKm = gauge.getStation().doubleValue();
 
-            log.debug(
-                "reference gauge: " + gauge.getName() + " (km " + refKm + ")");
+            log.debug("reference gauge: " + gauge.getName() + " (km " + refKm + ")");
         }
 
-        return computeWaterlevelData(kms, qs, ws, wst, refKm, report);        
+        return computeWaterlevelData(kms, qs, ws, wst, refKm, report);
     }
 
     /**
      * Computes the data of a waterlevel computation based on the interpolation
      * in WstValueTable.
      *
-     * @param kms The kilometer values.
-     * @param qs The discharge values.
-     * @param wst The WstValueTable used for the interpolation.
+     * @param kms
+     *            The kilometer values.
+     * @param qs
+     *            The discharge values.
+     * @param wst
+     *            The WstValueTable used for the interpolation.
      *
      * @return an array of data triples that consist of W, Q and Kms.
      */
-    private static CalculationResult computeWaterlevelData(
-        double []     kms,
-        double []     qs,
-        double []     ws,
-        WstValueTable wst,
-        double        refKm,
-        Calculation   report
-    ) {
+    private static CalculationResult computeWaterlevelData(final double[] kms, final double[] qs, final double[] ws, final WstValueTable wst,
+            final double refKm, final Calculation report) {
         log.info("WINFOArtifact.computeWaterlevelData");
 
-        Calculation1 calc1 = new Calculation1(kms, qs, ws, refKm);
+        final Calculation1 calc1 = new Calculation1(kms, qs, ws, refKm);
 
         if (report != null) {
             calc1.addProblems(report);
@@ -311,7 +267,6 @@
         return calc1.calculate(wst);
     }
 
-
     /**
      * Returns the data that is computed by a duration curve computation.
      *
@@ -320,24 +275,24 @@
     public CalculationResult getDurationCurveData() {
         log.debug("WINFOArtifact.getDurationCurveData");
 
-        RangeAccess rangeAccess = new RangeAccess(this);
+        final RangeAccess rangeAccess = new RangeAccess(this);
 
-        River r = rangeAccess.getRiver();
+        final River r = rangeAccess.getRiver();
         if (r == null) {
             return error(null, "no.river.selected");
         }
 
-        double[] locations = rangeAccess.getLocations();
+        final double[] locations = rangeAccess.getLocations();
         if (locations == null) {
             return error(null, "no.locations.selected");
         }
 
-        Gauge g = r.determineGaugeByPosition(locations[0]);
+        final Gauge g = r.determineGaugeByPosition(locations[0]);
         if (g == null) {
-           return error(null, "no.gauge.selected");
+            return error(null, "no.gauge.selected");
         }
 
-        WstValueTable wst = WstValueTableFactory.getTable(r);
+        final WstValueTable wst = WstValueTableFactory.getTable(r);
         if (wst == null) {
             return error(null, "no.wst.for.river");
         }
@@ -345,57 +300,51 @@
         return computeDurationCurveData(g, wst, locations[0]);
     }
 
-
     /**
      * Computes the data used to create duration curves.
      *
-     * @param gauge The selected gauge.
-     * @param location The selected location.
+     * @param gauge
+     *            The selected gauge.
+     * @param location
+     *            The selected location.
      *
      * @return the computed data.
      */
-    private static CalculationResult computeDurationCurveData(
-        Gauge         gauge,
-        WstValueTable wst,
-        double        location)
-    {
+    private static CalculationResult computeDurationCurveData(final Gauge gauge, final WstValueTable wst, final double location) {
         log.info("WINFOArtifact.computeDurationCurveData");
 
-        Object[] obj = gauge.fetchDurationCurveData();
+        final Object[] obj = gauge.fetchDurationCurveData();
 
-        int[]    days = (int[]) obj[0];
-        double[] qs   = (double[]) obj[1];
+        final int[] days = (int[]) obj[0];
+        final double[] qs = (double[]) obj[1];
 
-        Calculation3 calculation = new Calculation3(location, days, qs);
+        final Calculation3 calculation = new Calculation3(location, days, qs);
 
         return calculation.calculate(wst);
     }
 
-
     /**
      * Returns the data that is computed by a discharge curve computation.
      *
      * @return the data computed by a discharge curve computation.
      */
-    public CalculationResult getComputedDischargeCurveData()
-    throws NullPointerException
-    {
+    public CalculationResult getComputedDischargeCurveData() throws NullPointerException {
         log.debug("WINFOArtifact.getComputedDischargeCurveData");
 
-        River r = RiverUtils.getRiver(this);
+        final River r = RiverUtils.getRiver(this);
 
         if (r == null) {
             return error(new WQKms[0], "no.river.selected");
         }
 
-        RangeAccess rangeAccess = new RangeAccess(this);
-        double[] locations = rangeAccess.getLocations();
+        final RangeAccess rangeAccess = new RangeAccess(this);
+        final double[] locations = rangeAccess.getLocations();
 
         if (locations == null) {
             return error(new WQKms[0], "no.locations.selected");
         }
 
-        WstValueTable wst = WstValueTableFactory.getTable(r);
+        final WstValueTable wst = WstValueTableFactory.getTable(r);
         if (wst == null) {
             return error(new WQKms[0], "no.wst.for.river");
         }
@@ -403,84 +352,75 @@
         return computeDischargeCurveData(wst, locations[0]);
     }
 
-
     /**
      * Computes the data used to create computed discharge curves.
      *
-     * @param wst The WstValueTable that is used for the interpolation (river-
+     * @param wst
+     *            The WstValueTable that is used for the interpolation (river-
      *            bound).
-     * @param location The location where the computation should be based on.
+     * @param location
+     *            The location where the computation should be based on.
      *
      * @return an object that contains tuples of W/Q values at the specified
-     * location.
+     *         location.
      */
-    private static CalculationResult computeDischargeCurveData(
-        WstValueTable wst,
-        double location)
-    {
+    private static CalculationResult computeDischargeCurveData(final WstValueTable wst, final double location) {
         log.info("WINFOArtifact.computeDischargeCurveData");
 
-        Calculation2 calculation = new Calculation2(location);
+        final Calculation2 calculation = new Calculation2(location);
 
         return calculation.calculate(wst);
     }
 
-
     /** Create CalculationResult with data and message. */
-    protected static final CalculationResult error(Object data, String msg) {
+    protected static final CalculationResult error(final Object data, final String msg) {
         return new CalculationResult(data, new Calculation(msg));
     }
 
     /** Create CalculationResult with data and message with args. */
-    protected static final CalculationResult error(
-        Object data,
-        String msg,
-        Object ... args
-    ) {
+    protected static final CalculationResult error(final Object data, final String msg, final Object... args) {
         return new CalculationResult(data, new Calculation(msg, args));
     }
 
-
     /**
      * Returns the data that is computed by a reference curve computation.
      *
      * @return the data computed by a reference curve computation.
      */
-    public CalculationResult getReferenceCurveData(CallContext context) {
+    public CalculationResult getReferenceCurveData(final CallContext context) {
 
-        Double startKm = getReferenceStartKm();
+        final Double startKm = getReferenceStartKm();
 
         if (startKm == null) {
             return error(new WW[0], "no.reference.start.km");
         }
 
-        double [] endKms = getReferenceEndKms();
+        final double[] endKms = getReferenceEndKms();
 
         if (endKms == null || endKms.length == 0) {
             return error(new WW[0], "no.reference.end.kms");
         }
 
-        Calculation5 calc5 = new Calculation5(startKm, endKms);
+        final Calculation5 calc5 = new Calculation5(startKm, endKms);
 
-        River r = RiverUtils.getRiver(this);
+        final River r = RiverUtils.getRiver(this);
         if (r == null) {
             return error(new WW[0], "no.river.found");
         }
 
-        WstValueTable wst = WstValueTableFactory.getTable(r);
+        final WstValueTable wst = WstValueTableFactory.getTable(r);
         if (wst == null) {
             return error(new WW[0], "no.wst.for.river");
         }
 
-        Map<Double, Double> kms2gaugeDatums = r.queryGaugeDatumsKMs();
+        final Map<Double, Double> kms2gaugeDatums = r.queryGaugeDatumsKMs();
 
         return calc5.calculate(wst, kms2gaugeDatums, context);
     }
 
-
     /** Get reference (start) km. */
     public Double getReferenceStartKm() {
-        StateData sd = getData("reference_startpoint");
+        final StateData sd = getData("reference_startpoint");
 
         if (sd == null) {
             log.warn("no reference start given.");
@@ -499,25 +439,23 @@
         try {
             return Double.valueOf(input);
         }
-        catch (NumberFormatException nfe) {
+        catch (final NumberFormatException nfe) {
             log.warn("reference start string is not numeric.");
         }
 
         return null;
     }
 
-
     /**
      * Get end kms for reference curve (null if none).
      */
-    public double [] getReferenceEndKms() {
-        StateData sd = getData("reference_endpoint");
+    public double[] getReferenceEndKms() {
+        final StateData sd = getData("reference_endpoint");
 
         if (sd == null) {
             log.warn("no reference end given.");
             return null;
-        }
-        else {
+        } else {
             log.debug("Reference end km : " + sd.getValue());
         }
 
@@ -528,16 +466,16 @@
             return null;
         }
 
-        TDoubleArrayList endKms = new TDoubleArrayList();
+        final TDoubleArrayList endKms = new TDoubleArrayList();
 
-        for (String part: input.split("\\s+")) {
+        for (final String part : input.split("\\s+")) {
             try {
-                double km = Double.parseDouble(part);
+                final double km = Double.parseDouble(part);
                 if (!endKms.contains(km)) {
                     endKms.add(km);
                 }
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 log.warn("reference end string is not numeric.");
             }
         }
@@ -545,25 +483,22 @@
         return endKms.toNativeArray();
     }
 
-
     /**
      * Get corrected waterline against surface/profile.
      */
-    private Lines.LineData waterLineC(int idx, FastCrossSectionLine csl) {
-        List<Point2D> points = csl.getPoints();
+    private double waterLineC(final int idx, final double currentKm) {
 
-        WQKms[] wqckms = (WQKms[])
-            getDischargeLongitudinalSectionData().getData();
+        final WQKms[] wqckms = (WQKms[]) getDischargeLongitudinalSectionData().getData();
 
         // Find index of km.
-        double wishKM = csl.getKm();
+        final double wishKM = currentKm;
 
         // Find W/C at km, linear naive approach.
-        WQCKms triple = (WQCKms) wqckms[idx-1];
+        final WQCKms triple = (WQCKms) wqckms[idx - 1];
 
         if (triple.size() == 0) {
             log.warn("Calculation of c/waterline is empty.");
-            return Lines.createWaterLines(points, 0.0f);
+            return Double.NaN;
         }
 
         // Linear seach in WQKms for closest km.
@@ -571,7 +506,7 @@
         double last_c = triple.getC(0);
 
         for (int i = 0, T = triple.size(); i < T; i++) {
-            double diff = Math.abs(wishKM - triple.getKm(i));
+            final double diff = Math.abs(wishKM - triple.getKm(i));
             if (diff > old_dist_wish) {
                 break;
             }
@@ -579,79 +514,77 @@
             old_dist_wish = diff;
         }
 
-        return Lines.createWaterLines(points, last_c);
+        return last_c;
     }
 
-
     /**
      * Get points of line describing the surface of water at cross section.
      *
-     * @param idx Index for getWaterlevelData.
-     * @param csl The profile/surface to fill with water.
-     * @param nextIgnored Ignored in this implementation of WaterLineArtifact.
-     * @param prevIgnored Ignored in this implementation of WaterLineArtifact.
+     * @param idx
+     *            Index for getWaterlevelData.
+     * @param csl
+     *            The profile/surface to fill with water.
+     * @param nextIgnored
+     *            Ignored in this implementation of WaterLineArtifact.
+     * @param prevIgnored
+     *            Ignored in this implementation of WaterLineArtifact.
      *
      * @return an array holding coordinates of points of surface of water (
      *         in the form {{x1, x2} {y1, y2}} ).
      */
     @Override
-    public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl,
-        double nextIgnored, double prevIgnored, CallContext context) {
-        log.debug("getWaterLines(" + idx + ")");
+    public double getWaterLevel(final ComputeType type, final String hash, final String stateId, final double currentKm, final Serializable waterLineIndex,
+            final double nextKm, final double prevKm, final CallContext context) {
 
-        List<Point2D> points = csl.getPoints();
+        final int idx = (int) waterLineIndex;
 
         // Need W at km
-        Object waterlevelResult = getWaterlevelData(context).getData();
-        WQKms [] wqkms;
+        final Object waterlevelResult = getWaterlevelData(context).getData();
+        WQKms[] wqkms;
 
         if (waterlevelResult instanceof ExtremeResult) {
             wqkms = ((ExtremeResult) waterlevelResult).getWQKms();
-        }
-        else {
+        } else {
             wqkms = (WQKms[]) waterlevelResult;
         }
 
         if (wqkms.length == 0) {
             log.error("No WQKms found.");
-            return Lines.createWaterLines(points, 0.0f);
+            return Double.NaN;
         }
 
         if (wqkms.length <= idx) {
-            log.error("getWaterLines() requested index ("
-                         + idx + " not found.");
-            return waterLineC(idx, csl);
+            log.error("getWaterLines() requested index (" + idx + " not found.");
+            return waterLineC(idx, currentKm);
         }
 
         // Find W at km, linear naive approach.
-        WQKms triple = wqkms[idx];
+        final WQKms triple = wqkms[idx];
 
         // Find index of km.
-        double wishKM = csl.getKm();
+        final double wishKM = currentKm;
 
         if (triple.size() == 0) {
             log.warn("Calculation of waterline is empty.");
-            return Lines.createWaterLines(points, 0.0f);
+            return Double.NaN;
         }
 
         // Early abort if we would need to extrapolate.
-        int T = triple.size();
-        double max_km = triple.getKm(T-1), min_km = triple.getKm(0);
+        final int T = triple.size();
+        final double max_km = triple.getKm(T - 1), min_km = triple.getKm(0);
         if (wishKM < min_km || wishKM > max_km) {
             // TODO Does this have to be done in the other WaterlineArtifact
-            //      implementations, too?
+            // implementations, too?
             log.warn("Will not extrapolate waterlevels.");
-            return Lines.createWaterLines(points, 0.0f);
+            return Double.NaN;
         }
 
-        int old_idx = 0;
-
         // Linear seach in WQKms for closest km.
         double old_dist_wish = Math.abs(wishKM - triple.getKm(0));
         double last_w = triple.getW(0);
 
         for (int i = 0; i < T; i++) {
-            double diff = Math.abs(wishKM - triple.getKm(i));
+            final double diff = Math.abs(wishKM - triple.getKm(i));
             if (diff > old_dist_wish) {
                 break;
             }
@@ -659,38 +592,38 @@
             old_dist_wish = diff;
         }
 
-        return Lines.createWaterLines(points, last_w);
+        return last_w;
     }
 
-
     /**
      * Returns the Qs for a number of Ws.
      *
-     * @param ws An array of W values.
+     * @param ws
+     *            An array of W values.
      *
      * @return an array of Q values.
      */
-    private double [][] getQsForWs(double[] ws, Calculation report) {
+    private double[][] getQsForWs(final double[] ws, final Calculation report) {
 
         if (ws == null) {
             log.error("getQsForWs: ws == null");
             return null;
         }
 
-        boolean debug = log.isDebugEnabled();
+        final boolean debug = log.isDebugEnabled();
 
         if (debug) {
             log.debug("D4EArtifact.getQsForWs");
         }
 
-        River r = RiverUtils.getRiver(this);
+        final River r = RiverUtils.getRiver(this);
         if (r == null) {
             log.warn("no river found");
             return null;
         }
 
-        RangeAccess rangeAccess = new RangeAccess(this);
-        double [] range = rangeAccess.getKmRange();
+        final RangeAccess rangeAccess = new RangeAccess(this);
+        final double[] range = rangeAccess.getKmRange();
         if (range == null) {
             log.warn("no ranges found");
             return null;
@@ -700,25 +633,25 @@
             log.debug("Bezugslinienverfahren I: W auf freier Strecke");
             // The simple case of the "Bezugslinienverfahren"
             // "W auf freier Strecke".
-            WstValueTable wst = WstValueTableFactory.getTable(r);
+            final WstValueTable wst = WstValueTableFactory.getTable(r);
             if (wst == null) {
                 log.warn("no wst value table found");
                 return null;
             }
-            double km = range[0];
+            final double km = range[0];
 
-            TDoubleArrayList outQs = new TDoubleArrayList(ws.length);
-            TDoubleArrayList outWs = new TDoubleArrayList(ws.length);
+            final TDoubleArrayList outQs = new TDoubleArrayList(ws.length);
+            final TDoubleArrayList outWs = new TDoubleArrayList(ws.length);
 
             boolean generatedWs = false;
 
             for (int i = 0; i < ws.length; ++i) {
-                double w = ws[i];
+                final double w = ws[i];
                 if (debug) {
                     log.debug("getQsForWs: lookup Q for W: " + w);
                 }
                 // There could be more than one Q per W.
-                double [] qs = wst.findQsForW(km, w, report);
+                final double[] qs = wst.findQsForW(km, w, report);
                 for (int j = 0; j < qs.length; ++j) {
                     outWs.add(ws[i]);
                     outQs.add(qs[j]);
@@ -730,17 +663,14 @@
                 log.debug("getQsForWs: number of Qs: " + outQs.size());
             }
 
-            return new double [][] {
-                outQs.toNativeArray(),
-                generatedWs ? outWs.toNativeArray() : null };
+            return new double[][] { outQs.toNativeArray(), generatedWs ? outWs.toNativeArray() : null };
         }
 
         if (debug) {
             log.debug("range: " + Arrays.toString(range));
         }
 
-        Gauge g = rangeAccess.getRiver().determineRefGauge(
-            range, rangeAccess.isRange());
+        final Gauge g = rangeAccess.getRiver().determineRefGauge(range, rangeAccess.isRange());
         if (g == null) {
             log.warn("no gauge found for km: " + range[0]);
             return null;
@@ -750,18 +680,17 @@
             log.debug("convert w->q with gauge '" + g.getName() + "'");
         }
 
-        DischargeTable dt = g.fetchMasterDischargeTable();
+        final DischargeTable dt = g.fetchMasterDischargeTable();
 
         if (dt == null) {
-            log.warn("No master discharge table found for gauge '"
-                + g.getName() + "'");
+            log.warn("No master discharge table found for gauge '" + g.getName() + "'");
             return null;
         }
 
-        double [][] values = DischargeTables.loadDischargeTableValues(dt);
+        final double[][] values = DischargeTables.loadDischargeTableValues(dt);
 
-        TDoubleArrayList wsOut = new TDoubleArrayList(ws.length);
-        TDoubleArrayList qsOut = new TDoubleArrayList(ws.length);
+        final TDoubleArrayList wsOut = new TDoubleArrayList(ws.length);
+        final TDoubleArrayList qsOut = new TDoubleArrayList(ws.length);
 
         boolean generatedWs = false;
 
@@ -770,13 +699,12 @@
                 log.warn("W is NaN: ignored");
                 continue;
             }
-            double [] qs = DischargeTables.getQsForW(values, ws[i]);
+            final double[] qs = DischargeTables.getQsForW(values, ws[i]);
 
             if (qs.length == 0) {
                 log.warn("No Qs found for W = " + ws[i]);
-            }
-            else {
-                for (double q: qs) {
+            } else {
+                for (final double q : qs) {
                     wsOut.add(ws[i]);
                     qsOut.add(q);
                 }
@@ -784,110 +712,101 @@
             generatedWs |= qs.length != 1;
         }
 
-        return new double [][] {
-            qsOut.toNativeArray(),
-            generatedWs ? wsOut.toNativeArray() : null
-        };
+        return new double[][] { qsOut.toNativeArray(), generatedWs ? wsOut.toNativeArray() : null };
     }
 
-
     /**
      * Returns the selected distance based on a given range (from, to).
      *
-     * @param dFrom The StateData that contains the lower value.
-     * @param dTo The StateData that contains the upper value.
+     * @param dFrom
+     *            The StateData that contains the lower value.
+     * @param dTo
+     *            The StateData that contains the upper value.
      *
      * @return the selected distance.
      */
-    protected double[] getDistanceByRange(StateData dFrom, StateData dTo) {
-        double from = Double.parseDouble((String) dFrom.getValue());
-        double to   = Double.parseDouble((String) dTo.getValue());
+    protected double[] getDistanceByRange(final StateData dFrom, final StateData dTo) {
+        final double from = Double.parseDouble((String) dFrom.getValue());
+        final double to = Double.parseDouble((String) dTo.getValue());
 
         return new double[] { from, to };
     }
 
-
     /**
      * This method returns the Q values.
      *
      * @return the selected Q values or null, if no Q values are selected.
      */
     public double[] getQs() {
-        StateData dMode      = getData("wq_isq");
-        StateData dSelection = getData("wq_isrange");
+        final StateData dMode = getData("wq_isq");
+        final StateData dSelection = getData("wq_isrange");
 
-        boolean isRange = dSelection != null
-            ? Boolean.valueOf((String)dSelection.getValue())
-            : false;
+        final boolean isRange = dSelection != null ? Boolean.valueOf((String) dSelection.getValue()) : false;
 
         if (isQ()) {
             if (!isRange) {
                 return getSingleWQValues();
-            }
-            else {
+            } else {
                 return getWQTriple();
             }
-        }
-        else {
+        } else {
             log.warn("You try to get Qs, but W has been inserted.");
             return null;
         }
     }
 
-
     public boolean isQ() {
-        StateData mode = getData("wq_isq");
-        String value = (mode != null) ? (String) mode.getValue() : null;
+        final StateData mode = getData("wq_isq");
+        final String value = (mode != null) ? (String) mode.getValue() : null;
         return value != null ? Boolean.valueOf(value) : false;
     }
 
     public boolean isW() {
-        StateData mode = getData("wq_isq");
-        String value = (mode != null) ? (String) mode.getValue() : null;
+        final StateData mode = getData("wq_isq");
+        final String value = (mode != null) ? (String) mode.getValue() : null;
         return value != null ? !Boolean.valueOf(value) : false;
     }
 
     public boolean isFreeW() {
-        if(!isW()) {
+        if (!isW()) {
             return false;
         }
-        StateData mode = getData("wq_isfree");
-        String value =  (mode != null) ? (String) mode.getValue() : null;
+        final StateData mode = getData("wq_isfree");
+        final String value = (mode != null) ? (String) mode.getValue() : null;
 
         return value != null ? Boolean.valueOf(value) : false;
     }
 
-
     /**
      * Returns true, if the parameter is set to compute data on a free range.
      * Otherwise it returns false, which tells the calculation that it is bound
      * to a gauge.
      *
      * @return true, if the calculation should compute on a free range otherwise
-     * false and the calculation is bound to a gauge.
+     *         false and the calculation is bound to a gauge.
      */
     public boolean isFreeQ() {
-        if(!isQ()) {
+        if (!isQ()) {
             return false;
         }
-        StateData mode  = getData("wq_isfree");
-        String    value = (mode != null) ? (String) mode.getValue() : null;
+        final StateData mode = getData("wq_isfree");
+        final String value = (mode != null) ? (String) mode.getValue() : null;
 
         log.debug("isFreeQ: " + value);
 
         return value != null && Boolean.valueOf(value);
     }
 
-
     /**
      * Returns the Q values based on a specified kilometer range.
      *
-     * @param range A 2dim array with lower and upper kilometer range.
+     * @param range
+     *            A 2dim array with lower and upper kilometer range.
      *
      * @return an array of Q values.
      */
-    public double[] getQs(double[] range) {
-        StateData dMode   = getData("wq_isq");
+    public double[] getQs(final double[] range) {
+        final StateData dMode = getData("wq_isq");
 
         if (isQ()) {
             return getWQForDist(range);
@@ -897,15 +816,15 @@
         return null;
     }
 
-
     /**
      * Returns the W values based on a specified kilometer range.
      *
-     * @param range A 2dim array with lower and upper kilometer range.
+     * @param range
+     *            A 2dim array with lower and upper kilometer range.
      *
      * @return an array of W values.
      */
-    public double[] getWs(double[] range) {
+    public double[] getWs(final double[] range) {
         if (isW()) {
             return getWQForDist(range);
         }
@@ -914,7 +833,6 @@
         return null;
     }
 
-
     /**
      * This method returns the W values.
      *
@@ -922,15 +840,13 @@
      */
     public double[] getWs() {
         if (isW()) {
-            StateData dSingle = getData("wq_single");
+            final StateData dSingle = getData("wq_single");
             if (dSingle != null) {
                 return getSingleWQValues();
-            }
-            else {
+            } else {
                 return getWQTriple();
             }
-        }
-        else {
+        } else {
             log.warn("You try to get Ws, but Q has been inserted.");
             return null;
         }
@@ -940,39 +856,40 @@
      * This method returns the given W or Q values for a specific range
      * (inserted in the WQ input panel for discharge longitudinal sections).
      *
-     * @param dist A 2dim array with lower und upper kilometer values.
+     * @param dist
+     *            A 2dim array with lower und upper kilometer values.
      *
      * @return an array of W or Q values.
      */
-    protected double[] getWQForDist(double[] dist) {
+    protected double[] getWQForDist(final double[] dist) {
         log.debug("Search wq values for range: " + dist[0] + " - " + dist[1]);
-        StateData data = getData("wq_values");
+        final StateData data = getData("wq_values");
 
         if (data == null) {
             log.warn("Missing wq values!");
             return null;
         }
 
-        String dataString = (String) data.getValue();
-        String[]   ranges = dataString.split(":");
+        final String dataString = (String) data.getValue();
+        final String[] ranges = dataString.split(":");
 
-        for (String range: ranges) {
-            String[] parts = range.split(";");
+        for (final String range : ranges) {
+            final String[] parts = range.split(";");
 
-            double lower = Double.parseDouble(parts[0]);
-            double upper = Double.parseDouble(parts[1]);
+            final double lower = Double.parseDouble(parts[0]);
+            final double upper = Double.parseDouble(parts[1]);
 
             if (lower <= dist[0] && upper >= dist[1]) {
-                String[] values = parts[2].split(",");
+                final String[] values = parts[2].split(",");
 
-                int      num = values.length;
-                double[] res = new double[num];
+                final int num = values.length;
+                final double[] res = new double[num];
 
                 for (int i = 0; i < num; i++) {
                     try {
                         res[i] = Double.parseDouble(values[i]);
                     }
-                    catch (NumberFormatException nfe) {
+                    catch (final NumberFormatException nfe) {
                         log.warn(nfe, nfe);
                     }
                 }
@@ -986,7 +903,6 @@
         return null;
     }
 
-
     /**
      * This method returns an array of inserted WQ triples that consist of from,
      * to and the step width.
@@ -994,37 +910,36 @@
      * @return an array of from, to and step width.
      */
     protected double[] getWQTriple() {
-        StateData dFrom = getData("wq_from");
-        StateData dTo   = getData("wq_to");
+        final StateData dFrom = getData("wq_from");
+        final StateData dTo = getData("wq_to");
 
         if (dFrom == null || dTo == null) {
             log.warn("Missing start or end value for range.");
             return null;
         }
 
-        double from = Double.parseDouble((String) dFrom.getValue());
-        double to   = Double.parseDouble((String) dTo.getValue());
+        final double from = Double.parseDouble((String) dFrom.getValue());
+        final double to = Double.parseDouble((String) dTo.getValue());
 
-        StateData dStep = getData("wq_step");
+        final StateData dStep = getData("wq_step");
 
         if (dStep == null) {
             log.warn("No step width given. Cannot compute Qs.");
             return null;
         }
 
-        double step  = Double.parseDouble((String) dStep.getValue());
+        double step = Double.parseDouble((String) dStep.getValue());
 
         // if no width is given, the DEFAULT_Q_STEPS is used to compute the step
         // width. Maybe, we should round the value to a number of digits.
         if (step == 0d) {
-            double diff = to - from;
+            final double diff = to - from;
             step = diff / DEFAULT_Q_STEPS;
         }
 
         return DoubleUtil.explode(from, to, step);
     }
 
-
     /**
      * Returns an array of inserted WQ double values stored as whitespace
      * separated list.
@@ -1032,23 +947,23 @@
      * @return an array of W or Q values.
      */
     protected double[] getSingleWQValues() {
-        StateData dSingle = getData("wq_single");
+        final StateData dSingle = getData("wq_single");
 
         if (dSingle == null) {
             log.warn("Cannot determine single WQ values. No data given.");
             return null;
         }
 
-        String   tmp       = (String) dSingle.getValue();
-        String[] strValues = tmp.split(" ");
+        final String tmp = (String) dSingle.getValue();
+        final String[] strValues = tmp.split(" ");
 
-        TDoubleArrayList values = new TDoubleArrayList();
+        final TDoubleArrayList values = new TDoubleArrayList();
 
-        for (String strValue: strValues) {
+        for (final String strValue : strValues) {
             try {
                 values.add(Double.parseDouble(strValue));
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 log.warn(nfe, nfe);
             }
         }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/WaterLineArtifact.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/WaterLineArtifact.java	Fri Aug 17 15:31:02 2018 +0200
@@ -8,24 +8,33 @@
 
 package org.dive4elements.river.artifacts;
 
-import org.dive4elements.artifacts.CallContext;
+import java.io.Serializable;
 
-import org.dive4elements.river.artifacts.geom.Lines;
-import org.dive4elements.river.model.FastCrossSectionLine;
-
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
 
 /**
  * Interface, Artifact can create WaterLines (Water against Cross-Profile).
  */
 public interface WaterLineArtifact {
 
-    /** Get points that define a line of a (water)facet against a cross-
-     * section. */
-    public Lines.LineData getWaterLines(
-        int                  facetIdx,
-        FastCrossSectionLine      csl,
-        double                      d,
-        double                      w,
-        CallContext           context);
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+    /**
+     * Get points that define a line of a (water)facet against a cross-
+     * section.
+     *
+     * @param stateId
+     * @param hash
+     *
+     * @param waterLineIndex
+     *            The object whith wich this artifact determines which of the waterlevels to return. Given to the facet when
+     *            constructed. Can be an integer in the simple case, or a more complex description.
+     */
+    // REMARK: we are giving type, hash and stateId so individual artifacts may call back on their compute method, which
+    // needs
+    // those to hash the result data.
+    // Currently, the old implementations don't do that but simply execute the whole computation each time they are
+    // called...
+    // TODO: instead we should compute outside and provide the computed data to this method.
+    double getWaterLevel(ComputeType type, String hash, String stateId, double currentKm, Serializable waterLineIndex, double nextKm, double prevKm,
+            CallContext context);
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractCalculationResult.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractCalculationResult.java	Fri Aug 17 15:31:02 2018 +0200
@@ -52,6 +52,21 @@
         return getPoints(GeneralResultType.station, yType, TruePredicate.INSTANCE);
     }
 
+    /**
+     * Return the row with the given station (within the given tolerance) by linear search.
+     * Returns <code>null</code>, if no such station was found.
+     */
+    protected final ResultRow getRowForStation(final double searchStation, final double stationTolerance) {
+
+        for (final ResultRow row : this.rows) {
+            final double station = row.getDoubleValue(GeneralResultType.station);
+            if (Math.abs(station - searchStation) < stationTolerance)
+                return row;
+        }
+
+        return null;
+    }
+
     public final double[][] getPoints(final IResultType typeX, final IResultType typeY, final Predicate rowFilter) {
 
         final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionWaterLineFacet.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionWaterLineFacet.java	Fri Aug 17 15:31:02 2018 +0200
@@ -8,76 +8,85 @@
 
 package org.dive4elements.river.artifacts.model;
 
-import org.apache.log4j.Logger;
-
+import java.io.Serializable;
 import java.util.List;
 
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.DataProvider;
-
-import org.dive4elements.artifactdatabase.state.Facet;
-
 import org.dive4elements.river.artifacts.WaterLineArtifact;
-
+import org.dive4elements.river.artifacts.geom.Lines;
+import org.dive4elements.river.artifacts.geom.Lines.LineData;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
 import org.dive4elements.river.model.FastCrossSectionLine;
 
-import org.dive4elements.river.artifacts.geom.Lines;
-
-
 /**
  * Facet for Waterlines in Cross Sections.
  */
-public class CrossSectionWaterLineFacet
-extends      BlackboardDataFacet
-implements   FacetTypes {
+public class CrossSectionWaterLineFacet extends DataFacet implements FacetTypes {
+
+    private static final LineData NO_LINE_DATA = new Lines.LineData(new double[][] {}, 0d, 0d);
+
+    private static final long serialVersionUID = 1L;
 
     /** Private log to use. */
-    private static Logger log =
-        Logger.getLogger(CrossSectionWaterLineFacet.class);
+    private static Logger log = Logger.getLogger(CrossSectionWaterLineFacet.class);
 
+    private final Serializable waterLineIndex;
 
     /** Trivial constructor, set (maybe localized) description. */
-    public CrossSectionWaterLineFacet(int idx, String description) {
-        super(idx, CROSS_SECTION_WATER_LINE, description);
+    public CrossSectionWaterLineFacet(final int idx, final String description, final ComputeType type, final String hash, final String stateId,
+            final Serializable waterLineIndex) {
+        this(idx, CROSS_SECTION_WATER_LINE, description, type, hash, stateId, waterLineIndex);
     }
 
-
     /**
      * Trivial constructor, set (maybe localized) description.
-     * @param idx Index of this facet.
-     * @param name 'type' of this facet.
-     * @param description (maybe) localized user-visible description.
+     *
+     * @param facetIndex
+     *            Index of this facet.
+     * @param waterLineIndex
+     *            Determines which water-line the artifact will return. Depends on the implementation of the artifact.
+     *            Is serializable because this class is, must be immutable because only the reference is copied in
+     *            'deepCopy'
+     * @param name
+     *            'type' of this facet.
+     * @param description
+     *            (maybe) localized user-visible description.
      */
-    public CrossSectionWaterLineFacet(
-        int idx,
-        String name,
-        String description
-    ) {
-        super(idx, name, description);
+    public CrossSectionWaterLineFacet(final int facetIndex, final String name, final String description, final ComputeType type, final String hash,
+            final String stateId, final Serializable waterLineIndex) {
+        super(facetIndex, name, description, type, hash, stateId);
+
+        this.waterLineIndex = waterLineIndex;
     }
 
-
     /**
      * Gets waterline (crossed with cross section) of waterlevel.
+     * FIXME: the cross section facets delgate fetching the data to the artifact, which in turn (in most cases) re-calculate
+     * the artifact on every call....
+     * Instead this should work like other facets that rely on the hashed computation.
      */
-    public Object getData(Artifact artifact, CallContext context) {
+    @Override
+    public Object getData(final Artifact artifact, final CallContext context) {
         log.debug("Get data for cross section water line");
 
-        List<DataProvider> providers = context.
-            getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA);
+        final List<DataProvider> providers = context.getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA);
         if (providers.size() < 1) {
             log.warn("Could not find Cross-Section data provider.");
-            return new Lines.LineData(new double[][] {}, 0d, 0d);
+            return NO_LINE_DATA;
         }
 
-        Object crossSection = providers.get(0)
-            .provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA,
-                null, context);
-        Object nextKm = providers.get(0).
-            provideData(CrossSectionFacet.BLACKBOARD_CS_NEXT_KM, null, context);
-        Object prevKm = providers.get(0).
-            provideData(CrossSectionFacet.BLACKBOARD_CS_PREV_KM, null, context);
+        final DataProvider dataProvider = providers.get(0);
+
+        final FastCrossSectionLine crossSection = (FastCrossSectionLine) dataProvider.provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, null, context);
+        if (crossSection == null)
+            return NO_LINE_DATA;
+
+        Object nextKm = dataProvider.provideData(CrossSectionFacet.BLACKBOARD_CS_NEXT_KM, null, context);
+        Object prevKm = dataProvider.provideData(CrossSectionFacet.BLACKBOARD_CS_PREV_KM, null, context);
         if (prevKm == null)
             prevKm = new Double(-1d);
         if (nextKm == null)
@@ -85,29 +94,28 @@
 
         if (!(artifact instanceof WaterLineArtifact)) {
             log.error("CrossSectionWaterLineFacet needs WaterLineArtifact");
-            return new Lines.LineData(new double[][] {}, 0d,0d);
+            return NO_LINE_DATA;
         }
-        WaterLineArtifact lineArtifact = (WaterLineArtifact) artifact;
 
-        if (crossSection != null) {
-            return lineArtifact.getWaterLines(this.getIndex(),
-                (FastCrossSectionLine) crossSection, (Double) nextKm,
-                (Double) prevKm, context);
-        }
-        else {
-            return new Lines.LineData(new double[][] {}, 0d,0d);
-        }
+        final WaterLineArtifact lineArtifact = (WaterLineArtifact) artifact;
+
+        final double currentKm = crossSection.getKm();
+
+        final double waterLevel = lineArtifact.getWaterLevel(this.type, this.hash, this.stateId, currentKm, this.waterLineIndex, (Double) nextKm,
+                (Double) prevKm,
+                context);
+        if (Double.isNaN(waterLevel))
+            return NO_LINE_DATA;
+
+        return Lines.createWaterLines(crossSection.getPoints(), waterLevel);
     }
 
-
     /** Do a deep copy. */
     @Override
     public Facet deepCopy() {
-        CrossSectionWaterLineFacet copy = new CrossSectionWaterLineFacet(
-            this.getIndex(),
-            this.description);
+        final CrossSectionWaterLineFacet copy = new CrossSectionWaterLineFacet(this.getIndex(), this.name, this.description, this.type, this.hash, this.stateId,
+                this.waterLineIndex);
         copy.set(this);
         return copy;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DataFacet.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/DataFacet.java	Fri Aug 17 15:31:02 2018 +0200
@@ -109,6 +109,7 @@
         // FIXME: usage of internal knowledge of parent class...
         // Either the set method should be correctly overwritten, or implement a correct copy-constructor!
         copy.set(this);
+        // FIXME: instead we need to overwrite set and call it here
         copy.type    = type;
         copy.hash    = hash;
         copy.stateId = stateId;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/RelativePointFacet.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/RelativePointFacet.java	Fri Aug 17 15:31:02 2018 +0200
@@ -163,7 +163,7 @@
     public Object getData(Artifact artifact, CallContext context) {
         WKms wKms = null;
         if (artifact instanceof StaticWKmsArtifact) {
-            wKms = ((StaticWKmsArtifact) artifact).getWKms(0);
+            wKms = ((StaticWKmsArtifact) artifact).getWKms();
         }
         else if (artifact instanceof StaticWQKmsArtifact) {
             wKms = ((StaticWQKmsArtifact) artifact).getWQKms();
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFacet.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WKmsFacet.java	Fri Aug 17 15:31:02 2018 +0200
@@ -44,7 +44,7 @@
     public Object getData(Artifact artifact, CallContext context) {
         StaticWKmsArtifact staticData =
             (StaticWKmsArtifact) artifact;
-        return staticData.getWKms(0);
+        return staticData.getWKms();
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/DischargeLongitudinalSection.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/DischargeLongitudinalSection.java	Fri Aug 17 15:31:02 2018 +0200
@@ -71,7 +71,6 @@
         Object       old
     ) {
         if (artifact instanceof ChartArtifact) {
-            ChartArtifact chart = (ChartArtifact)artifact;
             facets.add(new EmptyFacet());
             return null;
         }
@@ -108,7 +107,7 @@
                 Facet w = new WaterlevelFacet(
                     i, DISCHARGE_LONGITUDINAL_W, nameW);
 
-                Facet s = new CrossSectionWaterLineFacet(i, nameW);
+                Facet s = new CrossSectionWaterLineFacet(i, nameW, ComputeType.ADVANCE, hash, getID(), Integer.valueOf(i));
 
                 Facet q = new WaterlevelFacet(
                     i, DISCHARGE_LONGITUDINAL_Q, nameQ);
@@ -141,7 +140,7 @@
 
                 // Here, avoid index clash with Facet "s" above and
                 // signal the WINFO later that we want to access Cs.
-                Facet r = new CrossSectionWaterLineFacet(i + 1, nameC);
+                Facet r = new CrossSectionWaterLineFacet(i + 1, nameC, ComputeType.ADVANCE, hash, getID(), Integer.valueOf(i + 1));
 
                 facets.add(c);
                 facets.add(r);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java	Fri Aug 17 15:31:02 2018 +0200
@@ -1015,7 +1015,7 @@
         else if (computed == null && src instanceof StaticWKmsArtifact) {
             // Floodmarks and protection.
             WQKms wqkms = WQKms.fromWKms(
-                ((StaticWKmsArtifact)src).getWKms(0), 1d);
+                ((StaticWKmsArtifact)src).getWKms(), 1d);
             return wqkms;
         }
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/ManualPointsSingleState.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/ManualPointsSingleState.java	Fri Aug 17 15:31:02 2018 +0200
@@ -58,8 +58,9 @@
      *
      * @return null.
      */
-    public Object compute(
+    private Object compute(
         D4EArtifact artifact,
+        ComputeType type,
         String       hash,
         CallMeta     meta,
         List<Facet>  facets
@@ -101,17 +102,13 @@
                         String fName = ct + "." + MANUALLINE;
                         log.debug("have facet: " + y + " / "
                             + name + " -> " + fName);
-                        CrossSectionWaterLineFacet facet =
-                            new CrossSectionWaterLineFacet(
-                                i,
-                                fName,
-                                name);
 
+                        final CrossSectionWaterLineFacet facet = new CrossSectionWaterLineFacet( i, fName, name, type, hash, getID(), Integer.valueOf(i));
                         facets.add(facet);
                     }
                 }
                 catch(JSONException e){
-                    log.error("Could not decode json.");
+                    log.error("Could not decode json.", e);
                 }
 
             }
@@ -133,7 +130,7 @@
         CallMeta     meta,
         List<Facet>  facets
      ) {
-        return compute(artifact, hash, meta, facets);
+        return compute(artifact, ComputeType.INIT, hash, meta, facets);
     }
 
 
@@ -146,7 +143,7 @@
         List<Facet> facets,
         Object old
     ) {
-        return compute(artifact, hash, context.getMeta(), facets);
+        return compute(artifact, ComputeType.FEED, hash, context.getMeta(), facets);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticWQKmsState.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/StaticWQKmsState.java	Fri Aug 17 15:31:02 2018 +0200
@@ -52,14 +52,15 @@
     /**
      * Compute, create Facets, do the same stuff as all the other states do.
      */
-    protected Object compute(
+    private Object compute(
         StaticWQKmsArtifact artifact,
         CallMeta      metaLocale,
+        ComputeType type,
         String        hash,
         List<Facet>   facets,
         Object        old
     ) {
-        String id = getID();
+        String stateId = getID();
         String code = artifact.getDataAsString("ids");
         String [] parts = code.split("-");
 
@@ -125,8 +126,7 @@
         Facet rpFacet = new RelativePointFacet(wkmsName);
         facets.add(rpFacet);
 
-        Facet csFacet = new CrossSectionWaterLineFacet(0,
-             wkmsName);
+        Facet csFacet = new CrossSectionWaterLineFacet(0,wkmsName, type, hash, stateId, null);
         facets.add(csFacet);
 
         if (!qEmpty) {
@@ -147,7 +147,7 @@
         Facet wstfacet = new DataFacet(
             WST,
             wkmsName,
-            ComputeType.ADVANCE, hash, id);
+            ComputeType.ADVANCE, hash, stateId);
         facets.add(wstfacet);
 
         return res;
@@ -161,8 +161,7 @@
         List<Facet>  facets,
         Object       old
     ) {
-        return compute((StaticWQKmsArtifact) artifact, context.getMeta(),
-            hash, facets, old);
+        return compute((StaticWQKmsArtifact) artifact, context.getMeta(), ComputeType.ADVANCE, hash, facets, old);
     }
 
     /**
@@ -178,8 +177,7 @@
         List<Facet>  facets,
         Object       old
     ) {
-        return compute((StaticWQKmsArtifact) artifact, context.getMeta(),
-            hash, facets, old);
+        return compute((StaticWQKmsArtifact) artifact, context.getMeta(), ComputeType.FEED, hash, facets, old);
     }
 
 
@@ -195,8 +193,7 @@
         CallMeta     meta,
         List<Facet>  facets
     ) {
-        return compute((StaticWQKmsArtifact) artifact, meta,
-            hash, facets, null);
+        return compute((StaticWQKmsArtifact) artifact, meta, ComputeType.INIT, hash, facets, null);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Fri Aug 17 15:31:02 2018 +0200
@@ -137,7 +137,7 @@
         if (d4eArtifact instanceof StaticWKmsArtifact) {
             StaticWKmsArtifact staticWKms = (StaticWKmsArtifact) d4eArtifact;
             log.debug("WDifferencesState obtain data from StaticWKms");
-            WKms wkms = staticWKms.getWKms(idx, from, to);
+            WKms wkms = staticWKms.getWKms(from, to);
             if (wkms == null) {
                 log.error("No WKms from Static artifact for this range.");
                 // FIXME: why does in error case we return Q's?
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java	Fri Aug 17 15:31:02 2018 +0200
@@ -79,7 +79,7 @@
             final double to) {
 
         if (d4eArtifact instanceof StaticWKmsArtifact)
-            return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, idx, from, to);
+            return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, from, to);
 
         if (d4eArtifact instanceof StaticWQKmsArtifact)
             return fetchStaticWQKmsArtifactWaterlevel((StaticWQKmsArtifact) d4eArtifact, from, to);
@@ -98,11 +98,11 @@
     // this logic back to the corresponding artifacts. However this will most certainly break existing
     // artifact-serialization
 
-    private WaterlevelData fetchStaticWKmsArtifactWaterlevel(final StaticWKmsArtifact staticWKms, final int idx, final double from, final double to) {
+    private WaterlevelData fetchStaticWKmsArtifactWaterlevel(final StaticWKmsArtifact staticWKms, final double from, final double to) {
 
         log.debug("WDifferencesState obtain data from StaticWKms");
 
-        final WKms wkms = staticWKms.getWKms(idx, from, to);
+        final WKms wkms = staticWKms.getWKms(from, to);
 
         if (wkms != null) {
             final int year = fetchStaticWKmsYear(staticWKms);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelInfoState.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelInfoState.java	Fri Aug 17 15:31:02 2018 +0200
@@ -51,18 +51,19 @@
         CallMeta     meta,
         List<Facet>  facets
     ) {
-        return compute((WINFOArtifact) artifact, hash, facets, null);
+        return compute((WINFOArtifact) artifact, ComputeType.INIT, hash, facets, null);
     }
 
 
-    protected Object compute(
+    private Object compute(
         WINFOArtifact winfo,
+        ComputeType type,
         String        hash,
         List<Facet>   facets,
         Object        old
     ) {
         log.debug("WaterlevelInfoState.compute");
-        String id = getID();
+        String stateId = getID();
 
         CalculationResult res = old instanceof CalculationResult
             ? (CalculationResult)old
@@ -91,9 +92,9 @@
             log.debug("WaterlevelInfoState Create facet: " + nameQ);
 
             Facet w = new WaterlevelFacet(
-                i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, id, hash);
+                i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, stateId, hash);
             Facet q = new WaterlevelFacet(
-                i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, id, hash);
+                i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, stateId, hash);
 
             facets.add(w);
             facets.add(q);
@@ -101,21 +102,20 @@
 
         if (wqkms.length > 0) {
             Facet wst = new DataFacet(
-                WST, "WST data", ComputeType.ADVANCE, hash, id);
+                WST, "WST data", ComputeType.ADVANCE, hash, stateId);
             Facet csv = new DataFacet(
-                CSV, "CSV data", ComputeType.ADVANCE, hash, id);
+                CSV, "CSV data", ComputeType.ADVANCE, hash, stateId);
 
             facets.add(wst);
             facets.add(csv);
         }
 
         if (res.getReport().hasProblems()) {
-            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, id));
+            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, stateId));
         }
 
         // TODO Adjust to WaterlevelState - implementation.
-        facets.add(new CrossSectionWaterLineFacet(0,
-                "Q=" + winfo.getDataAsString("wq_single")));
+        facets.add(new CrossSectionWaterLineFacet(0, "Q=" + winfo.getDataAsString("wq_single"), type, hash, stateId, null));
 
         // Assume to be in wq_single mode.
         return res;
@@ -133,7 +133,7 @@
         List<Facet>  facets,
         Object       old
     ) {
-        return compute((WINFOArtifact) artifact, hash, facets, old);
+        return compute((WINFOArtifact) artifact, ComputeType.FEED, hash, facets, old);
     }
 
 
@@ -148,7 +148,7 @@
         List<Facet>  facets,
         Object       old
     ) {
-        return compute((WINFOArtifact) artifact, hash, facets, old);
+        return compute((WINFOArtifact) artifact, ComputeType.ADVANCE, hash, facets, old);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelSelectState.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelSelectState.java	Fri Aug 17 15:31:02 2018 +0200
@@ -160,7 +160,7 @@
             wkms = (WKms[]) rawData;
         }
         else if (artifact instanceof StaticWKmsArtifact) {
-            wkms = new WKms[] {((StaticWKmsArtifact) artifact).getWKms(0)};
+            wkms = new WKms[] {((StaticWKmsArtifact) artifact).getWKms()};
         }
         else {
             if (rawData == null) {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java	Fri Aug 17 15:31:02 2018 +0200
@@ -51,11 +51,13 @@
 
     /**
      * Compute result or returned object from cache, create facets.
+     * @param feed 
      * @param old Object that was cached.
      */
-    protected Object compute(
+    private Object compute(
         WINFOArtifact winfo,
         CallContext   cc,
+        ComputeType type, 
         String        hash,
         List<Facet>   facets,
         Object        old
@@ -97,7 +99,7 @@
             Facet q = new WaterlevelFacet(
                 i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, id, hash);
 
-            facets.add(new CrossSectionWaterLineFacet(i, nameW));
+            facets.add(new CrossSectionWaterLineFacet(i, nameW, type, hash, getID(), Integer.valueOf(i)));
 
             facets.add(w);
             facets.add(q);
@@ -163,7 +165,7 @@
             facets.add(new EmptyFacet());
             return null;
         }
-        return compute((WINFOArtifact) artifact, context, hash, facets, old);
+        return compute((WINFOArtifact) artifact, context, ComputeType.FEED,  hash, facets, old);
     }
 
 
@@ -182,7 +184,7 @@
             facets.add(new EmptyFacet());
             return null;
         }
-        return compute((WINFOArtifact) artifact, context, hash, facets, old);
+        return compute((WINFOArtifact) artifact, context, ComputeType.ADVANCE, hash, facets, old);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/ExtremeCompute.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/extreme/ExtremeCompute.java	Fri Aug 17 15:31:02 2018 +0200
@@ -80,7 +80,7 @@
         }
 
         ExtremeResult eres = (ExtremeResult) res.getData();
-        WQKms [] wqkms = (WQKms []) eres.getWQKms();
+        WQKms [] wqkms = eres.getWQKms();
 
         if (wqkms == null) {
             log.error("No computation result!");
@@ -93,11 +93,9 @@
             String qname = name.replace("W(","Q=");
             qname = qname.substring(0,qname.length()-1);
 
-            Facet w = new WaterlevelFacet(
-                i, LONGITUDINAL_W, name, ComputeType.ADVANCE, id, hash);
-            Facet q = new WaterlevelFacet(
-                i, LONGITUDINAL_Q, qname, ComputeType.ADVANCE, id, hash);
-            Facet csFacet = new CrossSectionWaterLineFacet(i, name);
+            Facet w = new WaterlevelFacet( i, LONGITUDINAL_W, name, ComputeType.ADVANCE, id, hash );
+            Facet q = new WaterlevelFacet( i, LONGITUDINAL_Q, qname, ComputeType.ADVANCE, id, hash );
+            Facet csFacet = new CrossSectionWaterLineFacet( i, name, ComputeType.ADVANCE, hash, getID(), Integer.valueOf(i) );
 
             facets.add(w);
             facets.add(q);
@@ -105,18 +103,12 @@
         }
 
 
-        facets.add(
-            new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id));
-        facets.add(
-            new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id));
-        facets.add(
-            new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id));
+        facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id));
+        facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id));
+        facets.add(new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id));
 
-        facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(),
-                    "extreme_wq_curve", "extreme_wq_curve")));
-        facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(),
-                    "extreme_wq_base_curve", "extreme_wq_base_curve"),
-                true));
+        facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(), "extreme_wq_curve", "extreme_wq_curve")));
+        facets.add(new ExtremeCurveFacet(Resources.getMsg(context.getMeta(), "extreme_wq_base_curve", "extreme_wq_base_curve"), true));
 
         return res;
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixRealizingCompute.java	Fri Aug 17 14:29:05 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixRealizingCompute.java	Fri Aug 17 15:31:02 2018 +0200
@@ -80,7 +80,7 @@
             facets.add(new ReportFacet());
         }
 
-        final String id = getID();
+        final String stateId = getID();
         final CallMeta meta = context.getMeta();
 
         final FixRealizingResult fixRes = (FixRealizingResult) res.getData();
@@ -98,10 +98,10 @@
                 nameQ = "Q(" + nameW + ")";
             }
 
-            facets.add(new FixWaterlevelFacet(i, FIX_WQ_LS, nameW, ComputeType.ADVANCE, hash, id));
-            facets.add(new FixWaterlevelFacet(i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, hash, id));
-            facets.add(new FixWaterlevelFacet(i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, hash, id));
-            facets.add(new CrossSectionWaterLineFacet(i, nameW));
+            facets.add(new FixWaterlevelFacet(i, FIX_WQ_LS, nameW, ComputeType.ADVANCE, hash, stateId));
+            facets.add(new FixWaterlevelFacet(i, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, hash, stateId));
+            facets.add(new FixWaterlevelFacet(i, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, hash, stateId));
+            facets.add(new CrossSectionWaterLineFacet(i, nameW, ComputeType.ADVANCE, hash, stateId, Integer.valueOf(i)));
 
             // XXX: THIS CAN NOT HAPPEN! REMOVE IT!
             if (wqkms[i] instanceof WQCKms) {
@@ -127,12 +127,12 @@
                 facets.add(new FixReferenceEventsFacet(facetIndex++, event.getColumnId(), FIX_EVENTS, facetDescription, stationRange));
             }
 
-            facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id));
-            facets.add(new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, id));
-            facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, id));
+            facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, stateId));
+            facets.add(new DataFacet(WST, "WST data", ComputeType.ADVANCE, hash, stateId));
+            facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, stateId));
         }
 
-        facets.add(new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, id));
+        facets.add(new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, stateId));
 
         if (fixRes != null)
             facets.add(new FixWQCurveFacet(0, Resources.getMsg(meta, I18N_WQ_CURVE, I18N_WQ_CURVE) + " (" + access.getFunction() + ")"));

http://dive4elements.wald.intevation.org