Mercurial > dive4elements > river
view flys-backend/src/main/java/de/intevation/flys/importer/parsers/HYKParser.java @ 4768:99f9e371371b
Move distance calculation to Coordinate class. Use inheritance instead of composition in Anchor class. Made Anchor class static. Use epsilon equal comparision when checking for same station: Boy, do you ever learn that sharp equal comparison of doubles is not a clever idea!?
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Fri, 04 Jan 2013 15:35:51 +0100 |
parents | 36edf9a71cbd |
children |
line wrap: on
line source
package de.intevation.flys.importer.parsers; import de.intevation.artifacts.common.utils.FileTools; import de.intevation.flys.importer.ImportHYK; import de.intevation.flys.importer.ImportHYKEntry; import de.intevation.flys.importer.ImportHYKFormation; import de.intevation.flys.importer.ImportHYKFlowZone; import de.intevation.flys.importer.ImportHYKFlowZoneType; import java.io.File; import java.io.IOException; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.HashMap; import java.util.Map; import java.util.Date; import java.util.Calendar; import java.math.BigDecimal; import org.apache.log4j.Logger; public class HYKParser { private static Logger log = Logger.getLogger(HYKParser.class); public interface Callback { boolean hykAccept(File file); void hykParsed(HYKParser parser); } // interface Callback public static enum State { LINE_1, LINE_2, LINE_3, LINE_4, LINE_5, LINE_6 }; private static final String ENCODING = "ISO-8859-1"; protected Map<String, ImportHYKFlowZoneType> flowZoneTypes; protected ImportHYK hyk; public HYKParser() { flowZoneTypes = new HashMap<String, ImportHYKFlowZoneType>(); } public ImportHYK getHYK() { return hyk; } private static Date yearToDate(Integer year) { if (year == null) { return null; } Calendar cal = Calendar.getInstance(); cal.set(year, 0, 1, 12, 0, 0); long ms = cal.getTimeInMillis(); cal.setTimeInMillis(ms - ms%1000); return cal.getTime(); } public boolean parse(File file) { boolean debug = log.isDebugEnabled(); log.info("Parsing HYK file '" + file + "'"); LineNumberReader in = null; String description = file.getParentFile().getName() + "/" + file.getName(); hyk = new ImportHYK(null, description); try { in = new LineNumberReader( new InputStreamReader( new FileInputStream(file), ENCODING)); String line; State state = State.LINE_1; int numFormations = 0; BigDecimal km = null; BigDecimal top = null; BigDecimal bottom = null; BigDecimal distanceVL = null; BigDecimal distanceHF = null; BigDecimal distanceVR = null; Integer year = null; int numZones = 0; ImportHYKFlowZoneType [] fzts = null; BigDecimal [] coords = null; int coordPos = 0; ImportHYKEntry entry = null; ImportHYKFormation formation = null; while ((line = in.readLine()) != null) { if (line.startsWith("*") || line.startsWith("----")) { continue; } line = line.trim(); if (state != State.LINE_5 && line.length() == 0) { continue; } String [] parts = line.split("\\s+"); if (debug) { log.debug("'" + line + "': " + state); } switch (state) { case LINE_1: if (parts.length < 2) { log.error("HYK 1: not enough elements in line " + in.getLineNumber()); return false; } if (parts.length == 2) { // no year given year = null; } else { try { year = Integer.valueOf(parts[1]); } catch (NumberFormatException nfe) { log.error( "year is not an integer in line " + in.getLineNumber()); return false; } } try { km = new BigDecimal(parts[0]); numFormations = Integer.parseInt( parts[parts.length > 2 ? 2 : 1]); } catch (NumberFormatException nfe) { log.error( "parsing number of formations " + "or km failed in line " + in.getLineNumber()); return false; } entry = new ImportHYKEntry(hyk, km, yearToDate(year)); hyk.addEntry(entry); state = State.LINE_2; break; case LINE_2: if (parts.length < 3) { log.error("HYK 2: not enough elements in line " + in.getLineNumber()); return false; } try { numZones = Integer.parseInt(parts[0]); bottom = new BigDecimal(parts[1]); top = new BigDecimal(parts[2]); } catch (NumberFormatException nfe) { log.error( "HYK: parsing num zones, bottom or top height " + "failed in line " + in.getLineNumber()); return false; } formation = new ImportHYKFormation(); formation.setBottom(bottom); formation.setTop(top); entry.addFormation(formation); state = State.LINE_3; break; case LINE_3: if (parts.length != numZones) { log.error( "HYK: number of flow zones mismatches " + "in line " + in.getLineNumber()); return false; } fzts = new ImportHYKFlowZoneType[parts.length]; for (int i = 0; i < fzts.length; ++i) { fzts[i] = getFlowZoneType(parts[i]); } coords = new BigDecimal[numZones]; state = State.LINE_4; break; case LINE_4: try { int N = Math.min(parts.length, coords.length); for (coordPos = 0; coordPos < N; ++coordPos) { coords[coordPos] = new BigDecimal(parts[coordPos]); } } catch (NumberFormatException nfe) { log.error("HYK: cannot parse number in line " + in.getLineNumber()); return false; } state = State.LINE_5; break; case LINE_5: if (parts.length + coordPos < coords.length) { log.error("HYK 5: not enough elements in line " + in.getLineNumber()); return false; } try { for (int i = 0; i < parts.length && coordPos < coords.length; ++i, ++coordPos ) { coords[coordPos] = new BigDecimal(parts[i]); } } catch (NumberFormatException nfe) { log.error("HYK: cannot parse number in line " + in.getLineNumber()); return false; } for (int i = 0; i < coords.length; ++i) { BigDecimal a = coords[i]; BigDecimal b = coords[i == coords.length-1 ? i : i+1]; if (a.compareTo(b) > 0) { log.warn("HYK: zone coordinates swapped in line " + in.getLineNumber()); BigDecimal c = a; a = b; b = c; } ImportHYKFlowZone zone = new ImportHYKFlowZone( formation, fzts[i], a, b); formation.addFlowZone(zone); } state = State.LINE_6; break; case LINE_6: if (parts.length < 3) { log.error("HYK 6: not enough elements in line " + in.getLineNumber()); return false; } try { distanceVL = new BigDecimal(parts[0]); distanceHF = new BigDecimal(parts[1]); distanceVR = new BigDecimal(parts[2]); } catch (NumberFormatException nfe) { log.error("HYK: cannot parse number in line " + in.getLineNumber()); return false; } formation.setDistanceVL(distanceVL); formation.setDistanceHF(distanceHF); formation.setDistanceVR(distanceVR); // continue with next formation. state = --numFormations > 0 // formations left? ? State.LINE_2 : State.LINE_1; break; } } } catch (IOException ioe) { log.error("HYK: Error reading file.", ioe); return false; } finally { if (in != null) { try { in.close(); } catch (IOException ioe) { log.error("HYK: Error closing file.", ioe); } } } return true; } protected ImportHYKFlowZoneType getFlowZoneType(String name) { name = name.toUpperCase(); ImportHYKFlowZoneType fzt = flowZoneTypes.get(name); if (fzt == null) { log.info("New flow zone type: " + name); fzt = new ImportHYKFlowZoneType(name); flowZoneTypes.put(name, fzt); } return fzt; } protected void reset() { hyk = null; } public void parseHYKs(File root, final Callback callback) { FileTools.walkTree(root, new FileTools.FileVisitor() { @Override public boolean visit(File file) { if (file.isFile() && file.canRead() && file.getName().toLowerCase().endsWith(".hyk") && (callback == null || callback.hykAccept(file))) { reset(); boolean success = parse(file); log.info("parsing " + (success ? "succeeded" : "failed")); if (success && callback != null) { callback.hykParsed(HYKParser.this); } } return true; } }); } public static void main(String [] args) { HYKParser parser = new HYKParser(); for (String arg: args) { parser.parseHYKs(new File(arg), null); } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :