changeset 8881:6b93a2498e06

Slightly better abstraction for extraction waterlevels via datacage
author gernotbelger
date Fri, 09 Feb 2018 16:11:34 +0100
parents 64ca63f79f6f
children f762fadc5313
files artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelData.java artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java
diffstat 3 files changed, 232 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Fri Feb 09 13:27:10 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java	Fri Feb 09 16:11:34 2018 +0100
@@ -111,6 +111,7 @@
      * Access the data (wkms) of an artifact, coded in mingle.
      */
     // FIXME: meanwhile used by several places outside this context; refactor into separate helper class to access waterlevels
+    // FIXME: use org.dive4elements.river.artifacts.states.WaterlevelFetcher instead
     public WKms getWKms(
         String mingle,
         CallContext context,
@@ -160,6 +161,7 @@
                                               getData();
             if (wkms == null || wkms.length == 0) {
                 log.warn("no waterlevels in artifact");
+                // FIXME: fall through will lead to exception...
             }
             else if (wkms.length < idx+1) {
                 log.warn("Not enough waterlevels in artifact.");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelData.java	Fri Feb 09 16:11:34 2018 +0100
@@ -0,0 +1,84 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.artifacts.states;
+
+import org.dive4elements.river.artifacts.model.WKms;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.River;
+
+/**
+ * Represents a waterlevel fetched with the {@link WaterlevelFetcher}.
+ *
+ * @author Gernot Belger
+ */
+public class WaterlevelData {
+    private final WKms wkms;
+
+    private final String name;
+
+    /** If <code>true</code>, tabular export will show gauges for every station, else only for the first gauge */
+    private final boolean showAllGauges;
+
+    public WaterlevelData(final WKms wkms) {
+        this(wkms, false);
+    }
+
+    public WaterlevelData(final WKms wkms, final boolean showAllGauges) {
+        this(null, wkms, showAllGauges);
+    }
+
+    public WaterlevelData(final String name, final WKms wkms, final boolean showAllGauges) {
+        this.name = name;
+        this.wkms = wkms;
+        this.showAllGauges = showAllGauges;
+    }
+
+    public WaterlevelData filterByRange(final double from, final double to) {
+        if (Double.isNaN(from) || Double.isNaN(to)) {
+            return this;
+        }
+
+        final WKms filteredWkms = this.wkms.filteredKms(from, to);
+        return new WaterlevelData(filteredWkms);
+    }
+
+    public WaterlevelData withName(final String nameToSet) {
+        return new WaterlevelData(nameToSet, this.wkms, this.showAllGauges);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public WKms getWkms() {
+        return this.wkms;
+    }
+
+    public boolean isShowAllGauges() {
+        return this.showAllGauges;
+    }
+
+    public Gauge findReferenceGauge(final River river) {
+        final double[] wstFromTo = findWstFromTo();
+        return river.determineRefGauge(wstFromTo, true);
+    }
+
+    private double[] findWstFromTo() {
+
+        final double from = this.wkms.getKm(0);
+        final double to = this.wkms.getKm(this.wkms.size() - 1);
+
+        final boolean waterIncreasing = this.wkms.guessWaterIncreasing();
+        if (waterIncreasing)
+            return new double[] { to, from };
+
+        return new double[] { from, to };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java	Fri Feb 09 16:11:34 2018 +0100
@@ -0,0 +1,146 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.artifacts.states;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.FixationArtifact;
+import org.dive4elements.river.artifacts.StaticWKmsArtifact;
+import org.dive4elements.river.artifacts.StaticWQKmsArtifact;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.access.FixRealizingAccess;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.Segment;
+import org.dive4elements.river.artifacts.model.WKms;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult;
+import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.utils.RiverUtils;
+
+/**
+ * Helper class that accesses existing waterlevels (in most cases) from the data-cage.
+ * This is mainly a refaktoring of org.dive4elements.river.artifacts.states.WDifferencesState.getWKms(String,
+ * CallContext, double, double), adding more infos to the fetched water levels.
+ *
+ * @author Gernot Belger
+ */
+public class WaterlevelFetcher {
+    private static Logger log = Logger.getLogger(WaterlevelFetcher.class);
+
+    public WaterlevelData findWaterlevel(final CallContext context, final String mingle, final double from,
+            final double to) {
+
+        final String[] def = mingle.split(";");
+        final String uuid = def[0];
+        final String name = def[1];
+        final int idx = Integer.parseInt(def[2]);
+        final D4EArtifact d4eArtifact = RiverUtils.getArtifact(uuid, context);
+
+        final WaterlevelData data = fetchWaterlevelFromArtifact(context, d4eArtifact, idx, from, to);
+        return data.withName(name);
+    }
+
+    private WaterlevelData fetchWaterlevelFromArtifact(final CallContext context, final D4EArtifact d4eArtifact,
+            final int idx, final double from, final double to) {
+        if (d4eArtifact == null) {
+            log.warn("One of the artifacts (1) for diff calculation " + "could not be loaded");
+            return null;
+        }
+
+        if (d4eArtifact instanceof StaticWKmsArtifact) {
+            return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, idx, from, to);
+        }
+
+        if (d4eArtifact instanceof StaticWQKmsArtifact) {
+            return fetchStaticWQKmsArtifactWaterlevel((StaticWQKmsArtifact) d4eArtifact, from, to);
+        }
+
+        if (d4eArtifact instanceof WINFOArtifact)
+            return fetchWINFOArtifactWaterlevel(context, (WINFOArtifact) d4eArtifact, idx, from, to);
+
+        if (d4eArtifact instanceof FixationArtifact)
+            return fetchFixationArtifactWaterlevel(context, (FixationArtifact) d4eArtifact, idx, from, to);
+
+        log.warn(String.format("Get Waterlevel from %s not implemented! )", d4eArtifact.getClass().getSimpleName()));
+        return null;
+    }
+
+    // REMARK/TODO: instead of several helper methods here this would be a good place for abstraction, in order to push
+    // this logic back to the corresponding artifacts
+
+    private WaterlevelData fetchStaticWKmsArtifactWaterlevel(final StaticWKmsArtifact staticWKms, final int idx,
+            final double from, final double to) {
+
+        log.debug("WDifferencesState obtain data from StaticWKms");
+
+        final WKms wkms = staticWKms.getWKms(idx, from, to);
+
+        if (wkms != null)
+            return new WaterlevelData(wkms);
+
+        log.error("No WKms from Static artifact for this range.");
+        return null;
+    }
+
+    private WaterlevelData fetchStaticWQKmsArtifactWaterlevel(final StaticWQKmsArtifact staticWKms, final double from,
+            final double to) {
+
+        log.debug("WDifferencesState obtain data from StaticWQKms");
+
+        final WQKms wkms = staticWKms.getWQKms(from, to);
+
+        if (wkms != null)
+            return new WaterlevelData(wkms);
+
+        log.error("No WKms from Static artifact for this range.");
+        return null;
+    }
+
+    private WaterlevelData fetchWINFOArtifactWaterlevel(final CallContext context, final WINFOArtifact flys,
+            final int idx, final double from, final double to) {
+        log.debug("Get WKms from WINFOArtifact");
+
+        final WKms[] wkms = (WKms[]) flys.getWaterlevelData(context).getData();
+
+        if (wkms == null || wkms.length == 0) {
+            log.warn("no waterlevels in artifact");
+            return null;
+        }
+
+        if (wkms.length < idx + 1) {
+            log.warn("Not enough waterlevels in artifact.");
+            return null;
+        }
+
+        return new WaterlevelData(wkms[idx]).filterByRange(from, to);
+    }
+
+    private WaterlevelData fetchFixationArtifactWaterlevel(final CallContext context,
+            final FixationArtifact fixation, final int idx, final double from, final double to) {
+
+        log.debug("Get WKms from FixationArtifact.");
+
+        final CalculationResult r = (CalculationResult) fixation.compute(context, ComputeType.ADVANCE, false);
+        final FixRealizingResult frR = (FixRealizingResult) r.getData();
+
+        // Get W/Q input per gauge for this case.
+        final FixRealizingAccess fixAccess = new FixRealizingAccess(fixation);
+        final List<Segment> segments = fixAccess.getSegments();
+        final boolean isFixRealize = (segments != null && !segments.isEmpty());
+
+        // REMARK: same logic as in WaterlevelExporter
+        final boolean showAllGauges = isFixRealize;
+
+        return new WaterlevelData(frR.getWQKms()[idx], showAllGauges).filterByRange(from, to);
+    }
+}

http://dive4elements.wald.intevation.org