sascha@1215: package de.intevation.flys.importer.parsers; sascha@1215: sascha@1219: import de.intevation.flys.importer.ImportHYK; sascha@1219: import de.intevation.flys.importer.ImportHYKEntry; sascha@1219: import de.intevation.flys.importer.ImportHYKFormation; sascha@1219: import de.intevation.flys.importer.ImportHYKFlowZone; sascha@1215: import de.intevation.flys.importer.ImportHYKFlowZoneType; sascha@1215: sascha@1215: import java.io.File; sascha@1215: import java.io.IOException; sascha@1215: import java.io.FileInputStream; sascha@1215: import java.io.InputStreamReader; sascha@1215: import java.io.LineNumberReader; sascha@1215: sascha@1215: import java.util.HashMap; sascha@1215: import java.util.Map; sascha@1219: import java.util.Date; sascha@1219: import java.util.Calendar; sascha@1215: sascha@1215: import java.math.BigDecimal; sascha@1215: sascha@1215: import org.apache.log4j.Logger; sascha@1215: sascha@1216: import de.intevation.flys.utils.FileTools; sascha@1216: sascha@1215: public class HYKParser sascha@1215: { sascha@1215: private static Logger log = Logger.getLogger(HYKParser.class); sascha@1215: sascha@1216: public interface Callback { sascha@1216: boolean hykAccept(File file); sascha@1216: void hykParsed(HYKParser parser); sascha@1216: } // interface Callback sascha@1216: sascha@1215: public static enum State { sascha@1215: LINE_1, LINE_2, LINE_3, LINE_4, LINE_5, LINE_6 sascha@1215: }; sascha@1215: sascha@1215: private static final String ENCODING = "ISO-8859-1"; sascha@1215: sascha@1215: protected Map flowZoneTypes; sascha@1215: sascha@1219: protected ImportHYK hyk; sascha@1219: sascha@1215: public HYKParser() { sascha@1215: flowZoneTypes = new HashMap(); sascha@1215: } sascha@1215: sascha@1219: public ImportHYK getHYK() { sascha@1219: return hyk; sascha@1219: } sascha@1219: sascha@1219: private static Date yearToDate(Integer year) { sascha@1219: if (year == null) { sascha@1219: return null; sascha@1219: } sascha@1219: Calendar cal = Calendar.getInstance(); sascha@1219: cal.set(year, 0, 1, 12, 0, 0); sascha@1219: long ms = cal.getTimeInMillis(); sascha@1219: cal.setTimeInMillis(ms - ms%1000); sascha@1219: return cal.getTime(); sascha@1219: } sascha@1219: sascha@1215: public boolean parse(File file) { sascha@1215: sascha@1216: boolean debug = log.isDebugEnabled(); sascha@1216: sascha@1215: log.info("Parsing HYK file '" + file + "'"); sascha@1215: sascha@1215: LineNumberReader in = null; sascha@1215: sascha@1219: String description = sascha@1219: file.getParentFile().getName() + "/" + file.getName(); sascha@1219: sascha@1219: hyk = new ImportHYK(null, description); sascha@1219: sascha@1215: try { sascha@1215: in = sascha@1215: new LineNumberReader( sascha@1215: new InputStreamReader( sascha@1215: new FileInputStream(file), ENCODING)); sascha@1215: sascha@1215: String line; sascha@1215: sascha@1215: State state = State.LINE_1; sascha@1215: sascha@1215: int numFormations = 0; sascha@1215: sascha@1215: BigDecimal km = null; sascha@1215: BigDecimal top = null; sascha@1215: BigDecimal bottom = null; sascha@1215: BigDecimal distanceVL = null; sascha@1215: BigDecimal distanceHF = null; sascha@1215: BigDecimal distanceVR = null; sascha@1215: sascha@1215: Integer year = null; sascha@1215: int numZones = 0; sascha@1215: sascha@1215: ImportHYKFlowZoneType [] fzts = null; sascha@1215: BigDecimal [] coords = null; sascha@1215: int coordPos = 0; sascha@1215: sascha@1219: ImportHYKEntry entry = null; sascha@1219: ImportHYKFormation formation = null; sascha@1219: sascha@1215: while ((line = in.readLine()) != null) { sascha@1216: sascha@1216: if (line.startsWith("*") || line.startsWith("----")) { sascha@1215: continue; sascha@1215: } sascha@1216: sascha@1216: line = line.trim(); sascha@1216: sascha@1216: if (state != State.LINE_5 && line.length() == 0) { sascha@1215: continue; sascha@1215: } sascha@1216: sascha@1215: String [] parts = line.split("\\s+"); sascha@1215: sascha@1216: if (debug) { sascha@1216: log.debug("'" + line + "': " + state); sascha@1216: } sascha@1216: sascha@1215: switch (state) { sascha@1215: case LINE_1: sascha@1215: if (parts.length < 2) { sascha@1216: log.error("1: not enough elements in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1215: sascha@1215: if (parts.length == 2) { sascha@1215: // no year given sascha@1215: year = null; sascha@1215: } sascha@1215: else { sascha@1215: try { sascha@1215: year = Integer.valueOf(parts[1]); sascha@1215: } sascha@1215: catch (NumberFormatException nfe) { sascha@1215: log.error( sascha@1215: "year is not an integer in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1215: } sascha@1215: try { sascha@1215: km = new BigDecimal(parts[0]); sascha@1215: numFormations = Integer.parseInt( sascha@1215: parts[parts.length > 2 ? 2 : 1]); sascha@1215: } sascha@1215: catch (NumberFormatException nfe) { sascha@1215: log.error( sascha@1215: "parsing number of formations " + sascha@1215: "or km failed in line " + in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1219: entry = new ImportHYKEntry(hyk, km, yearToDate(year)); sascha@1219: hyk.addEntry(entry); sascha@1215: sascha@1215: state = State.LINE_2; sascha@1215: break; sascha@1215: sascha@1215: case LINE_2: sascha@1215: if (parts.length < 3) { sascha@1216: log.error("2: not enough elements in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1215: try { sascha@1215: numZones = Integer.parseInt(parts[0]); sascha@1215: bottom = new BigDecimal(parts[1]); sascha@1215: top = new BigDecimal(parts[2]); sascha@1215: } sascha@1215: catch (NumberFormatException nfe) { sascha@1215: log.error( sascha@1215: "parsing num zones, bottom or top height " + sascha@1215: "failed in line " + in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1219: formation = new ImportHYKFormation(); sascha@1224: formation.setBottom(bottom); sascha@1224: formation.setTop(top); sascha@1224: entry.addFormation(formation); sascha@1219: sascha@1215: state = State.LINE_3; sascha@1215: break; sascha@1215: sascha@1215: case LINE_3: sascha@1215: if (parts.length != numZones) { sascha@1215: log.error( sascha@1215: "number of flow zones mismatches " + sascha@1215: "in line " + in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1215: sascha@1215: fzts = new ImportHYKFlowZoneType[parts.length]; sascha@1215: for (int i = 0; i < fzts.length; ++i) { sascha@1215: fzts[i] = getFlowZoneType(parts[i]); sascha@1215: } sascha@1216: coords = new BigDecimal[numZones]; sascha@1215: state = State.LINE_4; sascha@1215: break; sascha@1215: sascha@1215: case LINE_4: sascha@1215: try { sascha@1215: int N = Math.min(parts.length, coords.length); sascha@1215: for (coordPos = 0; coordPos < N; ++coordPos) { sascha@1215: coords[coordPos] = sascha@1215: new BigDecimal(parts[coordPos]); sascha@1215: } sascha@1215: } sascha@1215: catch (NumberFormatException nfe) { sascha@1215: log.error("cannot parse number in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1215: state = State.LINE_5; sascha@1215: break; sascha@1215: sascha@1215: case LINE_5: sascha@1215: if (parts.length + coordPos < coords.length) { sascha@1216: log.error("5: not enough elements in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1215: try { sascha@1215: for (int i = 0; sascha@1215: i < parts.length && coordPos < coords.length; sascha@1215: ++i, ++coordPos sascha@1215: ) { sascha@1215: coords[coordPos] = new BigDecimal(parts[i]); sascha@1215: } sascha@1215: } sascha@1215: catch (NumberFormatException nfe) { sascha@1215: log.error("cannot parse number in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1219: for (int i = 0; i < coords.length; ++i) { sascha@1219: ImportHYKFlowZone zone = new ImportHYKFlowZone( sascha@1219: formation, sascha@1219: fzts[i], sascha@1219: coords[i], sascha@1219: coords[i == coords.length-1 ? i : i+1]); sascha@1219: formation.addFlowZone(zone); sascha@1219: } sascha@1215: state = State.LINE_6; sascha@1215: break; sascha@1215: sascha@1215: case LINE_6: sascha@1215: if (parts.length < 3) { sascha@1216: log.error("6: not enough elements in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1215: try { sascha@1215: distanceVL = new BigDecimal(parts[0]); sascha@1215: distanceHF = new BigDecimal(parts[1]); sascha@1224: distanceVR = new BigDecimal(parts[2]); sascha@1215: } sascha@1215: catch (NumberFormatException nfe) { sascha@1215: log.error("cannot parse number in line " + sascha@1215: in.getLineNumber()); sascha@1215: return false; sascha@1215: } sascha@1219: formation.setDistanceVL(distanceVL); sascha@1219: formation.setDistanceHF(distanceHF); sascha@1219: formation.setDistanceVR(distanceVR); sascha@1215: sascha@1215: // continue with next formation. sascha@1215: state = --numFormations > 0 // formations left? sascha@1215: ? State.LINE_2 sascha@1215: : State.LINE_1; sascha@1215: break; sascha@1215: } sascha@1215: } sascha@1215: } sascha@1215: catch (IOException ioe) { sascha@1215: log.error(ioe); sascha@1215: return false; sascha@1215: } sascha@1215: finally { sascha@1215: if (in != null) { sascha@1215: try { sascha@1215: in.close(); sascha@1215: } sascha@1215: catch (IOException ioe) { sascha@1215: log.error(ioe); sascha@1215: } sascha@1215: } sascha@1215: } sascha@1215: return true; sascha@1215: } sascha@1215: sascha@1215: protected ImportHYKFlowZoneType getFlowZoneType(String name) { sascha@1215: name = name.toUpperCase(); sascha@1215: ImportHYKFlowZoneType fzt = flowZoneTypes.get(name); sascha@1215: if (fzt == null) { sascha@1216: log.info("New flow zone type: " + name); sascha@1215: fzt = new ImportHYKFlowZoneType(name); sascha@1215: flowZoneTypes.put(name, fzt); sascha@1215: } sascha@1215: return fzt; sascha@1215: } sascha@1216: sascha@1216: protected void reset() { sascha@1219: hyk = null; sascha@1216: } sascha@1216: sascha@1216: public void parseHYKs(File root, final Callback callback) { sascha@1216: sascha@1216: FileTools.walkTree(root, new FileTools.FileVisitor() { sascha@1216: @Override sascha@1216: public boolean visit(File file) { sascha@1216: if (file.isFile() && file.canRead() sascha@1216: && file.getName().toLowerCase().endsWith(".hyk") sascha@1216: && (callback == null || callback.hykAccept(file))) { sascha@1216: reset(); sascha@1216: boolean success = parse(file); sascha@1216: log.info("parsing " + (success ? "succeeded" : "failed")); sascha@1216: if (success && callback != null) { sascha@1216: callback.hykParsed(HYKParser.this); sascha@1216: } sascha@1216: } sascha@1216: return true; sascha@1216: } sascha@1216: }); sascha@1216: } sascha@1216: sascha@1216: public static void main(String [] args) { sascha@1216: sascha@1216: HYKParser parser = new HYKParser(); sascha@1216: sascha@1216: for (String arg: args) { sascha@1216: parser.parseHYKs(new File(arg), null); sascha@1216: } sascha@1216: } sascha@1215: } sascha@1215: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :