view flys-backend/src/main/java/de/intevation/flys/importer/parsers/W80Parser.java @ 4761:ab87408bb0d3

W80Parser: Added field to store a date.
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Fri, 04 Jan 2013 11:11:52 +0100
parents 69bb2996ed19
children c6654a19b00f
line wrap: on
line source
package de.intevation.flys.importer.parsers;

import de.intevation.artifacts.common.utils.FileTools;

import de.intevation.flys.importer.XY;

import de.intevation.flys.utils.EpsilonComparator;
import de.intevation.flys.importer.parsers.tim.Coordinate;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import java.util.regex.Pattern;

import org.apache.log4j.Logger;


/**
 * To create cross-sections, generate: Map<double,list<xy>> from files
 * in w80 format.
 */
public class W80Parser extends LineParser implements CrossSectionParser
{
    /** Private logger. */
    private static Logger logger = Logger.getLogger(W80Parser.class);


    /** The current line to which add points. */
    private List<XY> currentLine;


    /** Data collected so far, last element will be currentLine. */
    protected Map<Double, List<XY>> data;


    /** Anchor to project to. */
    private class Anchor {
        private Coordinate coordinate;
        private double station;
        public Anchor(Coordinate anchor, double station) {
            this.coordinate = anchor;
            this.station = station;
        }
        public double getStation() {
            return station;
        }
        public Coordinate getCoordinate() {
            return coordinate;
        }
    }


    /** Reference point for simple projection. */
    private Anchor anchor;


    /** Measurement date of anchor as listed in w80 file. */
    private Date anchorDate;


    /** Trivial constructor. */
    public W80Parser() {
        data = new TreeMap<Double, List<XY>>(EpsilonComparator.CMP);
    }


    /** Get the description of the cross section parsed. */
    @Override
    public String getDescription() {
        return FileTools.removeExtension(getFileName());
    }


    /** Get the year of this cross sections measurement. */
    @Override
    public Integer getYear() {
        return null;
    }


    /**
     * Return the data parsed.
     * @return map of stations (km) to list of points.
     */
    @Override
    public Map<Double, List<XY>> getData() {
        return data;
    }


    public void parseW80s(File root, final Callback callback) {

        // TODO use the removeExtension/guess description and date.
        FileTools.walkTree(root, new FileTools.FileVisitor() {
            @Override
            public boolean visit(File file) {
                if (file.isFile() && file.canRead()
                && file.getName().toLowerCase().endsWith(".w80")
                && (callback == null || callback.accept(file))) {
                    reset();
                    try {
                        parse(file);
                        logger.info("parsing done");
                        if (callback != null) {
                            callback.parsed(W80Parser.this);
                        }
                    }
                    catch (IOException ioe) {
                        logger.error("IOException while parsing file");
                        return false;
                    }
                }
                return true;
            }
        });
    }


    /** Called before consuming first line of file. */
    public void reset() {
        data.clear();
        currentLine = new ArrayList<XY>();
        anchor = null;
        anchorDate = null;
    }


    /**
     * Get the Index of the last cross-section lines point.
     * @return last points index, -1 if not available.
     */
    private int lastPointIdx() {
        if (currentLine == null || currentLine.isEmpty()) {
            return -1;
        }
        XY lastPoint = this.currentLine.get(currentLine.size()-1);
        return lastPoint.getIndex();
    }


    /**
     * Add a Point (YZ,Index) to the current cross section line.
     * @param y The y coordinate of new point.
     * @param z The z coordinate of new point.
     * @param idx Ignored, the parameter of new point.
     * @return true if point could been added, false otherwise (e.g. not
     *         parsable y or z values.
     */
    private boolean addPoint(double gkr, double gkh, double height, String idx) {
        // Calculate distance between this and anchor-point.
        double dx = gkr - anchor.getCoordinate().getX();
        double dy = gkh - anchor.getCoordinate().getY();
        double d  = Math.sqrt(dx * dx + dy * dy);

        // TODO: Scale to have "x==0" e.g. at axis of river.
        // TODO: Handle "not straight lines."

        // We ignore idx, and increment instead.
        int index;
        int lastPointIdx = lastPointIdx();
        if (lastPointIdx <= 0) {
            index = 1;
        } else {
            index = lastPointIdx + 1;
        }

        currentLine.add(new XY(d, height/1000d, index));
        return true;
    }


    /**
     * Called for each line. Try to extract info from a w80 line.
     */
    @Override
    protected void handleLine(int lineNum, String line) {
        // The 'shore' field shows which side of the river the shore is measured.
        // Therefore, the points have to be added in the correct order (also
        // because later distances are calculated which cannot be
        // negative.
        String pointId = line.substring(0,20);
        String station = line.substring(9,15);
        String shore   = line.substring(15,17);
        // TODO: There is 'station' and a 'shore'-code behind.
        // 1 = left, 2 = right. none = middle
        String pointIndex = line.substring(17,21);
        // For GK, first seven digits are of interest.
        String gkRight = line.substring(20,30);
        String gkHigh  = line.substring(30,40);
        String date    = line.substring(40,46);
        /* Fields not (yet?) of interest for FLYS
        String locType = line.substring(46,47);
        */
        String height  = line.substring(47,54);
        String dateH   = line.substring(54,60);
        /* Fields not (yet?) of interest for FLYS
        String typeH   = line.substring(60,61);
        String kindH   = line.substring(61,64);
        */
        String dateDec = line.substring(64,70);
        /* Fields not (yet?) of interest for FLYS
        String note    = line.substring(70,78);
        String actual  = line.substring(78);
        */

        double stationKm = Double.parseDouble(station) / 1000d;
        double gkRightKm = Double.parseDouble(gkRight.substring(0,7));
        double gkHighKm  = Double.parseDouble(gkHigh.substring(0,7));
        double heightM   = Double.parseDouble(height);

        // New (or first) line.
        if (anchor == null || anchor.getStation() != stationKm) {
            this.anchor = new Anchor(new Coordinate(gkRightKm, gkHighKm, heightM), stationKm);
            currentLine = new ArrayList<XY>();
            data.put(stationKm, currentLine);
            currentLine.add(new XY(0d, heightM,0));
        }
        else {
            addPoint(gkRightKm, gkHighKm, heightM, pointIndex);
        }
    }


    /** Called when file is fully consumed. */
    @Override
    protected void finish() {
        logger.info("Parsed " + data.size() + " lines");
    }


    /** Parses files given as arguments. */
    public static void main(String [] args) {

        W80Parser parser = new W80Parser();

        logger.warn("Start parsing files.");
        for (String arg: args) {
            parser.parseW80s(new File(arg), null);
            logger.warn("Parsing a file.");
        }
        logger.error("Finished parsing files.");
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org