# HG changeset patch # User gernotbelger # Date 1518189094 -3600 # Node ID 6b93a2498e06f598cf3fa52e1867a9744712fbd2 # Parent 64ca63f79f6fe5926f1fe7a5689a697c5c2531d5 Slightly better abstraction for extraction waterlevels via datacage diff -r 64ca63f79f6f -r 6b93a2498e06 artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java --- 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."); diff -r 64ca63f79f6f -r 6b93a2498e06 artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelData.java --- /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 true, 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 }; + } +} diff -r 64ca63f79f6f -r 6b93a2498e06 artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java --- /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 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); + } +}