Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java @ 8962:708f210ff242
Fetching year informations for waterlevels used in sinfo
author | gernotbelger |
---|---|
date | Wed, 28 Mar 2018 17:03:11 +0200 |
parents | 86650594f051 |
children | 45f1ad66560e |
line wrap: on
line source
/** 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.Calendar; import java.util.Date; 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.Calculation; 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.WstColumnFactory; import org.dive4elements.river.artifacts.model.fixings.FixRealizingCalculationExtended; import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult; import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; import org.dive4elements.river.model.TimeInterval; import org.dive4elements.river.model.WstColumn; 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 Calculation problems) { final String[] def = mingle.split(";"); final String uuid = def[0]; // final String factory = def[1]; final int idx = Integer.parseInt(def[2]); final String name = def[3]; final D4EArtifact d4eArtifact = RiverUtils.getArtifact(uuid, context); final WaterlevelData data = fetchWaterlevelFromArtifact(context, d4eArtifact, idx, from, to); if (data != null) return data.withName(name); problems.addProblem("waterlevelfetcher.missing'", mingle); return null; } 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: 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. However this will most certainly break existing // artifact-serialization 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) { final int year = fetchStaticWKmsYear(staticWKms); return new WaterlevelData(wkms, year); } 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) { final int year = fetchStaticWKmsYear(staticWKms); return new WaterlevelData(wkms, year); } 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; } // REAMRK: W_INFO results does not know any 'year' final int year = -1; return new WaterlevelData(wkms[idx], year).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()); /* ugly but necessary to keep this logic at least a bit inside the FixRealizing stuff */ final FixRealizingCalculationExtended calculation = new FixRealizingCalculationExtended(fixAccess); final int year = calculation.determineMeanYear(); // REMARK: same logic as in WaterlevelExporter final boolean showAllGauges = isFixRealize; return new WaterlevelData(frR.getWQKms()[idx], year, showAllGauges).filterByRange(from, to); } /** * Fetches the 'year' for a staticXXX-artifact. * REMARK: actually this should happen inside the staticWKms artifact and eventually in the WKmsFactory, but the code * there is already awful and it will also break the old artifact-serialization... */ private int fetchStaticWKmsYear(final D4EArtifact staticWKms) { final int colPos = Integer.parseInt(staticWKms.getDataAsString("col_pos")); final int wstId = Integer.parseInt(staticWKms.getDataAsString("wst_id")); final WstColumn wstColumn = WstColumnFactory.getWstColumn(wstId, colPos); final TimeInterval timeInterval = wstColumn.getTimeInterval(); if (timeInterval == null) return -1; final Date startTime = timeInterval.getStartTime(); if (startTime == null) return -1; // REMARK: the times are stored without timezone in the DB, so it is unclear what hibernate makes of it. // We simply use the default timezone here and hope we never get problems... // Actually we always have 12:00 as time in the db data, so a smal timeshift due to winter/sommertime or UTC/GMT+1 will // no change anything regarding the year. final Calendar cal = Calendar.getInstance(); cal.setTime(startTime); return cal.get(Calendar.YEAR); } }