Mercurial > dive4elements > river
comparison backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelParser.java @ 8989:2693bfaf503d
Fixed several BigDecimal(double) creations by BigDecimal(String) parsing to avoid unnecessary decimal digits
author | mschaefer |
---|---|
date | Mon, 09 Apr 2018 09:07:00 +0200 |
parents | 5e38e2924c07 |
children | c43d8c1a4455 |
comparison
equal
deleted
inserted
replaced
8988:ae76f618d990 | 8989:2693bfaf503d |
---|---|
10 | 10 |
11 import java.io.File; | 11 import java.io.File; |
12 import java.io.IOException; | 12 import java.io.IOException; |
13 import java.math.BigDecimal; | 13 import java.math.BigDecimal; |
14 import java.text.NumberFormat; | 14 import java.text.NumberFormat; |
15 import java.text.ParseException; | |
16 import java.util.ArrayList; | 15 import java.util.ArrayList; |
17 import java.util.List; | 16 import java.util.List; |
18 import java.util.regex.Matcher; | 17 import java.util.regex.Matcher; |
19 import java.util.regex.Pattern; | 18 import java.util.regex.Pattern; |
20 | 19 |
21 import org.apache.log4j.Logger; | 20 import org.apache.log4j.Logger; |
22 | 21 import org.dive4elements.river.backend.utils.DateUtil; |
22 import org.dive4elements.river.importer.ImportRange; | |
23 import org.dive4elements.river.importer.ImportTimeInterval; | 23 import org.dive4elements.river.importer.ImportTimeInterval; |
24 import org.dive4elements.river.importer.ImportUnit; | 24 import org.dive4elements.river.importer.ImportUnit; |
25 | |
26 import org.dive4elements.river.importer.ImportRange; | |
27 import org.dive4elements.river.importer.ImportWst; | 25 import org.dive4elements.river.importer.ImportWst; |
28 import org.dive4elements.river.importer.ImportWstColumn; | 26 import org.dive4elements.river.importer.ImportWstColumn; |
29 import org.dive4elements.river.importer.ImportWstColumnValue; | 27 import org.dive4elements.river.importer.ImportWstColumnValue; |
30 import org.dive4elements.river.importer.ImportWstQRange; | 28 import org.dive4elements.river.importer.ImportWstQRange; |
31 import org.dive4elements.river.backend.utils.DateUtil; | 29 import org.dive4elements.river.importer.common.AbstractParser; |
32 | 30 |
33 | 31 |
34 /** | 32 /** |
35 * Parse CSV Waterlevel files. | 33 * Parse CSV Waterlevel files. |
36 * As these waterlevels are probably used in fixation analysis | 34 * As these waterlevels are probably used in fixation analysis |
41 public class WaterlevelParser extends LineParser { | 39 public class WaterlevelParser extends LineParser { |
42 | 40 |
43 private static final Logger log = Logger.getLogger(WaterlevelParser.class); | 41 private static final Logger log = Logger.getLogger(WaterlevelParser.class); |
44 | 42 |
45 private static final NumberFormat nf = | 43 private static final NumberFormat nf = |
46 NumberFormat.getInstance(DEFAULT_LOCALE); | 44 NumberFormat.getInstance(DEFAULT_LOCALE); |
47 | 45 |
48 private static final Pattern META_Q_RANGE = | 46 private static final Pattern META_Q_RANGE = |
49 Pattern.compile("Abfluss\\s\\[(.*)\\];(.*)"); | 47 Pattern.compile("Abfluss\\s\\[(.*)\\];(.*)"); |
50 | 48 |
51 public static final Pattern META_UNIT = | 49 public static final Pattern META_UNIT = |
52 Pattern.compile("^Einheit: \\[(.*)\\].*"); | 50 Pattern.compile("^Einheit: \\[(.*)\\].*"); |
53 | 51 |
54 public static final double INTERVAL_GAP = 0.00001d; | 52 public static final BigDecimal INTERVAL_GAP = new BigDecimal("0.00001"); |
55 | 53 |
56 private List<ImportWst> waterlevels; | 54 private final List<ImportWst> waterlevels; |
57 | 55 |
58 private ImportWst current; | 56 private ImportWst current; |
59 | 57 |
60 /** The Waterlevel-Wst s will always have but one column. */ | 58 /** The Waterlevel-Wst s will always have but one column. */ |
61 private ImportWstColumn column; | 59 private ImportWstColumn column; |
68 | 66 |
69 private String currentDescription; | 67 private String currentDescription; |
70 | 68 |
71 | 69 |
72 public WaterlevelParser() { | 70 public WaterlevelParser() { |
73 waterlevels = new ArrayList<ImportWst>(); | 71 this.waterlevels = new ArrayList<>(); |
74 } | 72 } |
75 | 73 |
76 | 74 |
77 public List<ImportWst> getWaterlevels() { | 75 public List<ImportWst> getWaterlevels() { |
78 return waterlevels; | 76 return this.waterlevels; |
79 } | 77 } |
80 | 78 |
81 | 79 |
82 @Override | 80 @Override |
83 public void parse(File file) throws IOException { | 81 public void parse(final File file) throws IOException { |
84 currentDescription = file.getName(); | 82 this.currentDescription = file.getName(); |
85 | 83 |
86 super.parse(file); | 84 super.parse(file); |
87 } | 85 } |
88 | 86 |
89 | 87 |
90 @Override | 88 @Override |
91 protected void reset() { | 89 protected void reset() { |
92 currentQRange = null; | 90 this.currentQRange = null; |
93 current = new ImportWst(currentDescription); | 91 this.current = new ImportWst(this.currentDescription); |
94 current.setNumberColumns(1); | 92 this.current.setNumberColumns(1); |
95 column = current.getColumn(0); | 93 this.column = this.current.getColumn(0); |
96 column.setName(currentDescription); | 94 this.column.setName(this.currentDescription); |
97 column.setDescription(currentDescription); | 95 this.column.setDescription(this.currentDescription); |
98 | 96 |
99 // Try to extract and set the TimeInterval. | 97 // Try to extract and set the TimeInterval. |
100 Matcher m = WaterlevelDifferencesParser.YEARS_IN_COLUMN.matcher( | 98 final Matcher m = WaterlevelDifferencesParser.YEARS_IN_COLUMN.matcher( |
101 currentDescription); | 99 this.currentDescription); |
102 | 100 |
103 if (m.matches()) { | 101 if (m.matches()) { |
104 int startYear = Integer.parseInt(m.group(1)); | 102 final int startYear = Integer.parseInt(m.group(1)); |
105 int endYear = Integer.parseInt(m.group(2)); | 103 final int endYear = Integer.parseInt(m.group(2)); |
106 ImportTimeInterval time = new ImportTimeInterval( | 104 final ImportTimeInterval time = new ImportTimeInterval( |
107 DateUtil.getStartDateFromYear(startYear), | 105 DateUtil.getStartDateFromYear(startYear), |
108 DateUtil.getEndDateFromYear(endYear) | 106 DateUtil.getEndDateFromYear(endYear) |
109 ); | 107 ); |
110 column.setTimeInterval(time); | 108 this.column.setTimeInterval(time); |
111 } else { | 109 } else { |
112 log.debug("No time interval in column header found: " | 110 log.debug("No time interval in column header found: " |
113 + currentDescription); | 111 + this.currentDescription); |
114 } | 112 } |
115 | 113 |
116 current.setKind(7); | 114 this.current.setKind(7); |
117 } | 115 } |
118 | 116 |
119 | 117 |
120 @Override | 118 @Override |
121 protected void finish() { | 119 protected void finish() { |
122 if (current != null) { | 120 if (this.current != null) { |
123 if (currentQRange != null) { | 121 if (this.currentQRange != null) { |
124 List<ImportWstColumnValue> cValues = column.getColumnValues(); | 122 final List<ImportWstColumnValue> cValues = this.column.getColumnValues(); |
125 // Set end of range to last station | 123 // Set end of range to last station |
126 // or expand range to minimal length in case it would be 0 | 124 // or expand range to minimal length in case it would be 0 |
127 // TODO: should otherwise be extended to | 125 // TODO: should otherwise be extended to |
128 // (first station of next range - INTERVAL_GAP), | 126 // (first station of next range - INTERVAL_GAP), |
129 // assuming always ascending stations | 127 // assuming always ascending stations |
130 BigDecimal lastStation = cValues.get(cValues.size() -1) | 128 final BigDecimal lastStation = cValues.get(cValues.size() -1) |
131 .getPosition(); | 129 .getPosition(); |
132 if (lastStation.compareTo(currentRange.getA()) == 0) { | 130 if (lastStation.compareTo(this.currentRange.getA()) == 0) { |
133 currentRange.setB(new BigDecimal(lastStation.doubleValue() | 131 this.currentRange.setB(lastStation.add(INTERVAL_GAP)); |
134 + INTERVAL_GAP)); | |
135 } | 132 } |
136 else { | 133 else { |
137 currentRange.setB(lastStation); | 134 this.currentRange.setB(lastStation); |
138 } | 135 } |
139 | 136 |
140 currentQRange.setRange(currentRange); | 137 this.currentQRange.setRange(this.currentRange); |
141 column.addColumnQRange(currentQRange); | 138 this.column.addColumnQRange(this.currentQRange); |
142 } | 139 } |
143 | 140 |
144 waterlevels.add(current); | 141 this.waterlevels.add(this.current); |
145 } | 142 } |
146 } | 143 } |
147 | 144 |
148 @Override | 145 @Override |
149 protected void handleLine(int lineNum, String line) { | 146 protected void handleLine(final int lineNum, final String line) { |
150 if (line.startsWith(START_META_CHAR)) { | 147 if (line.startsWith(START_META_CHAR)) { |
151 handleMetaLine(stripMetaLine(line)); | 148 handleMetaLine(stripMetaLine(line)); |
152 return; | 149 return; |
153 } | 150 } |
154 else if (handleQRange(line)) { | 151 else if (handleQRange(line)) { |
159 return; | 156 return; |
160 } | 157 } |
161 } | 158 } |
162 | 159 |
163 | 160 |
164 private void handleMetaLine(String meta) { | 161 private void handleMetaLine(final String meta) { |
165 Matcher m = META_UNIT.matcher(meta); | 162 final Matcher m = META_UNIT.matcher(meta); |
166 | 163 |
167 if (m.matches()) { | 164 if (m.matches()) { |
168 String unit = m.group(1); | 165 final String unit = m.group(1); |
169 log.debug("Found unit: '" + unit + "'"); | 166 log.debug("Found unit: '" + unit + "'"); |
170 | 167 |
171 current.setUnit(new ImportUnit(unit)); | 168 this.current.setUnit(new ImportUnit(unit)); |
172 } | 169 } |
173 } | 170 } |
174 | 171 |
175 | 172 |
176 private boolean handleQRange(String line) { | 173 private boolean handleQRange(final String line) { |
177 Matcher m = META_Q_RANGE.matcher(line); | 174 final Matcher m = META_Q_RANGE.matcher(line); |
178 | 175 |
179 if (m.matches()) { | 176 if (m.matches()) { |
180 String unitStr = m.group(1); | 177 final String unitStr = m.group(1); |
181 String valueStr = m.group(2); | 178 final String valueStr = m.group(2); |
182 try { | 179 try { |
183 if (currentQRange != null) { | 180 if (this.currentQRange != null) { |
184 // Finish off the last one. | 181 // Finish off the last one. |
185 List<ImportWstColumnValue> cValues = column | 182 final List<ImportWstColumnValue> cValues = this.column |
186 .getColumnValues(); | 183 .getColumnValues(); |
187 // Set end of range to last station. | 184 // Set end of range to last station. |
188 currentRange.setB(cValues.get(cValues.size() -1) | 185 this.currentRange.setB(cValues.get(cValues.size() -1) |
189 .getPosition()); | 186 .getPosition()); |
190 currentQRange.setRange(currentRange); | 187 this.currentQRange.setRange(this.currentRange); |
191 column.addColumnQRange(currentQRange); | 188 this.column.addColumnQRange(this.currentQRange); |
192 } | 189 } |
193 currentQRange = new ImportWstQRange(null, | 190 this.currentQRange = new ImportWstQRange(null, |
194 new BigDecimal(nf.parse(valueStr).doubleValue())); | 191 AbstractParser.parseDecimal(valueStr)); |
195 currentRange = new ImportRange(); | 192 this.currentRange = new ImportRange(); |
196 | 193 |
197 log.debug("Found new Q range: Q=" + valueStr); | 194 log.debug("Found new Q range: Q=" + valueStr); |
198 | 195 |
199 return true; | 196 return true; |
200 } | 197 } |
201 catch (ParseException pe) { | 198 catch (final NumberFormatException pe) { |
202 log.warn("Unparseable Q range: '" + line + "'"); | 199 log.warn("Unparseable Q range: '" + line + "'"); |
203 } | 200 } |
204 } | 201 } |
205 | 202 |
206 return false; | 203 return false; |
207 } | 204 } |
208 | 205 |
209 | 206 |
210 private void handleDataLine(String line) { | 207 private void handleDataLine(final String line) { |
211 String[] cols = line.split(SEPERATOR_CHAR); | 208 final String[] cols = line.split(SEPERATOR_CHAR); |
212 | 209 |
213 if (cols == null || cols.length < 2) { | 210 if (cols == null || cols.length < 2) { |
214 log.warn("skip invalid waterlevel line: '" + line + "'"); | 211 log.warn("skip invalid waterlevel line: '" + line + "'"); |
215 return; | 212 return; |
216 } | 213 } |
217 | 214 |
218 try { | 215 try { |
219 // Store the value and remember the position for QRange, if needed. | 216 // Store the value and remember the position for QRange, if needed. |
220 Double station = nf.parse(cols[0]).doubleValue(); | 217 final BigDecimal station = AbstractParser.parseDecimal(cols[0]); |
221 Double value = nf.parse(cols[1]).doubleValue(); | 218 final BigDecimal value = AbstractParser.parseDecimal(cols[1]); |
222 | 219 |
223 BigDecimal stationBD = new BigDecimal(station); | 220 this.column.addColumnValue(station, value); |
224 | 221 |
225 column.addColumnValue(stationBD, new BigDecimal(value)); | 222 if (this.currentRange.getA() == null) { |
226 | 223 this.currentRange.setA(station); |
227 if (currentRange.getA() == null) { | 224 } |
228 currentRange.setA(stationBD); | 225 } |
229 } | 226 catch (final NumberFormatException pe) { |
230 } | |
231 catch (ParseException pe) { | |
232 log.warn("Unparseable number in data row: " + line); | 227 log.warn("Unparseable number in data row: " + line); |
233 } | 228 } |
234 } | 229 } |
235 } | 230 } |
236 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 231 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |