course_generator.SaxGPXHandler.java Source code

Java tutorial

Introduction

Here is the source code for course_generator.SaxGPXHandler.java

Source

/*
 * Course Generator
 * Copyright (C) 2016 Pierre Delore
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package course_generator;

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

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import course_generator.utils.CgConst;

/**
 *
 * @author Pierre
 */
public class SaxGPXHandler extends DefaultHandler {

    private int trk_nb = 0;
    private int trkseg_nb = 0;
    private String characters = "";
    private String trk_name = "";
    private double trkpt_lat = 0.0;
    private double trkpt_lon = 0.0;
    private double trkpt_ele = 0.0;
    private String trkpt_name = "";
    private DateTime trkpt_time;
    private int level = 0;
    private final int LEVEL_GPX = 1;
    private final int LEVEL_TRK = 2;
    private final int LEVEL_TRKSEG = 3;
    private final int LEVEL_TRKPT = 4;
    private double gpx_version = 0;

    private double mLat;
    private double mLon;
    private double mEle;
    private DateTime old_time;

    private int errcode = 0;
    private Locator locator;
    private int errline = 0;

    private final int ERR_READ_NO = 0;
    private final int ERR_READ_LAT = -1;
    private final int ERR_READ_LON = -2;
    private final int ERR_READ_ELE = -3;
    private final int ERR_READ_TIME = -4;
    private final int ERR_READ_VERSION = -5;
    private final int ERR_READ_NOTEXIST = -6;
    private TrackData trkdata;
    private int mode = 0;
    private boolean first = true;
    private DateTime StartTime;
    private int Time_s;
    private double dTime_f;
    private int Cmpt = 0;

    /**
     * Read the GPX file from disc
     * @param filename Name of the gpx file to read
     * @param TData TrackData object where to store the read data
     * @param readmode Reading mode
     *  0=Load the complete file
     *  1=Insert the read data at the beginning of the current track
     *  2=Insert the read data at the end of the current track
     * @return The error code
     *   Erroce explanation:
     *   ERR_READ_NO = No problem during the reading of the file
     *   ERR_READ_LAT = Parsing error during the read of a latitude (lat) element 
     *   ERR_READ_LON = Parsing error during the read of a longitude (lon) element
     *   ERR_READ_ELE = Parsing error during the read of a elevation (ele) element
     *   ERR_READ_TIME = Parsing error during the read of a time (time) element
     *   ERR_READ_VERSION = Parsing error during the read of a version of the GPX file. Must be 1.1
     *   ERR_READ_NOTEXIST = The file doesn't exist or can't by read
     * @throws SAXException
     * @throws IOException
     * @throws ParserConfigurationException 
     */
    public int readDataFromGPX(String filename, TrackData TData, int readmode)
            throws SAXException, IOException, ParserConfigurationException {

        mode = readmode;
        trkdata = TData;
        trk_nb = 0;
        trkseg_nb = 0;
        characters = "";
        trk_name = "";
        trkpt_lat = 0.0;
        trkpt_lon = 0.0;
        trkpt_ele = 0.0;
        mLat = 0.0;
        mLon = 0.0;
        mEle = 0.0;
        Time_s = 0;
        Cmpt = 0;
        dTime_f = 0.0;

        trkpt_name = "";
        trkpt_time = new DateTime(1970, 1, 1, 0, 0, 0);
        level = 0;
        errcode = ERR_READ_NO;
        gpx_version = 0.0;
        first = true;
        StartTime = new DateTime(1970, 1, 1, 0, 0, 0);

        trkdata.ReadError = 0;

        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        File f = new File(filename);
        if (f.isFile() && f.canRead()) {
            //-- ok let's go

            //-- Clear the DataList? --
            if (mode == 0)
                trkdata.data.clear();

            //-- Parse the file
            parser.parse(f, this);
        } else
            trkdata.ReadError = ERR_READ_NOTEXIST;

        return trkdata.ReadError;
    }

    public int getErrLine() {
        return errline;
    }

    @Override
    public void setDocumentLocator(final Locator locator) {
        this.locator = locator; // Save the locator, so that it can be used later for line tracking when traversing nodes.
    }

    @Override
    public void startElement(String uri, String localname, String qName, Attributes attributs) throws SAXException {
        if (qName.equalsIgnoreCase("GPX")) {
            level++;
            // Check all the attributes
            for (int index = 0; index < attributs.getLength(); index++) {
                if (attributs.getLocalName(index).equalsIgnoreCase("VERSION")) {
                    try {
                        gpx_version = Double.parseDouble(attributs.getValue(index));
                    } catch (NumberFormatException e) {
                        gpx_version = 0.0;
                    }
                    if (gpx_version != 1.1)
                        errcode = ERR_READ_VERSION;
                } else if (attributs.getLocalName(index).equalsIgnoreCase("LON")) {
                    try {
                        trkpt_lon = Double.parseDouble(attributs.getValue(index));
                    } catch (NumberFormatException e) {
                        trkpt_lon = 0.0;
                        errcode = ERR_READ_LON;
                        errline = locator.getLineNumber();
                    }
                }
            }
        } else if (qName.equalsIgnoreCase("TRK")) {
            trk_nb++;
            level++;
        } else if (qName.equalsIgnoreCase("TRKSEG")) {
            trkseg_nb++;
            level++;
        } else if (qName.equalsIgnoreCase("TRKPT")) {
            level++;
            for (int index = 0; index < attributs.getLength(); index++) { // on parcourt la liste des attributs
                if (attributs.getLocalName(index).equalsIgnoreCase("LAT")) {
                    try {
                        trkpt_lat = Double.parseDouble(attributs.getValue(index));
                    } catch (NumberFormatException e) {
                        trkpt_lat = 0.0;
                        errcode = ERR_READ_LAT;
                        errline = locator.getLineNumber();
                    }
                } else if (attributs.getLocalName(index).equalsIgnoreCase("LON")) {
                    try {
                        trkpt_lon = Double.parseDouble(attributs.getValue(index));
                    } catch (NumberFormatException e) {
                        trkpt_lon = 0.0;
                        errcode = ERR_READ_LON;
                        errline = locator.getLineNumber();
                    }
                }
            }
        }
    }

    @Override
    public void endElement(String uri, String localname, String qName) throws SAXException {
        if (qName.equalsIgnoreCase("GPX")) {
            level--;
        } else if (qName.equalsIgnoreCase("TRK")) {
            level--;
        } else if (qName.equalsIgnoreCase("TRKSEG")) {
            level--;
        } else if ((level == LEVEL_TRK) && qName.equalsIgnoreCase("NAME")) {
            trk_name = characters;
            characters = "";
        } else if ((level == LEVEL_TRKPT) && qName.equalsIgnoreCase("NAME")) {
            trkpt_name = characters;
            characters = "";
        } else if ((level == LEVEL_TRKPT) && qName.equalsIgnoreCase("ELE")) {
            try {
                trkpt_ele = Double.parseDouble(characters);
                characters = "";
            } catch (NumberFormatException e) {
                trkpt_ele = 0.0;
                errcode = ERR_READ_ELE;
                errline = locator.getLineNumber();
                characters = "";
            }
        } else if ((level == LEVEL_TRKPT) && qName.equalsIgnoreCase("TIME")) {
            try {
                if (first) {
                    first = false;
                    trkpt_time = DateTime.parse(characters);
                    StartTime = trkpt_time;
                    old_time = StartTime;
                    Time_s = 0;
                    dTime_f = 0.0;
                    characters = "";
                } else {
                    trkpt_time = DateTime.parse(characters);
                    Time_s = (int) ((new Interval(StartTime, trkpt_time)).toDurationMillis() / 1000);
                    dTime_f = ((new Interval(old_time, trkpt_time)).toDurationMillis() / 1000.0);
                    characters = "";
                }
                trkdata.isTimeLoaded = true;
            } catch (IllegalArgumentException e) {
                trkpt_time = new DateTime(1970, 1, 1, 0, 0, 0);
                errcode = ERR_READ_TIME;
                errline = locator.getLineNumber();
                characters = "";
            }
        } else if (((level == LEVEL_TRKPT)) && qName.equalsIgnoreCase("TRKPT")) {
            level--;

            if ((mLat != trkpt_lat) || (mLon != trkpt_lon) || (!trkdata.isTimeLoaded)) {
                if ((mode == 0) || (mode == 2)) {
                    // Add data at the of the array
                    Cmpt++;
                    trkdata.data.add(new CgData(Cmpt, //double Num
                            trkpt_lat, //double Latitude
                            trkpt_lon, //double Longitude
                            trkpt_ele, //double Elevation
                            trkpt_ele, //double ElevationMemo
                            0, //int Tag
                            0.0, //double Dist
                            0.0, //double Total
                            100.0, //double Diff
                            100.0, //double Coeff
                            0.0, //double Recup
                            0.0, //double Slope
                            0.0, //double Speed
                            0.0, //double dElevation
                            Time_s, //int Time //Temps total en seconde
                            dTime_f, //double dTime_f  //temps de parcours du tronon en seconde (avec virgule)
                            0, //int TimeLimit //Barrire horaire
                            trkpt_time, //DateTime Hour //Contient la date et l'heure de passage
                            0, //int Station
                            "", //String Name
                            "", //String Comment
                            0.0, //double tmp1
                            0.0, //double tmp2
                            CgConst.DEFAULTMRBFORMAT, //String FmtLbMiniRoadbook
                            CgConst.MRBOPT_SEL | CgConst.MRBOPT_LEFT | CgConst.MRBOPT_SHOWTAGS, //int OptionMiniRoadbook
                            0, //int VPosMiniRoadbook
                            "", //String CommentMiniRoadbook
                            CgConst.DEFAULTMRBFONTSIZE //int FontSizeMiniRoadbook
                    ));
                } else {
                    trkdata.data.add(Cmpt, new CgData(Cmpt, //double Num
                            trkpt_lat, //double Latitude
                            trkpt_lon, //double Longitude
                            trkpt_ele, //double Elevation
                            trkpt_ele, //double ElevationMemo
                            0, //int Tag
                            0.0, //double Dist
                            0.0, //double Total
                            100.0, //double Diff
                            100.0, //double Coeff
                            0.0, //double Recup
                            0.0, //double Slope
                            0.0, //double Speed
                            0.0, //double dElevation
                            Time_s, //int Time
                            dTime_f, //double dTime_f
                            0, //int TimeLimit
                            trkpt_time, //DateTime Hour
                            0, //int Station
                            "", //String Name
                            "", //String Comment
                            0.0, //double tmp1
                            0.0, //double tmp2
                            CgConst.DEFAULTMRBFORMAT, //String FmtLbMiniRoadbook
                            CgConst.MRBOPT_SEL | CgConst.MRBOPT_LEFT | CgConst.MRBOPT_SHOWTAGS, //int OptionMiniRoadbook
                            0, //int VPosMiniRoadbook
                            "", //String CommentMiniRoadbook
                            CgConst.DEFAULTMRBFONTSIZE //int FontSizeMiniRoadbook
                    ));
                } //else
                Cmpt++;
            }
            mLat = trkpt_lat;
            mLon = trkpt_lon;
            mEle = trkpt_ele;
            old_time = trkpt_time;
        }
    }

    @Override
    public void characters(char[] chars, int start, int end) throws SAXException {
        characters = new String(chars, start, end);
    }

}