mschaefer@9014: /* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde mschaefer@9014: * Software engineering by mschaefer@9014: * Björnsen Beratende Ingenieure GmbH mschaefer@9014: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt mschaefer@9014: * mschaefer@9014: * This file is Free Software under the GNU AGPL (>=v3) mschaefer@9014: * and comes with ABSOLUTELY NO WARRANTY! Check out the mschaefer@9014: * documentation coming with Dive4Elements River for details. mschaefer@9014: */ mschaefer@9014: mschaefer@9014: package org.dive4elements.river.importer.uinfo.parsers; mschaefer@9014: mschaefer@9014: import java.io.File; mschaefer@9014: import java.util.ArrayList; mschaefer@9014: import java.util.EnumMap; mschaefer@9014: import java.util.List; mschaefer@9014: import java.util.regex.Matcher; mschaefer@9014: import java.util.regex.Pattern; mschaefer@9014: mschaefer@9014: import org.apache.log4j.Logger; mschaefer@9014: import org.dive4elements.river.importer.Config; mschaefer@9014: import org.dive4elements.river.importer.ImportRiver; mschaefer@9014: import org.dive4elements.river.importer.common.AbstractParser; mschaefer@9014: import org.dive4elements.river.importer.common.ParsingState; mschaefer@9014: import org.dive4elements.river.importer.uinfo.importitem.VegetationSeriesImport; mschaefer@9014: import org.dive4elements.river.importer.uinfo.importitem.VegetationZoneImport; mschaefer@9014: import org.dive4elements.river.model.uinfo.Vegetation; mschaefer@9014: import org.dive4elements.river.model.uinfo.VegetationZone; mschaefer@9014: mschaefer@9014: /** mschaefer@9014: * Reads and parses a vegetation zones file mschaefer@9014: * mschaefer@9014: * @author Matthias Schäfer mschaefer@9014: * mschaefer@9014: */ mschaefer@9014: public class VegetationParser extends AbstractParser { mschaefer@9014: mschaefer@9014: /***** FIELDS *****/ mschaefer@9014: mschaefer@9014: private static final Logger log = Logger.getLogger(VegetationParser.class); mschaefer@9014: mschaefer@9014: private static final Pattern META_NAME = Pattern.compile("^#\\sEinteilung:\\s*([^;]*).*", Pattern.CASE_INSENSITIVE); mschaefer@9014: mschaefer@9014: private static final Pattern META_COLUMNTITLES = Pattern.compile("^#*\\s*Vegetationstyp\\s*;.+", Pattern.CASE_INSENSITIVE); mschaefer@9014: mschaefer@9014: private enum ColTitlePattern { mschaefer@9014: OVERFLOW_LIMIT("((.)|(Ue))berflutungsdauer-bis\\s*\\[(.*)\\].*"), // mschaefer@9401: CLASSNO("Vegetationsklasse.*"), // mschaefer@9401: COLOR_R("Rot"), // mschaefer@9401: COLOR_G("Gr((.)|(ue))n"), // mschaefer@9401: COLOR_B("Blau"); mschaefer@9014: mschaefer@9014: private final Pattern pattern; mschaefer@9014: mschaefer@9014: ColTitlePattern(final String regexp) { mschaefer@9014: this.pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE); mschaefer@9014: } mschaefer@9014: mschaefer@9014: public Pattern getPattern() { mschaefer@9014: return this.pattern; mschaefer@9014: } mschaefer@9014: } mschaefer@9014: mschaefer@9014: private final EnumMap cols = new EnumMap<>(ColTitlePattern.class); mschaefer@9014: mschaefer@9014: private int previousClassNo; mschaefer@9014: mschaefer@9014: private int previousDaysLimit; mschaefer@9014: mschaefer@9014: mschaefer@9014: /***** CONSTRUCTORS *****/ mschaefer@9014: mschaefer@9014: public VegetationParser(final File importPath, final File rootRelativePath, final ImportRiver river) { mschaefer@9014: super(importPath, rootRelativePath, river); mschaefer@9014: this.previousClassNo = 0; mschaefer@9014: this.previousDaysLimit = -1; mschaefer@9014: } mschaefer@9014: mschaefer@9014: mschaefer@9014: /***** METHODS *****/ mschaefer@9014: mschaefer@9014: @Override mschaefer@9014: protected Logger getLog() { mschaefer@9014: return log; mschaefer@9014: } mschaefer@9014: mschaefer@9014: /** mschaefer@9014: * Whether this import type shall be skipped mschaefer@9014: */ mschaefer@9014: public static boolean shallSkip() { mschaefer@9014: return Config.INSTANCE.skipUInfoVegetation(); mschaefer@9014: } mschaefer@9014: mschaefer@9014: /** mschaefer@9014: * Creates a list of parsers for all vegetation import files in a directory mschaefer@9014: */ mschaefer@9014: public static List createParsers(final File importDir, final File relativeDir, final ImportRiver river) { mschaefer@9014: final List parsers = new ArrayList<>(); mschaefer@9014: if (importDir.exists()) { mschaefer@9014: for (final File file : listFiles(importDir, ".csv")) mschaefer@9014: parsers.add(new VegetationParser(file, new File(relativeDir, file.getName()), river)); mschaefer@9014: } mschaefer@9014: return parsers; mschaefer@9014: } mschaefer@9014: mschaefer@9014: @Override mschaefer@9014: protected KmMode kmMode() { mschaefer@9014: return KmMode.NONE; mschaefer@9014: } mschaefer@9014: mschaefer@9014: @Override mschaefer@9014: protected VegetationSeriesImport createSeriesImport(final String filename) { mschaefer@9014: return new VegetationSeriesImport(filename); mschaefer@9014: } mschaefer@9014: mschaefer@9014: @Override mschaefer@9014: protected boolean handleMetaOther() { mschaefer@9014: if (handleMetaName()) mschaefer@9014: return true; mschaefer@9014: else mschaefer@9014: return false; mschaefer@9014: } mschaefer@9014: mschaefer@9014: private boolean handleMetaName() { mschaefer@9014: final Matcher m = META_NAME.matcher(this.currentLine); mschaefer@9014: if (m.matches()) { mschaefer@9014: this.metaPatternsMatched.add(META_NAME); mschaefer@9014: this.seriesHeader.setName(parseMetaInfo(m.group(1).trim())); mschaefer@9014: return true; mschaefer@9014: } mschaefer@9014: return false; mschaefer@9014: } mschaefer@9014: mschaefer@9014: @Override mschaefer@9014: protected boolean handleMetaColumnTitles() { mschaefer@9014: if (!META_COLUMNTITLES.matcher(this.currentLine).matches()) mschaefer@9014: return false; mschaefer@9014: this.metaPatternsMatched.add(META_COLUMNTITLES); mschaefer@9014: this.columnTitles.clear(); mschaefer@9014: final String[] titles = this.currentLine.split(SEPARATOR_CHAR, 0); mschaefer@9014: for (int i = 0; i <= titles.length - 1; i++) mschaefer@9014: this.columnTitles.add(titles[i].trim()); mschaefer@9014: for (final ColTitlePattern col : ColTitlePattern.values()) mschaefer@9014: this.cols.put(col, -1); mschaefer@9014: for (int i = 1; i <= this.columnTitles.size() - 1; i++) { mschaefer@9014: for (final ColTitlePattern col : ColTitlePattern.values()) { mschaefer@9014: if (col.getPattern().matcher(this.columnTitles.get(i)).matches()) { mschaefer@9014: this.cols.put(col, i); mschaefer@9014: break; mschaefer@9014: } mschaefer@9014: } mschaefer@9014: } mschaefer@9014: if ((this.cols.get(ColTitlePattern.OVERFLOW_LIMIT) < 0) || (this.cols.get(ColTitlePattern.CLASSNO) < 0)) { mschaefer@9014: logError("Column of the overflow duration limit and/or vegetation zone class could not be identified"); mschaefer@9014: this.headerParsingState = ParsingState.STOP; mschaefer@9014: return true; mschaefer@9014: } mschaefer@9014: this.previousClassNo = 0; mschaefer@9401: this.previousDaysLimit = -1; mschaefer@9014: return true; mschaefer@9014: } mschaefer@9014: mschaefer@9014: @Override mschaefer@9014: protected VegetationZoneImport createKmLineImport(final Double km, final String[] values) { mschaefer@9401: int daysLimit = 366; mschaefer@9014: int classNo = 0; mschaefer@9014: try { mschaefer@9014: if (!values[this.cols.get(ColTitlePattern.OVERFLOW_LIMIT)].trim().isEmpty()) mschaefer@9014: daysLimit = Integer.parseInt(values[this.cols.get(ColTitlePattern.OVERFLOW_LIMIT)]); mschaefer@9014: classNo = Integer.parseInt(values[this.cols.get(ColTitlePattern.CLASSNO)]); mschaefer@9014: } mschaefer@9014: catch (final Exception e) { mschaefer@9014: logError("Overflow days limit and/or vegetation zone class could not be parsed: line " + this.in.getLineNumber()); mschaefer@9014: return null; mschaefer@9014: } mschaefer@9014: // Check completeness of vegetation zone type set, if needed mschaefer@9014: // if (classNo != this.previousClassNo + 1) { mschaefer@9014: // logError("Wrong vegetation zone class number or wrong class order: line " + this.in.getLineNumber()); mschaefer@9014: // return null; mschaefer@9014: // } mschaefer@9014: // if (!this.types.containsKey(Integer.valueOf(classNo))) { mschaefer@9014: // logError("Unknown vegetation zone class: line " + this.in.getLineNumber()); mschaefer@9014: // return null; mschaefer@9014: // } mschaefer@9014: this.previousClassNo = classNo; mschaefer@9401: final int minDays = this.previousDaysLimit + 1; mschaefer@9401: this.previousDaysLimit = daysLimit; mschaefer@9401: final int red = (this.cols.get(ColTitlePattern.COLOR_R) >= 0) ? Integer.parseInt(values[this.cols.get(ColTitlePattern.COLOR_R)]) : 0; mschaefer@9401: final int green = (this.cols.get(ColTitlePattern.COLOR_G) >= 0) ? Integer.parseInt(values[this.cols.get(ColTitlePattern.COLOR_G)]) : 0; mschaefer@9401: final int blue = (this.cols.get(ColTitlePattern.COLOR_B) >= 0) ? Integer.parseInt(values[this.cols.get(ColTitlePattern.COLOR_B)]) : 0; mschaefer@9401: return new VegetationZoneImport(classNo, minDays, daysLimit, red, green, blue); mschaefer@9014: } mschaefer@9014: }