view artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/MainWstValues.java @ 9527:7c8d62867876

Cleanup of MainWstValue code. Cache qPositions once determined.
author gernotbelger
date Tue, 02 Oct 2018 13:25:52 +0200
parents
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.model.river;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dive4elements.river.artifacts.model.WstValueTable;
import org.dive4elements.river.artifacts.model.WstValueTable.QPosition;
import org.dive4elements.river.artifacts.model.WstValueTableFactory;
import org.dive4elements.river.model.Gauge;
import org.dive4elements.river.model.MainValue;
import org.dive4elements.river.model.MainValueType;
import org.dive4elements.river.model.NamedMainValue;
import org.dive4elements.river.model.River;

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

    private static final Map<String, MainWstValues> values = new HashMap<>();

    public synchronized static MainWstValues forRiver(final River river) {

        final String riverName = river.getName();
        if (values.containsKey(riverName))
            return values.get(riverName);

        /* determine q main values of first upstream gauge */
        final Gauge gauge = river.firstUpstreamGauge();

        /* determine reference station */
        // REAMRK: we will be using the station of the gauge (not the start of the range) to determine the q-Position,
        // because we are using the discharge of the main value of the gauge. Hopefully .wt file and main values are always
        // synchrone...
        final BigDecimal referenceStation = gauge.getStation();

        /* determine q-positions for all main values */
        // REMARK: wst is cached, so we get it when we need it and do not remember it
        final WstValueTable wst = WstValueTableFactory.getTable(river);

        final Map<String, QPosition> mainValuePositions = new HashMap<>();

        final List<MainValue> mainValues = gauge.getMainValues();
        for (final MainValue mainValue : mainValues) {
            final NamedMainValue nmv = mainValue.getMainValue();
            if (nmv.getType().getName().equals(MainValueType.MainValueTypeKey.Q.getName())) {
                final BigDecimal discharge = mainValue.getValue();
                final String name = nmv.getName();

                final QPosition qPosition = wst.getQPosition(referenceStation.doubleValue(), discharge.doubleValue());
                mainValuePositions.put(name.toUpperCase(), qPosition);
            }
        }

        final MainWstValues mainWstValues = new MainWstValues(river.getName(), mainValuePositions);
        values.put(riverName, mainWstValues);
        return mainWstValues;
    }

    private final Map<String, QPosition> mainValuePositions;

    private final String riverName;

    private MainWstValues(final String riverName, final Map<String, QPosition> mainValuePositions) {
        this.riverName = riverName;
        this.mainValuePositions = mainValuePositions;
    }

    public boolean hasPosition(final String mainValueName) {

        final QPosition qPosition = this.mainValuePositions.get(mainValueName.toUpperCase());
        return qPosition != null;
    }

    public double getW(final River river, final String mainValueName, final double station) {
        // REMARK: we do not keep the river, as it is a hibernate object and this instance is statically cached.
        // However, we need to make sure we are not misused with another river
        // We also do not look up the river by its name here, because thats a database access
        if (!river.getName().equals(this.riverName))
            throw new IllegalStateException();

        // REMARK: wst is cached, so we get it when we need it and do not remember it
        final WstValueTable wst = WstValueTableFactory.getTable(river);

        final QPosition qPosition = this.mainValuePositions.get(mainValueName.toUpperCase());
        if (qPosition == null)
            return Double.NaN;

        return wst.interpolateW(station, qPosition);
    }
}

http://dive4elements.wald.intevation.org