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.sinfo.parsers; mschaefer@8971: mschaefer@8971: import java.io.File; mschaefer@8971: import java.io.FilenameFilter; mschaefer@8971: import java.text.DateFormat; mschaefer@8971: import java.text.SimpleDateFormat; mschaefer@8971: import java.util.ArrayList; mschaefer@8971: import java.util.Date; 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.sinfo.importitem.DailyDischargeDayLineImport; mschaefer@8971: import org.dive4elements.river.importer.sinfo.importitem.DailyDischargeSeriesImport; mschaefer@8971: import org.dive4elements.river.model.sinfo.DailyDischarge; mschaefer@8971: import org.dive4elements.river.model.sinfo.DailyDischargeValue; mschaefer@8971: mschaefer@8971: /** mschaefer@8971: * Reads and parses a daily discharge file mschaefer@8971: * mschaefer@8971: * @author Matthias Schäfer mschaefer@8971: * mschaefer@8971: */ mschaefer@8971: public class DailyDischargeParser extends AbstractParser { mschaefer@8971: mschaefer@8971: /***** FIELDS *****/ mschaefer@8971: mschaefer@8971: private static final Logger log = Logger.getLogger(DailyDischargeParser.class); mschaefer@8971: mschaefer@8971: static final Pattern IMPORT_FILENAME = Pattern.compile("^(.+)_mittlerer_Tagesabfluss.csv", Pattern.CASE_INSENSITIVE); mschaefer@8971: mschaefer@8971: private static final Pattern META_GAUGENAME = Pattern.compile("^#\\s*Stations-*Name:\\s*(\\S[^;]*).*", Pattern.CASE_INSENSITIVE); mschaefer@8971: mschaefer@8971: private static final Pattern META_GAUGENUMBER = Pattern.compile("^#\\s*Stations-*Nummer:\\s*(\\S[^;]*).*", Pattern.CASE_INSENSITIVE); mschaefer@8971: mschaefer@8971: private static final Pattern META_COLUMNTITLES = Pattern.compile("^#*\\s*Datum\\s*;\\s*Q.*", Pattern.CASE_INSENSITIVE); mschaefer@8971: mschaefer@8971: private static final DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy"); mschaefer@8971: mschaefer@8971: mschaefer@8971: /***** CONSTRUCTORS *****/ mschaefer@8971: mschaefer@8971: public DailyDischargeParser(final File importPath, final File rootRelativePath, final ImportRiver river) { mschaefer@8971: super(importPath, rootRelativePath, river); mschaefer@8971: } 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.skipSInfoDailyDischarge(); mschaefer@8971: } mschaefer@8971: mschaefer@8971: /** mschaefer@8971: * Creates a list of parsers for all daily discharge 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: if (importDir.exists()) { mschaefer@8988: final File[] files = importDir.listFiles(new FilenameFilter() { mschaefer@8988: @Override mschaefer@8988: public boolean accept(final File dir, final String name) { mschaefer@8988: return IMPORT_FILENAME.matcher(name).matches(); mschaefer@8988: } mschaefer@8988: }); mschaefer@8988: for (final File file : files) mschaefer@8988: parsers.add(new DailyDischargeParser(file, new File(relativeDir, file.getName()), river)); mschaefer@8988: } mschaefer@8971: return parsers; mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected boolean kmMustBeUnique() { mschaefer@8971: return false; mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected DailyDischargeSeriesImport createSeriesImport(final String filename) { mschaefer@8971: return new DailyDischargeSeriesImport(filename); mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected DailyDischargeDayLineImport createKmLineImport(final Double km, final String[] values) { mschaefer@8971: Date day = null; mschaefer@8971: try { mschaefer@8971: day = dateFormat.parse(values[0]); mschaefer@8971: } mschaefer@8971: catch (final Exception e) { mschaefer@8971: logError("Invalid date in line " + this.in.getLineNumber()); mschaefer@8971: return null; mschaefer@8971: } mschaefer@8971: if (parseDoubleWithNull(values[1]) == null) { mschaefer@8971: logError("Invalid discharge value in line " + this.in.getLineNumber()); mschaefer@8971: return null; mschaefer@8971: } mschaefer@8971: return new DailyDischargeDayLineImport(day, Double.valueOf(parseDoubleWithNull(values[1]).doubleValue())); mschaefer@8971: } mschaefer@8971: mschaefer@8971: @Override mschaefer@8971: protected boolean handleMetaOther() { mschaefer@8971: if (handleMetaGaugeName()) mschaefer@8971: return true; mschaefer@8971: else if (handleMetaGaugeNumber()) mschaefer@8971: return true; mschaefer@8971: else mschaefer@8971: return false; mschaefer@8971: } mschaefer@8971: mschaefer@8971: private boolean handleMetaGaugeName() { mschaefer@8971: final Matcher m = META_GAUGENAME.matcher(this.currentLine); mschaefer@8971: if (m.matches()) { mschaefer@8971: this.metaPatternsMatched.add(META_GAUGENAME); mschaefer@8971: this.seriesHeader.setGaugeName(m.group(1).trim()); mschaefer@8971: return true; mschaefer@8971: } mschaefer@8971: return false; mschaefer@8971: } mschaefer@8971: mschaefer@8971: private boolean handleMetaGaugeNumber() { mschaefer@8971: final Matcher m = META_GAUGENUMBER.matcher(this.currentLine); mschaefer@8971: if (m.matches()) { mschaefer@8971: this.metaPatternsMatched.add(META_GAUGENUMBER); mschaefer@8971: this.seriesHeader.setGaugeNumber(Long.parseLong(m.group(1))); 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 (!META_COLUMNTITLES.matcher(this.currentLine).matches()) mschaefer@8971: return false; mschaefer@8971: this.metaPatternsMatched.add(META_COLUMNTITLES); mschaefer@8971: this.columnTitles.clear(); mschaefer@8971: final String[] titles = this.currentLine.split(SEPARATOR_CHAR, 0); mschaefer@8971: for (int i = 0; i <= titles.length - 1; i++) mschaefer@8971: this.columnTitles.add(titles[i].trim()); mschaefer@8971: this.seriesHeader.setGauge(this.river.getPeer().findGauge(this.seriesHeader.getGaugeNumber(), this.seriesHeader.getGaugeName())); mschaefer@8971: if (this.seriesHeader.getGauge() == null) { mschaefer@8971: logError("Gauge not found, file skipped"); mschaefer@8971: this.headerParsingState = ParsingState.STOP; mschaefer@8971: } mschaefer@8971: return true; mschaefer@8971: } mschaefer@8971: }