[PATCH 8 of 8] Range data handled consistently as BigDecimal to minimize the fractional part of a and b
Wald Commits
scm-commit at wald.intevation.org
Tue Apr 3 10:45:00 CEST 2018
# HG changeset patch
# User mschaefer
# Date 1522745033 -7200
# Node ID e541938dd3ab01b739eb0b3360442e57d24b68a8
# Parent a0a0a7f912abe68c7f683fa224cb37440e63b8fb
Range data handled consistently as BigDecimal to minimize the fractional part of a and b
diff -r a0a0a7f912ab -r e541938dd3ab backend/src/main/java/org/dive4elements/river/importer/ImportRange.java
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportRange.java Tue Apr 03 10:40:57 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportRange.java Tue Apr 03 10:43:53 2018 +0200
@@ -8,12 +8,11 @@
package org.dive4elements.river.importer;
-import org.dive4elements.river.model.Range;
-import org.dive4elements.river.model.River;
-
import java.math.BigDecimal;
import org.apache.log4j.Logger;
+import org.dive4elements.river.model.Range;
+import org.dive4elements.river.model.River;
/** A range that is about to be imported. */
public class ImportRange
@@ -30,7 +29,7 @@
public ImportRange() {
}
- public ImportRange(BigDecimal a) {
+ public ImportRange(final BigDecimal a) {
this.a = a;
this.b = null;
}
@@ -55,14 +54,14 @@
}
else {
if (a.compareTo(b) > 0) {
- BigDecimal t = a; a = b; b = t;
+ final BigDecimal t = a; a = b; b = t;
}
this.a = a;
this.b = b;
}
}
- private static final int compare(BigDecimal a, BigDecimal b) {
+ private static final int compare(final BigDecimal a, final BigDecimal b) {
if (a == null && b == null) {
return 0;
}
@@ -75,41 +74,54 @@
return a.compareTo(b);
}
- public int compareTo(ImportRange other) {
- int cmp = compare(a, other.a);
+ @Override
+ public int compareTo(final ImportRange other) {
+ final int cmp = compare(this.a, other.a);
if (cmp != 0) return cmp;
- return compare(b, other.b);
+ return compare(this.b, other.b);
}
public BigDecimal getA() {
- return a;
+ return this.a;
}
- public void setA(BigDecimal a) {
- if (this.b != null && a.compareTo(b) >= 0) {
+ public void setA(final BigDecimal a) {
+ if (this.b != null && a.compareTo(this.b) >= 0) {
throw new IllegalArgumentException(
- "a (" + a + ") must be smaller than b (" + b + ").");
+ "a (" + a + ") must be smaller than b (" + this.b + ").");
}
this.a = a;
}
public BigDecimal getB() {
- return b;
+ return this.b;
}
- public void setB(BigDecimal b) {
- if (b != null && b.compareTo(a) <= 0) {
+ public void setB(final BigDecimal b) {
+ if (b != null && b.compareTo(this.a) <= 0) {
throw new IllegalArgumentException(
- "b (" + b + ") must be greater than a (" + a + ") or null.");
+ "b (" + b + ") must be greater than a (" + this.a + ") or null.");
}
this.b = b;
}
- public Range getPeer(River river) {
- if (peer == null) {
- peer = ImporterSession.getInstance().getRange(river, a, b);
+ /**
+ * Difference of a and b
+ *
+ * @return b - a, or NaN if a or b null
+ */
+ public double difference() {
+ if ((this.a != null) && (this.b != null))
+ return this.b.subtract(this.a).doubleValue();
+ else
+ return Double.NaN;
+ }
+
+ public Range getPeer(final River river) {
+ if (this.peer == null) {
+ this.peer = ImporterSession.getInstance().getRange(river, this.a, this.b);
}
- return peer;
+ return this.peer;
}
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
diff -r a0a0a7f912ab -r e541938dd3ab backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java Tue Apr 03 10:40:57 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java Tue Apr 03 10:43:53 2018 +0200
@@ -8,34 +8,28 @@
package org.dive4elements.river.importer.parsers;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.math.BigDecimal;
+import java.text.NumberFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
-import java.util.Arrays;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.LineNumberReader;
-import java.io.InputStreamReader;
-import java.io.FileInputStream;
-
-import java.text.NumberFormat;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.utils.DateGuesser;
import org.dive4elements.river.backend.utils.StringUtil;
-import org.dive4elements.river.backend.utils.DateGuesser;
-
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-
-import java.math.BigDecimal;
-
-import org.dive4elements.river.importer.ImportWstQRange;
-import org.dive4elements.river.importer.ImportWstColumn;
+import org.dive4elements.river.importer.ImportRange;
import org.dive4elements.river.importer.ImportTimeInterval;
-import org.dive4elements.river.importer.ImportRange;
import org.dive4elements.river.importer.ImportUnit;
import org.dive4elements.river.importer.ImportWst;
+import org.dive4elements.river.importer.ImportWstColumn;
+import org.dive4elements.river.importer.ImportWstQRange;
public class WstParser
{
@@ -47,43 +41,41 @@
public static final String COLUMN_DATUM = "column-datum";
public static final BigDecimal UNDEFINED_ZERO =
- new BigDecimal(0.0);
+ new BigDecimal(0.0);
public static final BigDecimal MIN_RANGE =
- new BigDecimal(-Double.MAX_VALUE);
+ new BigDecimal(-Double.MAX_VALUE);
public static final BigDecimal MAX_RANGE =
- new BigDecimal(Double.MAX_VALUE);
+ new BigDecimal(Double.MAX_VALUE);
public static final String ENCODING = "ISO-8859-1";
public static final Pattern UNIT_COMMENT =
- Pattern.compile("\\*\\s*[kK][mM]\\s+(.+)");
+ Pattern.compile("\\*\\s*[kK][mM]\\s+(.+)");
public static final Pattern UNIT =
- Pattern.compile("[^\\[]*\\[([^]]+)\\].*");
+ Pattern.compile("[^\\[]*\\[([^]]+)\\].*");
public static final Pattern YEAR_INTERVAL =
- Pattern.compile("(\\d{4})\\s*[-/]\\s*(\\d{4})");
+ Pattern.compile("(\\d{4})\\s*[-/]\\s*(\\d{4})");
- public static final double INTERVAL_GAP = 0.00001d;
+ public static final BigDecimal INTERVAL_GAP = new BigDecimal("0.00001");
protected ImportWst wst;
protected ImportRange lastRange;
- protected Double lastA;
- protected Double lastB;
public WstParser() {
}
- public WstParser(ImportWst wst) {
+ public WstParser(final ImportWst wst) {
this.wst = wst;
}
public ImportWst getWst() {
- return wst;
+ return this.wst;
}
- public void setWst(ImportWst wst) {
+ public void setWst(final ImportWst wst) {
this.wst = wst;
}
@@ -91,46 +83,46 @@
public ParseException() {
}
- public ParseException(String msg) {
+ public ParseException(final String msg) {
super(msg);
}
} // class ParseException
/** Returns a new ImportTimeInterval with a date guessed from string. */
- public static ImportTimeInterval guessDate(String string) {
+ public static ImportTimeInterval guessDate(final String string) {
try {
- Matcher m = YEAR_INTERVAL.matcher(string);
+ final Matcher m = YEAR_INTERVAL.matcher(string);
if (m.matches()) {
return new ImportTimeInterval(
- DateGuesser.guessDate(m.group(1)),
- DateGuesser.guessDate(m.group(2)));
+ DateGuesser.guessDate(m.group(1)),
+ DateGuesser.guessDate(m.group(2)));
}
return new ImportTimeInterval(
- DateGuesser.guessDate(string));
+ DateGuesser.guessDate(string));
}
- catch (IllegalArgumentException iae) {
+ catch (final IllegalArgumentException iae) {
log.warn("WST: String '" + string +
- "' could not be interpreted as valid timestamp");
+ "' could not be interpreted as valid timestamp");
}
return null;
}
- public void parse(File file) throws IOException, ParseException {
+ public void parse(final File file) throws IOException, ParseException {
log.info("Parsing WST file '" + file + "'");
- if (wst == null) {
- wst = new ImportWst(file.getName());
+ if (this.wst == null) {
+ this.wst = new ImportWst(file.getName());
}
else {
- wst.setDescription(file.getName());
+ this.wst.setDescription(file.getName());
}
- LineNumberReader in =
- new LineNumberReader(
- new InputStreamReader(
- new FileInputStream(file), ENCODING));
+ final LineNumberReader in =
+ new LineNumberReader(
+ new InputStreamReader(
+ new FileInputStream(file), ENCODING));
try {
String input;
boolean first = true;
@@ -158,7 +150,7 @@
String einheit = "m ü. unbekannte Referenz";
boolean unitFound = false;
- HashSet<BigDecimal> kms = new HashSet<BigDecimal>();
+ final HashSet<BigDecimal> kms = new HashSet<>();
while ((input = in.readLine()) != null) {
String line = input;
@@ -170,13 +162,13 @@
columnCount = Integer.parseInt(line);
if (columnCount <= 0) {
throw new NumberFormatException(
- "number of columns <= 0");
+ "number of columns <= 0");
}
log.debug("Number of columns: " + columnCount);
- wst.setNumberColumns(columnCount);
+ this.wst.setNumberColumns(columnCount);
lsBezeichner = new String[columnCount];
}
- catch (NumberFormatException nfe) {
+ catch (final NumberFormatException nfe) {
log.warn("WST: invalid number.", nfe);
continue;
}
@@ -188,15 +180,15 @@
// handle Q-lines
if (line.startsWith("*\u001f")) {
- BigDecimal [] data = parseLineAsDouble(
- line, columnCount, false, true);
+ final BigDecimal [] data = parseLineAsDouble(
+ line, columnCount, false, true);
if (aktAbfluesse != null) {
// add Q-ranges obtained from previous lines
if (kmHist1 != null && kmHist2 != null
- && kmHist1.compareTo(kmHist2) < 0) {
+ && kmHist1.compareTo(kmHist2) < 0) {
// stations descending in file
- BigDecimal t = minKm; minKm = maxKm; maxKm = t;
+ final BigDecimal t = minKm; minKm = maxKm; maxKm = t;
}
addInterval(minKm, maxKm, aktAbfluesse);
minKm = MAX_RANGE;
@@ -216,7 +208,7 @@
// remember Q-values from first Q-line
// for header generation
if (firstAbfluesse == null) {
- firstAbfluesse = (BigDecimal [])aktAbfluesse.clone();
+ firstAbfluesse = aktAbfluesse.clone();
}
continue;
}
@@ -231,7 +223,7 @@
if (spezial.startsWith(COLUMN_BEZ_TEXT)) {
spezial = spezial.substring(
- COLUMN_BEZ_TEXT.length()).trim();
+ COLUMN_BEZ_TEXT.length()).trim();
if (spezial.length() == 0) {
continue;
}
@@ -239,13 +231,13 @@
}
else if (spezial.startsWith(COLUMN_BEZ_BREITE)) {
spezial = spezial.substring(
- COLUMN_BEZ_BREITE.length()).trim();
+ COLUMN_BEZ_BREITE.length()).trim();
if (spezial.length() == 0) {
continue;
}
- String[] split = spezial.split("\\s+");
+ final String[] split = spezial.split("\\s+");
colNaWidths = new int[split.length];
for (int i=0; i < split.length; i++) {
@@ -254,7 +246,7 @@
}
else if (spezial.startsWith(COLUMN_QUELLE)) {
spezial = spezial.substring(
- COLUMN_QUELLE.length()).trim();
+ COLUMN_QUELLE.length()).trim();
if (spezial.length() == 0) {
continue;
}
@@ -263,7 +255,7 @@
}
else if (spezial.startsWith(COLUMN_DATUM)) {
spezial = spezial.substring(
- COLUMN_DATUM.length()).trim();
+ COLUMN_DATUM.length()).trim();
if (spezial.length() == 0) {
continue;
}
@@ -283,7 +275,7 @@
log.debug("unit comment found");
// XXX: This hack is needed because desktop
// FLYS is broken figuring out the unit
- String [] units = m.group(1).split("\\s{2,}");
+ final String [] units = m.group(1).split("\\s{2,}");
m = UNIT.matcher(units[0]);
einheit = m.matches() ? m.group(1) : units[0];
log.debug("unit: " + einheit);
@@ -296,69 +288,69 @@
if (firstAbfluesse != null) {
if (!columnHeaderChecked) {
int unknownCount = 0;
- HashSet<String> uniqueColumnNames =
- new HashSet<String>();
+ final HashSet<String> uniqueColumnNames =
+ new HashSet<>();
if (langBezeichner != null) {
// use column name from '*!column-bez-text'-line
lsBezeichner = StringUtil.fitArray(
- langBezeichner, lsBezeichner);
+ langBezeichner, lsBezeichner);
}
for (int i = 0; i < lsBezeichner.length; ++i) {
if (lsBezeichner[i] == null
- || lsBezeichner[i].length() == 0) {
+ || lsBezeichner[i].length() == 0) {
// generate alternative column names
- double q = firstAbfluesse.length > i ?
- firstAbfluesse[i].doubleValue() : 0d;
- if (q < 0.001) {
- lsBezeichner[i] =
- "<unbekannt #" + unknownCount + ">";
- ++unknownCount;
- }
- else {
- lsBezeichner[i] = "Q="+format(q);
- }
+ final double q = firstAbfluesse.length > i ?
+ firstAbfluesse[i].doubleValue() : 0d;
+ if (q < 0.001) {
+ lsBezeichner[i] =
+ "<unbekannt #" + unknownCount + ">";
+ ++unknownCount;
+ }
+ else {
+ lsBezeichner[i] = "Q="+format(q);
+ }
}
String candidate = lsBezeichner[i];
int collision = 1;
while (!uniqueColumnNames.add(candidate)) {
candidate = lsBezeichner[i] +
- " (" + collision + ")";
+ " (" + collision + ")";
++collision;
}
- ImportWstColumn iwc = wst.getColumn(i);
+ final ImportWstColumn iwc = this.wst.getColumn(i);
iwc.setName(candidate);
if (quellen != null && i < quellen.length) {
iwc.setSource(quellen[i]);
}
- String potentialDate =
- daten != null && i < daten.length
- ? daten[i]
- : candidate;
- iwc.setTimeInterval(guessDate(potentialDate));
+ final String potentialDate =
+ daten != null && i < daten.length
+ ? daten[i]
+ : candidate;
+ iwc.setTimeInterval(guessDate(potentialDate));
}
columnHeaderChecked = true;
}
- BigDecimal [] data = parseLineAsDouble(
- line, columnCount, true, false);
+ final BigDecimal [] data = parseLineAsDouble(
+ line, columnCount, true, false);
- BigDecimal kaem = data[0];
+ final BigDecimal kaem = data[0];
if (!kms.add(kaem)) {
log.warn(
- "WST: km " + kaem +
- " (line " + in.getLineNumber() +
- ") found more than once. -> ignored");
+ "WST: km " + kaem +
+ " (line " + in.getLineNumber() +
+ ") found more than once. -> ignored");
continue;
}
// check consistence of station ordering in file
if (kmHist2 != null &&
- kmHist2.compareTo(kmHist1) != kmHist1.compareTo(kaem)
- ) {
+ kmHist2.compareTo(kmHist1) != kmHist1.compareTo(kaem)
+ ) {
throw new ParseException("WST: Stations in " + file +
- " near line " + in.getLineNumber() +
- " not ordered. File rejected.");
+ " near line " + in.getLineNumber() +
+ " not ordered. File rejected.");
}
// remember stations in two previous lines
@@ -385,25 +377,25 @@
}
else if (colNaWidths != null) {
for (int j = 0, i = 0, N = input.length();
- j < colNaWidths.length && i < N;
- i += colNaWidths[j++]
- ) {
+ j < colNaWidths.length && i < N;
+ i += colNaWidths[j++]
+ ) {
lsBezeichner[j] = input.substring(
- i, i+colNaWidths[j]).trim();
+ i, i+colNaWidths[j]).trim();
}
}
else { // fetch column names from non-comment header line
- // (above first Qs)
+ // (above first Qs)
// first column begins at position 8 in line
for (int i = 8, col = 0; i < input.length(); i += 9) {
// one column header is 9 chars wide
// but the last one may be shorter
if (col < lsBezeichner.length) {
lsBezeichner[col++] =
- input.substring(
- i,
- Math.min(i + 9, input.length())
- ).trim();
+ input.substring(
+ i,
+ Math.min(i + 9, input.length())
+ ).trim();
}
if (col == lsBezeichner.length) {
break;
@@ -417,16 +409,16 @@
if (!unitFound) {
log.warn("no unit and height reference found. Using default.");
}
- wst.setUnit(new ImportUnit(einheit));
+ this.wst.setUnit(new ImportUnit(einheit));
// add Q-ranges obtained from previous lines
// in case there was no further Q-line
// but only if there were values following the last Q-line
if (minKm != MAX_RANGE && maxKm != MIN_RANGE) {
if (kmHist1 != null && kmHist2 != null
- && kmHist1.compareTo(kmHist2) < 0) {
+ && kmHist1.compareTo(kmHist2) < 0) {
// stations descending in file
- BigDecimal t = minKm; minKm = maxKm; maxKm = t;
+ final BigDecimal t = minKm; minKm = maxKm; maxKm = t;
}
addInterval(minKm, maxKm, aktAbfluesse);
}
@@ -436,9 +428,9 @@
}
}
- protected void addValue(BigDecimal km, BigDecimal w, int index) {
+ protected void addValue(final BigDecimal km, final BigDecimal w, final int index) {
if (w != null) {
- ImportWstColumn column = wst.getColumn(index);
+ final ImportWstColumn column = this.wst.getColumn(index);
column.addColumnValue(km, w);
}
}
@@ -446,21 +438,21 @@
private static final NumberFormat NF = getNumberFormat();
private static final NumberFormat getNumberFormat() {
- NumberFormat nf = NumberFormat.getInstance();
+ final NumberFormat nf = NumberFormat.getInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
return nf;
}
- protected static String format(double value) {
+ protected static String format(final double value) {
return NF.format(value);
}
protected void addInterval(
- BigDecimal from,
- BigDecimal to,
- BigDecimal [] values
- ) {
+ final BigDecimal from,
+ final BigDecimal to,
+ final BigDecimal[] values
+ ) {
log.debug("addInterval: " + from + " " + to);
if (values == null || from == MAX_RANGE || from == MIN_RANGE) {
@@ -468,56 +460,43 @@
}
// expand single-line i.e. 0-lenght Q-range to minimal length
+ final ImportRange range = new ImportRange(from, to);
if (from == to) {
- if (lastRange != null && lastA > lastB) {
- to = new BigDecimal(from.doubleValue() - INTERVAL_GAP);
- }
- else {
- to = new BigDecimal(from.doubleValue() + INTERVAL_GAP);
- }
+ if ((this.lastRange != null) && (this.lastRange.difference() < 0.0))
+ range.setB(from.subtract(INTERVAL_GAP));
+ else
+ range.setB(from.add(INTERVAL_GAP));
}
- ImportRange range = new ImportRange(from, to);
-
// little workaround to make the q ranges tightly fit.
// Leave a very small gap to ensure that the range queries
// still work.
- if (lastRange != null) {
- double a2 = range.getA().doubleValue();
- double b2 = range.getB().doubleValue();
-
- if (lastA < lastB) {
- lastRange.setB(new BigDecimal(a2 - INTERVAL_GAP));
- }
- else { // lastA >= lastB
- lastRange.setA(new BigDecimal(b2 + INTERVAL_GAP));
- }
+ if (this.lastRange != null) {
+ if (this.lastRange.difference() > 0.0)
+ this.lastRange.setB(range.getA().subtract(INTERVAL_GAP));
+ else // lastA >= lastB
+ this.lastRange.setA(range.getB().add(INTERVAL_GAP));
}
- for (int i = 0; i < values.length; ++i) {
- ImportWstColumn column = wst.getColumn(i);
- ImportWstQRange wstQRange = new ImportWstQRange(range, values[i]);
- column.addColumnQRange(wstQRange);
- }
+ for (int i = 0; i < values.length; ++i)
+ this.wst.getColumn(i).addColumnQRange(new ImportWstQRange(range, values[i]));
- lastA = from.doubleValue();
- lastB = to.doubleValue();
- lastRange = range;
+ this.lastRange = range;
}
private static final BigDecimal [] parseLineAsDouble(
- String line,
- int count,
- boolean bStation,
- boolean bParseEmptyAsZero
- ) throws ParseException {
- String [] tokens = parseLine(line, count, bStation);
+ final String line,
+ final int count,
+ final boolean bStation,
+ final boolean bParseEmptyAsZero
+ ) throws ParseException {
+ final String [] tokens = parseLine(line, count, bStation);
- BigDecimal [] doubles = new BigDecimal[tokens.length];
+ final BigDecimal [] doubles = new BigDecimal[tokens.length];
for (int i = 0; i < doubles.length; ++i) {
- String token = tokens[i].trim();
+ final String token = tokens[i].trim();
if (token.length() != 0) {
doubles[i] = new BigDecimal(token);
}
@@ -530,11 +509,11 @@
}
private static String [] parseLine(
- String line,
- int tokenCount,
- boolean bParseStation
- ) throws ParseException {
- ArrayList<String> strings = new ArrayList<String>();
+ final String line,
+ final int tokenCount,
+ final boolean bParseStation
+ ) throws ParseException {
+ final ArrayList<String> strings = new ArrayList<>();
if (bParseStation) {
if (line.length() < 8) {
@@ -550,7 +529,7 @@
break;
}
strings.add(line.substring(pos,
- Math.min(pos + 8, line.length())));
+ Math.min(pos + 8, line.length())));
}
return strings.toArray(new String[strings.size()]);
More information about the Dive4Elements-commits
mailing list