diff artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java @ 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 f61bc0c63188
children 2b83d3a96703
line wrap: on
line diff
--- 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);
             }
         }

http://dive4elements.wald.intevation.org