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 :

http://dive4elements.wald.intevation.org