view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhcalculation/SoilKindKmValueFinder.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 45f1ad66560e
children 6e5ff436febe
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.tkhcalculation;

import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;

import org.apache.commons.lang.math.DoubleRange;
import org.dive4elements.river.artifacts.model.Calculation;
import org.dive4elements.river.backend.SessionHolder;
import org.dive4elements.river.model.River;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.type.StandardBasicTypes;

/**
 * @author Matthias Schäfer
 */
final class SoilKindKmValueFinder {

    /***** FIELDS *****/

    // private static Logger log = Logger.getLogger(SoilKindKmValueFinder.class);

    /**
     * Query selecting the bed mobility attribute for a range of stations of a river
     */
    private static final String SQL_BED_MOBILITY = "SELECT bmv.station, bmv.moving"
            + " FROM bed_mobility bm INNER JOIN bed_mobility_values bmv ON bm.id = bmv.bed_mobility_id"
            + " WHERE (bm.river_id=:river_id) AND (bmv.station BETWEEN (:fromkm-0.0001) AND (:tokm+0.0001))" + " ORDER BY bmv.station ASC";

    private final NavigableMap<Double, SoilKind> kmMobility = new TreeMap<>();

    private Calculation problems;

    /***** CONSTRUCTORS *****/

    private SoilKindKmValueFinder(final Calculation problems, final List<Object[]> queryRows) {
        this.problems = problems;

        for (int i = 0; i <= queryRows.size() - 1; i++) {
            this.kmMobility.put(Double.valueOf((double) queryRows.get(i)[0]), (((int) queryRows.get(i)[1]) == 1) ? SoilKind.mobil : SoilKind.starr);
        }
    }

    /***** METHODS *****/

    /**
     * Loads the range of the river's kms with their soil kind.
     *
     * @return Whether the load has been successful
     */
    public static SoilKindKmValueFinder loadValues(final Calculation problems, final River river, final DoubleRange kmRange) {
        final Session session = SessionHolder.HOLDER.get();
        final SQLQuery sqlQuery = session.createSQLQuery(SQL_BED_MOBILITY).addScalar("station", StandardBasicTypes.DOUBLE).addScalar("moving",
                StandardBasicTypes.INTEGER);
        sqlQuery.setInteger("river_id", river.getId().intValue());
        sqlQuery.setDouble("fromkm", kmRange.getMinimumDouble());
        sqlQuery.setDouble("tokm", kmRange.getMaximumDouble());
        final List<Object[]> rows = sqlQuery.list();
        if (rows.size() >= 1)
            return new SoilKindKmValueFinder(problems, rows);

        problems.addProblem("soilkindkmvaluefinder.empty");
        return null;
    }

    /***** METHODS *****/

    /**
     * Searches a km with its soil kind
     */
    public SoilKind findSoilKind(final double km) {

        if (this.kmMobility.containsKey(Double.valueOf(km)))
            return this.kmMobility.get(Double.valueOf(km));

        final Entry<Double, SoilKind> streamUp = this.kmMobility.floorEntry(Double.valueOf(km));
        if (streamUp == null) {
            reportProblem(km);
            return null;
        }

        // Return the soil kind of the neighbouring station with the shorter distance to the candidate.
        final Entry<Double, SoilKind> streamDown = this.kmMobility.ceilingEntry(Double.valueOf(km));
        if (streamDown == null)
            return streamUp.getValue();

        final double streamUpValue = streamUp.getKey().doubleValue();
        final double streamDownValue = streamDown.getKey().doubleValue();

        if ((streamUpValue + streamDownValue) / 2 <= km)
            return streamUp.getValue();

        return streamDown.getValue();
    }

    private void reportProblem(final double km) {
        if (this.problems == null)
            return;

        this.problems.addProblem(km, "soilkindkmvaluefinder.missing");

        // report problem only once
        this.problems = null;
    }
}

http://dive4elements.wald.intevation.org