view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/DefaultBedHeights.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 11bf13cf0463
children fb976ea01463
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.tkhstate;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberRange;
import org.dive4elements.artifacts.common.utils.Config;
import org.dive4elements.river.artifacts.model.Calculation;
import org.dive4elements.river.model.BedHeight;
import org.dive4elements.river.model.Range;
import org.dive4elements.river.model.River;

/**
 * This class knows how to find the default bed heights defined for tkh calculation
 *
 * @author Gernot Belger
 */
final class DefaultBedHeights {
    private static final String CONFIG_FILE = "sinfo_tkh_bedheights.properties";
    private final River river;

    public DefaultBedHeights(final River river) {
        this.river = river;
    }

    public List<BedHeight> getBedHeights(final Calculation problems) {
        final Collection<String> bedHeightNames = loadBedHeightDefaultsForRiver(this.river, problems);

        final List<BedHeight> defaultBedHeights = loadBedHeightsByName(this.river, bedHeightNames, problems);

        final List<BedHeight> validBedHeights = new ArrayList<>(defaultBedHeights.size());

        // REMARK: check for bad ranges because db schema allow for incomplete ranges, and ignore if this is the case
        for (final BedHeight bedHeight : defaultBedHeights) {

            final Range range = bedHeight.getRange();

            if (range.getA() == null || range.getB() == null)
                problems.addProblem("sinfo.bedheightsfinder.badrange", bedHeight.getDescription());
            else
                validBedHeights.add(bedHeight);
        }

        /* check for overlapping ranges, N2-search, but we expect only have small numbers of bed heights */
        final List<BedHeight> result = new ArrayList<>(defaultBedHeights.size());

        for (int i = 0; i < defaultBedHeights.size(); i++) {
            final BedHeight bedHeight = validBedHeights.get(i);

            final Range range = bedHeight.getRange();
            final NumberRange bedRange = new NumberRange(range.getA(), range.getB());

            if (overlapsRange(bedRange, validBedHeights, i + 1)) {
                problems.addProblem("sinfo.bedheightsfinder.overlappingrange", bedHeight.getDescription());
            } else
                result.add(bedHeight);
        }

        return result;
    }

    private static Collection<String> loadBedHeightDefaultsForRiver(final River river, final Calculation problems) {
        final File configDir = Config.getConfigDirectory();
        final File configFile = new File(configDir, CONFIG_FILE);

        final Properties properties = new Properties();
        try (final InputStreamReader reader = new InputStreamReader(Files.newInputStream(configFile.toPath()), StandardCharsets.ISO_8859_1)) {
            properties.load(reader);

            final String value = properties.getProperty(river.getName());
            final String[] split = StringUtils.split(StringUtils.trim(value), ',');
            if (ArrayUtils.isEmpty(split)) {
                problems.addProblem("sinfo.bedheightsfinder.configfile.missingriver", CONFIG_FILE, river.getName());
                return Collections.emptyList();
            }

            return Arrays.asList(split);
        }
        catch (final IOException e) {
            e.printStackTrace();
            problems.addProblem("sinfo.bedheightsfinder.configfile.loaderror", CONFIG_FILE, e.getMessage());
            return Collections.emptyList();
        }
    }

    private static List<BedHeight> loadBedHeightsByName(final River shouldBeRiver, final Collection<String> bedHeightNames, final Calculation problems) {

        final List<BedHeight> bedHeights = new ArrayList<>(bedHeightNames.size());

        for (final String name : bedHeightNames) {
            try {
                final BedHeight bedHeight = BedHeight.getBedHeightByDescription(name);
                if (bedHeight == null)
                    problems.addProblem("sinfo.bedheightsfinder.missingdescription", name);
                else {
                    final River river = bedHeight.getRiver();
                    if (!shouldBeRiver.getId().equals(river.getId()))
                        problems.addProblem("sinfo.bedheightsfinder.wrongriver", name, shouldBeRiver.getName());
                    else
                        bedHeights.add(bedHeight);
                }
            }
            catch (final Exception e) {
                e.printStackTrace();
                problems.addProblem("sinfo.bedheightsfinder.missingdescription", name);
            }
        }

        return bedHeights;
    }

    private static boolean overlapsRange(final NumberRange bedRange, final List<BedHeight> result, final int startIndex) {

        for (int i = startIndex; i < result.size(); i++) {

            final BedHeight compareBed = result.get(i);
            final Range range = compareBed.getRange();
            final NumberRange compareRange = new NumberRange(range.getA(), range.getB());

            if (compareRange.overlapsRange(bedRange))
                return true;
        }

        return false;
    }
}

http://dive4elements.wald.intevation.org