teichmann@8025: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@8025: * Software engineering by Intevation GmbH teichmann@8025: * teichmann@8025: * This file is Free Software under the GNU AGPL (>=v3) teichmann@8025: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@8025: * documentation coming with Dive4Elements River for details. teichmann@8025: */ teichmann@8025: teichmann@8025: package org.dive4elements.river.importer.parsers; teichmann@8025: teichmann@8025: import java.io.File; teichmann@8025: import java.io.IOException; teichmann@8025: teichmann@8025: import java.text.NumberFormat; teichmann@8025: import java.text.ParseException; teichmann@8025: teichmann@8025: import java.util.ArrayList; teichmann@8025: import java.util.List; teichmann@8025: import java.util.regex.Matcher; teichmann@8025: import java.util.regex.Pattern; teichmann@8025: teichmann@8025: import org.apache.log4j.Logger; teichmann@8025: teichmann@8025: import org.dive4elements.river.importer.ImportGrainFraction; teichmann@8031: import org.dive4elements.river.importer.ImportSedimentLoadLS; teichmann@8025: import org.dive4elements.river.importer.ImportSedimentLoadLSValue; teichmann@8025: import org.dive4elements.river.importer.ImportTimeInterval; teichmann@8025: import org.dive4elements.river.importer.ImportUnit; teichmann@8025: import org.dive4elements.river.model.GrainFraction; teichmann@8025: import org.dive4elements.river.utils.DateUtil; teichmann@8025: teichmann@8025: teichmann@8025: /** Parses Sediment Yield files. */ teichmann@8025: public class SedimentLoadLSParser extends LineParser { teichmann@8025: teichmann@8025: private static final Logger log = teichmann@8025: Logger.getLogger(SedimentLoadLSParser.class); teichmann@8025: teichmann@8025: teichmann@8025: public static final NumberFormat nf = NumberFormat.getInstance(DEFAULT_LOCALE); teichmann@8025: teichmann@8025: teichmann@8025: public static final String FRAKTION_START = "Fraktion:"; teichmann@8025: teichmann@8025: public static final String FRACTION_COARSE_STR = teichmann@8025: ".*Grobkorn.*"; teichmann@8025: teichmann@8025: public static final String FRACTION_FINE_MIDDLE_STR = teichmann@8025: ".*Fein.Mittel.Kies.*"; teichmann@8025: teichmann@8025: public static final String FRACTION_SAND = teichmann@8025: ".*Sand.*"; teichmann@8025: teichmann@8025: public static final String FRACTION_SUSP_SAND = teichmann@8025: ".*susp.Sand.*"; teichmann@8025: teichmann@8025: public static final String FRACTION_SUSP_SAND_BED = teichmann@8025: ".*bettbild.Anteil.susp.Sand.*"; teichmann@8025: teichmann@8025: public static final String FRACTION_SUSP_SAND_BED_EPOCH = teichmann@8025: ".*susp.Sand.bettbildAnteil.*"; teichmann@8025: teichmann@8025: public static final String FRACTION_SUSPENDED_SEDIMENT = teichmann@8025: ".*Schwebstoff.*"; teichmann@8025: teichmann@8025: public static final String FRACTION_TOTAL = teichmann@8025: ".*gesamt.*"; teichmann@8025: teichmann@8025: teichmann@8025: public static final Pattern TIMEINTERVAL_SINGLE = teichmann@8025: Pattern.compile("\\D*([0-9]+?)\\D*"); teichmann@8025: teichmann@8025: public static final Pattern TIMEINTERVAL_EPOCH = teichmann@8025: Pattern.compile("\\D*([0-9]+?)\\s*-\\s*([0-9]+?)\\D*"); teichmann@8025: teichmann@8025: public static final Pattern META_FRACTION = teichmann@8025: Pattern.compile("^Fraktion: (.*)"); teichmann@8025: teichmann@8025: public static final Pattern META_UNIT = teichmann@8025: Pattern.compile("^Einheit: \\[(.*)\\].*"); teichmann@8025: teichmann@8025: public static final Pattern META_COLUMN_NAMES = teichmann@8025: Pattern.compile("^Fluss-km.*"); teichmann@8025: teichmann@8025: public static final Pattern META_GRAIN_FRACTION_A = teichmann@8025: Pattern.compile("\\D*(([0-9]+?,[0-9]+?)\\s*-|([0-9]++)\\s*-)(([0-9]+?,[0-9]+?)|([0-9]++))\\s*([a-zA-Z]+?)\\W*\\D*"); teichmann@8025: teichmann@8025: public static final Pattern META_GRAIN_FRACTION_B = teichmann@8025: Pattern.compile("(<|>){1}\\s*(\\w++)\\s*(([0-9]+?,[0-9]+?)\\s*-|([0-9]++)\\s*-)(([0-9]+?,[0-9]+?)|([0-9]++))\\s*([a-zA-Z]+?)"); teichmann@8025: teichmann@8025: public static final Pattern META_GRAIN_FRACTION_C = teichmann@8025: Pattern.compile("(<|>){1}\\s*((([0-9]+?,[0-9]+?)|([0-9]++))\\s*(\\w+))"); teichmann@8025: teichmann@8025: teichmann@8031: protected List sedimentYields; teichmann@8025: teichmann@8031: protected ImportSedimentLoadLS[] current; teichmann@8025: teichmann@8025: protected ImportGrainFraction grainFraction; teichmann@8025: teichmann@8025: protected ImportUnit unit; teichmann@8025: teichmann@8025: protected String description; teichmann@8025: teichmann@8025: protected String[] columnNames; teichmann@8025: teichmann@8025: teichmann@8025: public SedimentLoadLSParser() { teichmann@8031: sedimentYields = new ArrayList(); teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: @Override teichmann@8025: public void parse(File file) throws IOException { teichmann@8025: description = file.getName(); teichmann@8025: teichmann@8025: super.parse(file); teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: @Override teichmann@8025: protected void reset() { teichmann@8025: current = null; teichmann@8025: grainFraction = null; teichmann@8025: unit = null; teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: @Override teichmann@8025: protected void finish() { teichmann@8025: if (current != null) { teichmann@8031: for (ImportSedimentLoadLS isy: current) { teichmann@8025: sedimentYields.add(isy); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: description = null; teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: @Override teichmann@8025: protected void handleLine(int lineNum, String line) { teichmann@8025: if (line.startsWith(START_META_CHAR)) { teichmann@8025: handleMetaLine(stripMetaLine(line)); teichmann@8025: } teichmann@8025: else { teichmann@8025: handleDataLine(line); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: protected void handleMetaLine(String line) { teichmann@8025: if (handleMetaUnit(line)) { teichmann@8025: return; teichmann@8025: } teichmann@8025: else if (handleMetaFraction(line)) { teichmann@8025: return; teichmann@8025: } teichmann@8025: else if (handleColumnNames(line)) { teichmann@8025: return; teichmann@8025: } teichmann@8025: else { teichmann@8025: log.warn("SYP: Unknown meta line: '" + line + "'"); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: protected boolean handleMetaUnit(String line) { teichmann@8025: Matcher m = META_UNIT.matcher(line); teichmann@8025: teichmann@8025: if (m.matches()) { teichmann@8025: unit = new ImportUnit(m.group(1)); teichmann@8025: return true; teichmann@8025: } teichmann@8025: teichmann@8025: return false; teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: public boolean handleMetaFraction(String line) { teichmann@8025: Matcher m = META_FRACTION.matcher(line); teichmann@8025: teichmann@8025: if (m.matches()) { teichmann@8025: String tmp = m.group(1); teichmann@8025: teichmann@8025: this.grainFraction = buildGrainFraction(tmp); teichmann@8025: teichmann@8025: return true; teichmann@8025: } teichmann@8025: else if (line.startsWith(FRAKTION_START)) { teichmann@8025: String newLine = line.replace(FRAKTION_START, "").trim(); teichmann@8025: if (newLine.length() == 0) { teichmann@8025: log.debug("Found total grain fraction."); teichmann@8025: this.grainFraction = new ImportGrainFraction(GrainFraction.UNKNOWN); teichmann@8025: teichmann@8025: return true; teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: return false; teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: public boolean handleColumnNames(String line) { teichmann@8025: Matcher m = META_COLUMN_NAMES.matcher(line); teichmann@8025: teichmann@8025: if (m.matches()) { teichmann@8025: columnNames = line.split(SEPERATOR_CHAR); teichmann@8025: teichmann@8025: initializeSedimentYields(); teichmann@8025: teichmann@8025: return true; teichmann@8025: } teichmann@8025: teichmann@8025: return false; teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: protected void handleDataLine(String line) { teichmann@8025: String[] vals = line.split(SEPERATOR_CHAR); teichmann@8025: teichmann@8025: if (vals == null || vals.length < columnNames.length-1) { teichmann@8025: log.warn("SYP: skip invalid data line: '" + line + "'"); teichmann@8025: return; teichmann@8025: } teichmann@8025: teichmann@8025: try { teichmann@8025: Double km = nf.parse(vals[0]).doubleValue(); teichmann@8025: teichmann@8025: for (int i = 1, n = columnNames.length-1; i < n; i++) { teichmann@8025: String curVal = vals[i]; teichmann@8025: teichmann@8025: if (curVal != null && curVal.length() > 0) { teichmann@8025: current[i-1].addValue(new ImportSedimentLoadLSValue( teichmann@8025: km, nf.parse(vals[i]).doubleValue() teichmann@8025: )); teichmann@8025: } teichmann@8025: } teichmann@8025: } teichmann@8025: catch (ParseException pe) { teichmann@8025: log.warn("SYP: unparseable number in data row '" + line + "':", pe); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: /** Initialize SedimentYields from columns, set the kind teichmann@8025: * with respect to file location (offical epoch or not?) */ teichmann@8025: private void initializeSedimentYields() { teichmann@8025: // skip first column (Fluss-km) and last column (Hinweise) teichmann@8031: current = new ImportSedimentLoadLS[columnNames.length-2]; teichmann@8025: teichmann@8025: Integer kind; teichmann@8025: teichmann@8025: if (inputFile.getAbsolutePath().contains("amtliche Epochen")) { teichmann@8025: kind = new Integer(1); teichmann@8025: } teichmann@8025: else { teichmann@8025: kind = new Integer(0); teichmann@8025: } teichmann@8025: teichmann@8025: for (int i = 0, n = columnNames.length; i < n-2; i++) { teichmann@8031: current[i] = new ImportSedimentLoadLS(this.description); teichmann@8025: current[i].setTimeInterval(getTimeInterval(columnNames[i+1])); teichmann@8025: current[i].setUnit(unit); teichmann@8025: current[i].setGrainFraction(grainFraction); teichmann@8025: current[i].setKind(kind); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: private ImportTimeInterval getTimeInterval(String column) { teichmann@8025: try { teichmann@8025: Matcher a = TIMEINTERVAL_EPOCH.matcher(column); teichmann@8025: if (a.matches()) { teichmann@8025: int yearA = nf.parse(a.group(1)).intValue(); teichmann@8025: int yearB = nf.parse(a.group(2)).intValue(); teichmann@8025: teichmann@8025: return new ImportTimeInterval( teichmann@8025: DateUtil.getStartDateFromYear(yearA), teichmann@8025: DateUtil.getEndDateFromYear(yearB) teichmann@8025: ); teichmann@8025: } teichmann@8025: teichmann@8025: Matcher b = TIMEINTERVAL_SINGLE.matcher(column); teichmann@8025: if (b.matches()) { teichmann@8025: int year = nf.parse(b.group(1)).intValue(); teichmann@8025: teichmann@8025: return new ImportTimeInterval(DateUtil.getStartDateFromYear(year)); teichmann@8025: } teichmann@8025: teichmann@8025: log.warn("SYP: Unknown time interval string: '" + column + "'"); teichmann@8025: } teichmann@8025: catch (ParseException pe) { teichmann@8025: log.warn("SYP: Could not parse years: " + column, pe); teichmann@8025: } teichmann@8025: teichmann@8025: return null; teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: private ImportGrainFraction buildGrainFraction(String gfStr) { teichmann@8025: Matcher a = META_GRAIN_FRACTION_A.matcher(gfStr); teichmann@8025: if (a.matches()) { teichmann@8025: String lowerA = a.group(2); teichmann@8025: String lowerB = a.group(3); teichmann@8025: teichmann@8025: String upperA = a.group(4); teichmann@8025: String upperB = a.group(5); teichmann@8025: teichmann@8025: String lower = lowerA != null ? lowerA : lowerB; teichmann@8025: String upper = upperA != null ? upperA : upperB; teichmann@8025: teichmann@8025: try { teichmann@8025: return new ImportGrainFraction( teichmann@8025: getGrainFractionTypeName(this.description), teichmann@8025: nf.parse(lower).doubleValue(), teichmann@8025: nf.parse(upper).doubleValue() teichmann@8025: ); teichmann@8025: } teichmann@8025: catch (ParseException pe) { teichmann@8025: log.warn("SYP: Could not parse ranges of: '" + gfStr + "'"); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: Matcher b = META_GRAIN_FRACTION_B.matcher(gfStr); teichmann@8025: if (b.matches()) { teichmann@8025: String lowerA = b.group(4); teichmann@8025: String lowerB = b.group(5); teichmann@8025: String upperA = b.group(6); teichmann@8025: String upperB = b.group(7); teichmann@8025: teichmann@8025: String lower = lowerA != null ? lowerA : lowerB; teichmann@8025: String upper = upperA != null ? upperA : upperB; teichmann@8025: teichmann@8025: try { teichmann@8025: return new ImportGrainFraction( teichmann@8025: getGrainFractionTypeName(this.description), teichmann@8025: nf.parse(lower).doubleValue(), teichmann@8025: nf.parse(upper).doubleValue() teichmann@8025: ); teichmann@8025: } teichmann@8025: catch (ParseException pe) { teichmann@8025: log.warn("SYP: Could not parse ranges of: '" + gfStr + "'"); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: Matcher c = META_GRAIN_FRACTION_C.matcher(gfStr); teichmann@8025: if (c.matches()) { teichmann@8025: String oper = c.group(1); teichmann@8025: String valueStr = c.group(3); teichmann@8025: teichmann@8025: try { teichmann@8025: Double value = nf.parse(valueStr).doubleValue(); teichmann@8025: teichmann@8025: if (oper.equals(">")) { teichmann@8025: return new ImportGrainFraction( teichmann@8025: getGrainFractionTypeName(this.description), teichmann@8025: value, teichmann@8025: null teichmann@8025: ); teichmann@8025: } teichmann@8025: else { teichmann@8025: return new ImportGrainFraction( teichmann@8025: getGrainFractionTypeName(this.description), teichmann@8025: null, teichmann@8025: value teichmann@8025: ); teichmann@8025: } teichmann@8025: } teichmann@8025: catch (ParseException pe) { teichmann@8025: log.warn("SYP: Could not parse ranges of: '" + gfStr + "'"); teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: log.warn("SYP: Unknown grain fraction: '" + gfStr + "'"); teichmann@8025: return new ImportGrainFraction(GrainFraction.UNKNOWN); teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8025: public static String getGrainFractionTypeName(String filename) { teichmann@8025: if (Pattern.matches(FRACTION_COARSE_STR, filename)) { teichmann@8025: return GrainFraction.COARSE; teichmann@8025: } teichmann@8025: else if (Pattern.matches(FRACTION_FINE_MIDDLE_STR, filename)) { teichmann@8025: return GrainFraction.FINE_MIDDLE; teichmann@8025: } teichmann@8025: else if (Pattern.matches(FRACTION_SUSP_SAND_BED, filename) || teichmann@8025: Pattern.matches(FRACTION_SUSP_SAND_BED_EPOCH, filename)) { teichmann@8025: return GrainFraction.SUSP_SAND_BED; teichmann@8025: } teichmann@8025: else if (Pattern.matches(FRACTION_SUSP_SAND, filename)) { teichmann@8025: return GrainFraction.SUSP_SAND; teichmann@8025: } teichmann@8025: else if (Pattern.matches(FRACTION_SAND, filename)) { teichmann@8025: return GrainFraction.SAND; teichmann@8025: } teichmann@8025: else if (Pattern.matches(FRACTION_SUSPENDED_SEDIMENT, filename)) { teichmann@8025: return GrainFraction.SUSPENDED_SEDIMENT; teichmann@8025: } teichmann@8025: else if (Pattern.matches(FRACTION_TOTAL, filename)) { teichmann@8025: return GrainFraction.TOTAL; teichmann@8025: } teichmann@8025: else { teichmann@8025: log.warn("SYP: Unknown grain fraction '" + filename + "'"); teichmann@8025: return GrainFraction.UNKNOWN; teichmann@8025: } teichmann@8025: } teichmann@8025: teichmann@8025: teichmann@8031: public List getSedimentYields() { teichmann@8025: return sedimentYields; teichmann@8025: } teichmann@8025: } teichmann@8025: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :