Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java @ 9708:93389a05119e
zu Nachtrag - BezugsWST in intell. Datenkorb
author | dnt_bjoernsen <d.tironi@bjoernsen.de> |
---|---|
date | Fri, 22 Jan 2021 18:45:39 +0100 |
parents | 3f49835a00c3 |
children |
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.commons.lang.math.DoubleRange; import org.apache.log4j.Logger; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.AbstractFixBunduArtifact; import org.dive4elements.river.artifacts.D4EArtifact; 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.bundu.bezugswst.BezugswstCalculationResults; import org.dive4elements.river.artifacts.bundu.bezugswst.BezugswstMainCalculationResult; import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult; 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); /** * @param simulationRange * This range is used to check if the found waterlevel covers it. It * is NOT used to reduce the fetched data, because in case of * waterlevels we always need to full set in order to determine the * relevant gauge. */ public WaterlevelData findWaterlevel(final CallContext context, final String mingle, final DoubleRange simulationRange, 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); if (d4eArtifact == null) return null; final WaterlevelData data = fetchWaterlevelFromArtifact(context, d4eArtifact, idx, Double.NaN, Double.NaN); if (data == null) { problems.addProblem("waterlevelfetcher.missing", mingle); return null; } if (!data.covers(simulationRange)) { problems.addProblem("waterlevelfetcher.empty", data.getName()); return null; } return data.withName(name); } private WaterlevelData fetchWaterlevelFromArtifact(final CallContext context, final D4EArtifact d4eArtifact, final int idx, final double from, final double to) { if (d4eArtifact instanceof StaticWKmsArtifact) return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, 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 AbstractFixBunduArtifact) //including BUNDUArtifact return fetchFixationArtifactWaterlevel(context, (AbstractFixBunduArtifact) 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 double from, final double to) { log.debug("WDifferencesState obtain data from StaticWKms"); final WKms wkms = staticWKms.getWKms(from, to); if (wkms != null) { final int year = fetchStaticWKmsYear(staticWKms); return new WaterlevelData(wkms, year, false, false); } 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, false, false); } 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, false, true).filterByRange(from, to); } // private WaterlevelData fetchBUNDUArtifactWaterlevel(final CallContext // context, final BUNDUArtifact flys, // final int idx, final double from, final double to) { // log.debug("Get WKms from BUNDUArtifact"); // // 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, false, true).filterByRange(from, // to); // } private WaterlevelData fetchFixationArtifactWaterlevel(final CallContext context, final AbstractFixBunduArtifact artifact, final int idx, final double from, final double to) { log.debug("Get WKms from FixationArtifact or BUNDUArtifact.bezugswst"); final Object r = artifact.compute(context, ComputeType.ADVANCE, false); if (r instanceof CalculationResult) { final Object frR = ((CalculationResult) r).getData(); ///For BezugsWST if (frR instanceof BezugswstCalculationResults) { List<AbstractCalculationExportableResult> results = ((BezugswstCalculationResults)frR).getResults(); BezugswstMainCalculationResult mainResult = this.getBezugsWstMainResultFromList(results); if (mainResult!=null) { //Taken FROM BezugswstCalculation // We have no wst year as the wst is created by a calculation; we do not need it though final int wspYear = -1; // Remark: showAllGauges true for Fixierungsanalyse, false for WInfo, so true here as well final boolean showAllGauges = true; return new WaterlevelData( mainResult.getWQKms() , wspYear, showAllGauges, true) .filterByRange(from, to); } } else if (frR instanceof FixRealizingResult) { // Get W/Q input per gauge for this case. final FixRealizingAccess fixAccess = new FixRealizingAccess(artifact); 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(((FixRealizingResult) frR).getWQKms()[idx], year, showAllGauges, true) .filterByRange(from, to); } } return null; } private BezugswstMainCalculationResult getBezugsWstMainResultFromList(List<AbstractCalculationExportableResult> results) { for ( Object result : results) if (result instanceof BezugswstMainCalculationResult) return (BezugswstMainCalculationResult) result; return null; } /** * 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); } }