mschaefer@8971: /* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde mschaefer@8971: * Software engineering by mschaefer@8971: * Björnsen Beratende Ingenieure GmbH mschaefer@8971: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt mschaefer@8971: * mschaefer@8971: * This file is Free Software under the GNU AGPL (>=v3) mschaefer@8971: * and comes with ABSOLUTELY NO WARRANTY! Check out the mschaefer@8971: * documentation coming with Dive4Elements River for details. mschaefer@8971: */ mschaefer@8971: mschaefer@8971: package org.dive4elements.river.importer.uinfo.parsers; mschaefer@8971: mschaefer@8971: import java.io.File; mschaefer@8971: import java.util.ArrayList; mschaefer@8971: import java.util.EnumMap; mschaefer@8971: import java.util.List; mschaefer@8971: import java.util.regex.Matcher; mschaefer@8971: import java.util.regex.Pattern; mschaefer@8971: mschaefer@8971: import org.apache.log4j.Logger; mschaefer@8971: import org.dive4elements.river.importer.Config; mschaefer@8971: import org.dive4elements.river.importer.ImportRiver; mschaefer@8971: import org.dive4elements.river.importer.common.AbstractParser; mschaefer@8971: import org.dive4elements.river.importer.common.ParsingState; mschaefer@8971: import org.dive4elements.river.importer.uinfo.importitem.SalixKmLineImport; mschaefer@8971: import org.dive4elements.river.importer.uinfo.importitem.SalixSeriesImport; mschaefer@8971: import org.dive4elements.river.model.uinfo.Salix; mschaefer@8971: import org.dive4elements.river.model.uinfo.SalixValue; mschaefer@8971: mschaefer@8971: /** mschaefer@8971: * Reads and parses a salix file mschaefer@8971: * mschaefer@8971: * @author Matthias Schäfer mschaefer@8971: * mschaefer@8971: */ mschaefer@8971: public class SalixParser extends AbstractParser { mschaefer@8971: mschaefer@8971: /***** FIELDS *****/ mschaefer@8971: mschaefer@8971: private static final Logger log = Logger.getLogger(SalixParser.class); mschaefer@8971: gernotbelger@9389: private static final String IMPORT_FILENAME = "Iota.csv"; mschaefer@8971: mschaefer@9660: private static final Pattern META_FIRST = Pattern.compile("^#\\sIota.*", Pattern.CASE_INSENSITIVE); mschaefer@9660: mschaefer@8971: private static final Pattern META_EVALUATOR = Pattern.compile("^#\\sAuswerter:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE); mschaefer@8971: mschaefer@8971: private enum ColTitlePattern { mschaefer@9408: FACTOR("Iota\\s*\\[(.*)\\].*"), // mschaefer@8971: MWMNW("\\(MW-MNW\\).*\\[(.*)\\].*"); mschaefer@8971: mschaefer@8971: private final Pattern pattern; mschaefer@8971: mschaefer@8971: ColTitlePattern(final String regexp) { mschaefer@8971: this.pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE); mschaefer@8971: } mschaefer@8971: mschaefer@8971: public Pattern getPattern() { mschaefer@8971: return this.pattern; mschaefer@8971: } mschaefer@8971: } mschaefer@8971: mschaefer@9660: private final EnumMap cols; mschaefer@9660: mschaefer@9660: private final EnumMap units; mschaefer@9660: mschaefer@8971: mschaefer@8971: /***** CONSTRUCTORS *****/ mschaefer@8971: mschaefer@8971: public SalixParser(final File importPath, final File rootRelativePath, final ImportRiver river) { mschaefer@8971: super(importPath, rootRelativePath, river); mschaefer@9660: this.cols = new EnumMap<>(ColTitlePattern.class); mschaefer@9660: this.units = new EnumMap<>(ColTitlePattern.class); mschaefer@8971: } mschaefer@8971: mschaefer@8971: /***** METHODS *****/ mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected Logger getLog() { mschaefer@8971: return log; mschaefer@8971: } mschaefer@8971: mschaefer@8971: /** mschaefer@8971: * Whether this import type shall be skipped mschaefer@8971: */ mschaefer@8971: public static boolean shallSkip() { mschaefer@8971: return Config.INSTANCE.skipUInfoSalix(); mschaefer@8971: } mschaefer@8971: mschaefer@8971: /** mschaefer@8971: * Creates a list of parsers for all salix import files in a directory mschaefer@8971: */ mschaefer@8971: public static List createParsers(final File importDir, final File relativeDir, final ImportRiver river) { mschaefer@8971: final List parsers = new ArrayList<>(); mschaefer@8988: final File importFile = new File(importDir, IMPORT_FILENAME); mschaefer@8988: if (importFile.exists()) mschaefer@8988: parsers.add(new SalixParser(importFile, new File(relativeDir, IMPORT_FILENAME), river)); mschaefer@8971: return parsers; mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected SalixSeriesImport createSeriesImport(final String filename) { mschaefer@8971: return new SalixSeriesImport(filename); mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected boolean handleMetaOther() { mschaefer@9660: if (handleMetaFirst()) mschaefer@9660: return true; mschaefer@9660: else if (handleMetaEvaluator()) mschaefer@8971: return true; mschaefer@8971: else mschaefer@8971: return false; mschaefer@8971: } mschaefer@8971: mschaefer@9660: private boolean handleMetaFirst() { mschaefer@9660: final Matcher m = META_FIRST.matcher(this.currentLine); mschaefer@9660: if (m.matches()) { mschaefer@9660: this.metaPatternsMatched.add(META_FIRST); mschaefer@9660: return true; mschaefer@9660: } mschaefer@9660: return false; mschaefer@9660: } mschaefer@9660: mschaefer@8971: private boolean handleMetaEvaluator() { mschaefer@8971: final Matcher m = META_EVALUATOR.matcher(this.currentLine); mschaefer@8971: if (m.matches()) { mschaefer@8971: this.metaPatternsMatched.add(META_EVALUATOR); mschaefer@8971: this.seriesHeader.setEvaluationBy(parseMetaInfo(m.group(1).trim())); mschaefer@8971: return true; mschaefer@8971: } mschaefer@8971: return false; mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected boolean handleMetaColumnTitles() { mschaefer@8971: if (!super.handleMetaColumnTitles()) mschaefer@8971: return false; mschaefer@9660: for (final ColTitlePattern col : ColTitlePattern.values()) { mschaefer@8971: this.cols.put(col, -1); mschaefer@9660: this.units.put(col, ""); mschaefer@9660: } mschaefer@8971: for (int i = 1; i <= this.columnTitles.size() - 1; i++) { mschaefer@8971: for (final ColTitlePattern col : ColTitlePattern.values()) { mschaefer@9660: final Matcher m = col.getPattern().matcher(this.columnTitles.get(i)); mschaefer@9660: if (m.matches()) { mschaefer@8971: this.cols.put(col, i); mschaefer@9660: this.units.put(col, m.group(1)); mschaefer@8971: break; mschaefer@8971: } mschaefer@8971: } mschaefer@8971: } mschaefer@8971: if ((this.cols.get(ColTitlePattern.FACTOR) < 0) || (this.cols.get(ColTitlePattern.MWMNW) < 0)) { mschaefer@9660: logLineError("Column of the iota value and/or mnw-mw-diff could not be identified"); mschaefer@8971: this.headerParsingState = ParsingState.STOP; mschaefer@9660: return true; mschaefer@9660: } mschaefer@9660: if (!this.units.get(ColTitlePattern.FACTOR).equals("m") || !this.units.get(ColTitlePattern.MWMNW).equals("m")) { mschaefer@9660: logLineError("Column of the iota value and/or mnw-mw-diff have unsupported units"); mschaefer@9660: this.headerParsingState = ParsingState.STOP; mschaefer@8971: } mschaefer@8971: return true; mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected SalixKmLineImport createKmLineImport(final Double km, final String[] values) { mschaefer@9660: final Number factor = parseDoubleCheckNull(values, this.cols.get(ColTitlePattern.FACTOR)); mschaefer@9660: if ((factor == null) || Double.isNaN(factor.doubleValue())) { mschaefer@9660: logLineWarning(INVALID_VALUE_ERROR_FORMAT, "iota"); mschaefer@8971: return null; mschaefer@8971: } mschaefer@9660: final Number mnwmw = parseDoubleCheckNull(values, this.cols.get(ColTitlePattern.MWMNW)); mschaefer@9660: if ((mnwmw == null) || Double.isNaN(mnwmw.doubleValue())) { mschaefer@9660: logLineWarning(INVALID_VALUE_ERROR_FORMAT, "MNW-MW-diff"); mschaefer@8971: return null; mschaefer@8971: } mschaefer@9660: return new SalixKmLineImport(km, factor.doubleValue(), mnwmw.doubleValue()); mschaefer@8971: } mschaefer@8971: }