view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/RiverInfoProvider.java @ 8980:b194fa64506a

SINFO - show results themes according to spec, either raw data or floating mean values. Some improvements to error handling and handling of empty results.
author gernotbelger
date Thu, 05 Apr 2018 18:30:34 +0200
parents d9dbf0b74bc2
children aab0c2730a25
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.sinfo.common;

import java.util.List;

import org.apache.commons.lang.math.DoubleRange;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.river.artifacts.model.LocationProvider;
import org.dive4elements.river.artifacts.model.WKms;
import org.dive4elements.river.artifacts.resources.Resources;
import org.dive4elements.river.artifacts.states.WaterlevelData;
import org.dive4elements.river.model.Gauge;
import org.dive4elements.river.model.River;
import org.dive4elements.river.utils.GaugeIndex;

/**
 * @author Gernot Belger
 *
 */
public final class RiverInfoProvider {

    private static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range";

    private final River river;
    private final GaugeIndex gaugeIndex;
    private final Gauge refGauge;
    private final boolean showAllGauges;
    private final String notinrange;

    public static RiverInfoProvider forRange(final CallContext context, final River river, final DoubleRange calcRange) {

        final List<Gauge> gauges = river.determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble());
        final GaugeIndex gaugeIndex = new GaugeIndex(gauges);

        final String notinrange = Resources.getMsg(context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE);

        return new RiverInfoProvider(notinrange, river, false, gaugeIndex, null);
    }

    private RiverInfoProvider(final String notinrange, final River river, final boolean showAllGauges, final GaugeIndex gaugeIndex, final Gauge refGauge) {
        this.notinrange = notinrange;
        this.river = river;
        this.showAllGauges = showAllGauges;
        this.gaugeIndex = gaugeIndex;
        this.refGauge = refGauge;
    }

    public RiverInfoProvider forWaterlevel(final WaterlevelData waterlevel) {
        final WKms wstKms = waterlevel.getWkms();
        final Gauge waterlevelRefGauge = findReferenceGauge(wstKms);
        final boolean waterlevelShowAllGauges = waterlevel.isShowAllGauges();

        return new RiverInfoProvider(this.notinrange, this.river, waterlevelShowAllGauges, this.gaugeIndex, waterlevelRefGauge);
    }

    /**
     * Re-determines the reference gauge, in the same way as the WaterlevelArtifact would do it
     */
    private Gauge findReferenceGauge(final WKms wkms) {

        final double[] wstFromTo = findWstFromTo(wkms);
        return this.river.determineRefGauge(wstFromTo, true);
    }

    private static double[] findWstFromTo(final WKms wkms) {

        final double from = wkms.getKm(0);
        final double to = wkms.getKm(wkms.size() - 1);

        final boolean waterIncreasing = wkms.guessWaterIncreasing();
        if (waterIncreasing)
            return new double[] { to, from };

        return new double[] { from, to };
    }

    public String getLocation(final double km) {
        return LocationProvider.getLocation(this.river.getName(), km);
    }

    public String findGauge(final double km) {
        // REMARK: access the gauge once only during calculation
        final Gauge gauge = getGauge(km);

        return gauge == null ? this.notinrange : gauge.getName();
    }

    private Gauge getGauge(final double km) {

        // REMARK: using same logic as in WaterlevelExporter here

        if (this.showAllGauges)
            return this.gaugeIndex.findGauge(km);

        if (this.refGauge.getRange().contains(km))
            return this.refGauge;

        return null;
    }

    public String getReferenceGauge() {
        return this.refGauge == null ? this.notinrange : this.refGauge.getName();
    }

    public River getRiver() {
        return this.river;
    }
}

http://dive4elements.wald.intevation.org