diff flys-backend/src/main/java/org/dive4elements/river/importer/parsers/HYKParser.java @ 5828:dfb26b03b179

Moved directories to org.dive4elements.river
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 11:53:11 +0200
parents flys-backend/src/main/java/de/intevation/flys/importer/parsers/HYKParser.java@36edf9a71cbd
children 18619c1e7c2a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-backend/src/main/java/org/dive4elements/river/importer/parsers/HYKParser.java	Thu Apr 25 11:53:11 2013 +0200
@@ -0,0 +1,344 @@
+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 :

http://dive4elements.wald.intevation.org