org.footware.server.gpx.GPXImport.java Source code

Java tutorial

Introduction

Here is the source code for org.footware.server.gpx.GPXImport.java

Source

/*
 * Copyright 2010 Andreas Brauchli, Ren Buffat, Florian Widmer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.footware.server.gpx;

import java.io.File;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

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

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.footware.server.db.Track;
import org.footware.server.gpx.model.GPXTrack;
import org.footware.server.gpx.model.GPXTrackPoint;
import org.footware.server.gpx.model.GPXTrackSegment;
import org.footware.shared.dto.TrackDTO;
import org.footware.shared.dto.TrackVisualizationDTO;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

public class GPXImport implements TrackImporter {

    private static String GPX_NAMESPACE_URI_1_1 = "http://www.topografix.com/GPX/1/1";
    private static String GPX_NAMESPACE_URI_1_0 = "http://www.topografix.com/GPX/1/0";
    private static String GPX_NS = "tpx";
    private static String LATITUDE = "lat";
    private static String LONGITUDE = "lon";
    private static String ELEVATION = "ele";
    private static String TIME = "time";
    private Logger logger;

    boolean trackImported = false;

    private String GPX_NAMESPACE_URI = GPX_NAMESPACE_URI_1_1;

    private List<TrackVisualizationDTO> speedVisualizations = new LinkedList<TrackVisualizationDTO>();
    private List<TrackVisualizationDTO> elevationVisualizations = new LinkedList<TrackVisualizationDTO>();
    private List<Track> tracks = new LinkedList<Track>();

    public GPXImport() {
        logger = LoggerFactory.getLogger(GPXImport.class);
    }

    public void importTrack(File file) {
        logger.info("Import file: " + file.getAbsolutePath());
        List<GPXTrack> gpxTracks = parseXML(file);

        TrackVisualizationFactoryImpl speedFactory = new TrackVisualizationFactoryImpl(
                new TrackVisualizationSpeedStrategy());
        TrackVisualizationFactoryImpl elevationFactory = new TrackVisualizationFactoryImpl(
                new TrackVisualizationElevationStrategy());

        //TODO
        for (GPXTrack track : gpxTracks) {
            Track newTrack = TrackFactory.create(track);
            tracks.add(newTrack);
            speedVisualizations.add(speedFactory.create(newTrack));
            elevationVisualizations.add(elevationFactory.create(newTrack));
        }
        trackImported = true;
    }

    private List<GPXTrack> parseXML(File file) {
        LinkedList<GPXTrack> tracks = new LinkedList<GPXTrack>();
        try {
            long startTime = System.currentTimeMillis();
            logger.info("Start parsing @" + startTime);

            // Determine GPX Version
            SAXReader xmlReader = new SAXReader();
            Document document = xmlReader.read(file);
            String version = document.getRootElement().attributeValue("version");

            File xsd = null;

            if (version.equals("1.1")) {
                logger.info("Detected gpx version " + version + "  +" + (System.currentTimeMillis() - startTime));
                xsd = new File("gpx_1_1.xsd");
                GPX_NAMESPACE_URI = GPX_NAMESPACE_URI_1_1;
            } else if (version.equals("1.0")) {
                logger.info("Detected gpx version '" + version + "'  +" + (System.currentTimeMillis() - startTime));
                xsd = new File("gpx_1_0.xsd");
                GPX_NAMESPACE_URI = GPX_NAMESPACE_URI_1_0;
            } else {
                logger.info("No supported version detected: " + version + "  +"
                        + (System.currentTimeMillis() - startTime));
                // As default we try version 1.1
                xsd = new File("gpx_1_1.xsd");
                GPX_NAMESPACE_URI = GPX_NAMESPACE_URI_1_1;
            }

            // Parse GPX
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");

            factory.setSchema(schemaFactory.newSchema(xsd));

            SAXParser parser = factory.newSAXParser();
            SAXReader reader = new SAXReader(parser.getXMLReader());
            reader.setValidation(true);
            reader.setErrorHandler(new SimpleErrorHandler());

            document = reader.read(file);
            logger.info("End parsing +" + (System.currentTimeMillis() - startTime));

            // Define namespaces
            HashMap<String, String> namespacesMap = new HashMap<String, String>();
            namespacesMap.put(GPX_NS, GPX_NAMESPACE_URI);

            // Find tracks
            logger.info("Search tracks +" + (System.currentTimeMillis() - startTime));
            XPath xpathTrk = DocumentHelper.createXPath("//" + GPX_NS + ":trk");
            xpathTrk.setNamespaceURIs(namespacesMap);

            List<Element> xmlTracks = xpathTrk.selectNodes(document);
            logger.info("Found " + xmlTracks.size() + " tracks +" + (System.currentTimeMillis() - startTime));

            GPXTrack track;

            // for (Element xmlTrack : xmlTracks) {
            // Iterate about all tracks of the gpx file
            for (int currentTrackNummer = 1; currentTrackNummer <= xmlTracks.size(); currentTrackNummer++) {
                logger.info("Start track " + currentTrackNummer + " +" + (System.currentTimeMillis() - startTime));

                track = new GPXTrack();

                // Find track segments
                XPath xpathTrkseg = DocumentHelper
                        .createXPath("//" + GPX_NS + ":trk[" + currentTrackNummer + "]/" + GPX_NS + ":trkseg");
                xpathTrkseg.setNamespaceURIs(namespacesMap);

                List<Element> xmlTrackSegs = xpathTrkseg.selectNodes(document);
                logger.info("Found " + xmlTrackSegs.size() + " segments for track " + currentTrackNummer + " +"
                        + (System.currentTimeMillis() - startTime));

                // List<Element> xmlTrackSegs =
                // xmlTrack.selectNodes("//trkseg");

                GPXTrackSegment trackSegment;

                // for (Element xmlTrackSeq : xmlTrackSegs) {
                // Iterate above all segments of a track
                for (int currentTrackSegmentNummer = 1; currentTrackSegmentNummer <= xmlTrackSegs
                        .size(); currentTrackSegmentNummer++) {
                    trackSegment = new GPXTrackSegment();

                    // Find track points
                    XPath xpathTrkPt = DocumentHelper.createXPath("//" + GPX_NS + ":trk[" + currentTrackNummer
                            + "]/" + GPX_NS + ":trkseg[" + currentTrackSegmentNummer + "]/" + GPX_NS + ":trkpt");
                    xpathTrkPt.setNamespaceURIs(namespacesMap);
                    List<Element> xmlTrackPts = xpathTrkPt.selectNodes(document);

                    logger.info("Found " + xmlTrackPts.size() + " points for segment " + currentTrackSegmentNummer
                            + " for track " + currentTrackNummer + " +" + (System.currentTimeMillis() - startTime));

                    GPXTrackPoint trackPoint;
                    BigDecimal latitude;
                    BigDecimal longitude;
                    BigDecimal elevation;
                    DateTime time;

                    // Iterate above all points of a segment of a track
                    for (Element xmlTrackPt : xmlTrackPts) {

                        latitude = new BigDecimal(xmlTrackPt.attributeValue(LATITUDE));
                        longitude = new BigDecimal(xmlTrackPt.attributeValue(LONGITUDE));
                        elevation = new BigDecimal(xmlTrackPt.element(ELEVATION).getText());
                        time = ISODateTimeFormat.dateTimeNoMillis()
                                .parseDateTime(xmlTrackPt.element(TIME).getText());

                        trackPoint = new GPXTrackPoint(latitude, longitude, elevation, time);
                        trackSegment.addPoint(trackPoint);
                    }
                    track.addTrackSegment(trackSegment);
                }
                tracks.add(track);

            }
            logger.info("Done parsing +" + (System.currentTimeMillis() - startTime));

        } catch (ParserConfigurationException e) {
            logger.error("ParserConfigurationException", e);
            e.printStackTrace();
        } catch (SAXException e) {
            logger.error("SAXException", e);
            e.printStackTrace();
        } catch (DocumentException e) {
            logger.error("DocumentException", e);
            e.printStackTrace();
        }

        return tracks;
    }

    @Override
    public List<TrackVisualizationDTO> getElevationVisualizations() {
        if (!trackImported) {
            try {
                throw new Exception("importTrack must be called first!");
            } catch (Exception e) {
                logger.error("importTrack must be called first!", e);
            }
        }
        return elevationVisualizations;
    }

    @Override
    public List<TrackVisualizationDTO> getSpeedVisualizations() {
        if (!trackImported) {
            try {
                throw new Exception("importTrack must be called first!");
            } catch (Exception e) {
                logger.error("importTrack must be called first!", e);
            }
        }
        return speedVisualizations;
    }

    @Override
    public List<Track> getTracks() {
        if (!trackImported) {
            try {
                throw new Exception("importTrack must be called first!");
            } catch (Exception e) {
                logger.error("importTrack must be called first!", e);
            }
        }
        return tracks;
    }
}