view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/DefaultBedHeights.java @ 8942:11bf13cf0463

Minor changes to tkh calculation. Loading default bed heights form config file.
author gernotbelger
date Fri, 09 Mar 2018 18:47:06 +0100
parents
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