/**
* H2GIS is a library that brings spatial support to the H2 Database Engine
* <http://www.h2database.com>. H2GIS is developed by CNRS
* <http://www.cnrs.fr/>.
*
* This code is part of the H2GIS project. H2GIS is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation;
* version 3.0 of the License.
*
* H2GIS 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 Lesser General Public License
* for more details <http://www.gnu.org/licenses/>.
*
*
* For more information, please consult: <http://www.h2gis.org/>
* or contact directly: info_at_h2gis.org
*/
package org.h2gis.functions.io.gpx.model;
import org.h2gis.utilities.JDBCUtilities;
import org.h2gis.utilities.TableLocation;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import org.h2gis.utilities.TableUtilities;
/**
* Main class to parse the GPX file
*
* @author Erwan Bocher
*/
public abstract class AbstractGpxParserDefault extends AbstractGpxParser {
// Specific parsers
private AbstractGpxParserWpt wptParser;
private AbstractGpxParserRte rteParser;
private AbstractGpxParserTrk trkParser;
// General informations about the document to read
// The <bounds> element has attributes which specify minimum and maximum latitude and longitude.
private double minLat, maxLat, minLon, maxLon;
// Name or URL of the software that created ther GPX document.
private String creator;
// The version number of the GPX document.
private String version;
// The name of the GPX file.
private String name;
// A description of the contents of the GPX file.
private String desc;
// URLs associated with the location described in the file.
private String link;
// Text of hyperlink.
private String linkText;
// The creation date of the file.
private String time;
// Name of the person or organization who created the GPX file.
private String authorName;
// Email address of the person or organization who created the GPX file.
private String email;
// Link to Web site or other external information about person.
private String authorLink;
//Text of author's hyperlink.
private String authorLinkText;
// Keywords associated with the file.
private String keywords;
// The max size of the StringStack
public static final int STRINGSTACK_SIZE = 50;
/**
* Initialisation of all the indicators used to read the document.
*/
public void clear() {
setElementNames(new StringStack(STRINGSTACK_SIZE));
setContentBuffer(new StringBuilder());
setSpecificElement(false);
minLat = 0;
maxLat = 0;
minLon = 0;
maxLon = 0;
creator = null;
version = null;
name = null;
desc = null;
link = null;
linkText = null;
time = null;
authorName = null;
email = null;
authorLink = null;
authorLinkText = null;
keywords = null;
}
/**
* Gives copyright and license information governing use of the file.
*
* @return
*/
abstract String getCopyright();
/**
* Reads the document and parses it. The other methods are called
* automatically when corresponding markup is found.
*
* @param inputFile a File representing the gpx file to read
* @param tableName the table used to create all tables
* @param connection the connection to the database
* @return a boolean value if the parser ends successfully or not
* @throws SQLException if the creation of the tables failed
*/
public boolean read(File inputFile, String tableName, Connection connection) throws SQLException {
// Initialisation
final boolean isH2 = JDBCUtilities.isH2DataBase(connection.getMetaData());
boolean success = false;
TableLocation requestedTable = TableLocation.parse(tableName, isH2);
String table = requestedTable.getTable();
clear();
GpxPreparser gpxPreparser = new GpxPreparser();
try {
gpxPreparser.read(inputFile);
} catch (SAXException ex) {
throw new SQLException(ex);
} catch (IOException ex) {
throw new SQLException(ex);
}
StringBuilder tableNames = new StringBuilder();
// We create the tables to store all gpx data in the database
if (gpxPreparser.getTotalWpt() > 0) {
String wptTableName = TableUtilities.caseIdentifier(requestedTable, table + GPXTablesFactory.WAYPOINT, isH2);
if (JDBCUtilities.tableExists(connection, wptTableName)) {
throw new SQLException("The table " + wptTableName + " already exists.");
}
setWptPreparedStmt(GPXTablesFactory.createWayPointsTable(connection, wptTableName, isH2));
tableNames.append(wptTableName).append(",");
}
if (gpxPreparser.getTotalRte() > 0 && gpxPreparser.getTotalRtept() > 0) {
String routeTableName = TableUtilities.caseIdentifier(requestedTable, table + GPXTablesFactory.ROUTE, isH2);
if (JDBCUtilities.tableExists(connection, routeTableName)) {
throw new SQLException("The table " + routeTableName + " already exists.");
}
String routePointsTableName = TableUtilities.caseIdentifier(requestedTable, table + GPXTablesFactory.ROUTEPOINT, isH2);
if (JDBCUtilities.tableExists(connection, routePointsTableName)) {
throw new SQLException("The table " + routePointsTableName + " already exists.");
}
setRtePreparedStmt(GPXTablesFactory.createRouteTable(connection, routeTableName, isH2));
setRteptPreparedStmt(GPXTablesFactory.createRoutePointsTable(connection, routePointsTableName, isH2));
tableNames.append(routeTableName).append(",").append(routePointsTableName).append(",");
}
if (gpxPreparser.getTotalTrk() > 0 && gpxPreparser.getTotalTrkseg() > 0
&& gpxPreparser.getTotalTrkpt() > 0) {
String trackTableName = TableUtilities.caseIdentifier(requestedTable, table + GPXTablesFactory.TRACK, isH2);
if (JDBCUtilities.tableExists(connection, trackTableName)) {
throw new SQLException("The table " + trackTableName + " already exists.");
}
String trackSegmentsTableName = TableUtilities.caseIdentifier(requestedTable, table + GPXTablesFactory.TRACKSEGMENT, isH2);
if (JDBCUtilities.tableExists(connection, trackSegmentsTableName)) {
throw new SQLException("The table " + trackSegmentsTableName + " already exists.");
}
String trackPointsTableName = TableUtilities.caseIdentifier(requestedTable, table + GPXTablesFactory.TRACKPOINT, isH2);
if (JDBCUtilities.tableExists(connection, trackPointsTableName)) {
throw new SQLException("The table " + trackPointsTableName + " already exists.");
}
setTrkPreparedStmt(GPXTablesFactory.createTrackTable(connection, trackTableName, isH2));
setTrkSegmentsPreparedStmt(GPXTablesFactory.createTrackSegmentsTable(connection, trackSegmentsTableName, isH2));
setTrkPointsPreparedStmt(GPXTablesFactory.createTrackPointsTable(connection, trackPointsTableName, isH2));
tableNames.append(trackTableName).append(",").append(trackSegmentsTableName).append(",").append(trackPointsTableName).append(",");
}
// Initialisation of the contentHandler by default
try {
setReader(XMLReaderFactory.createXMLReader());
getReader().setErrorHandler(this);
getReader().setContentHandler(this);
getReader().parse(new InputSource(new FileInputStream(inputFile)));
success = true;
} catch (SAXException ex) {
throw new SQLException(ex);
} catch (IOException ex) {
throw new SQLException("Cannot parse the file " + inputFile.getAbsolutePath(), ex);
} finally {
// When the reading ends, close() method has to be called
if (getWptPreparedStmt() != null) {
getWptPreparedStmt().close();
}
if (getRteptPreparedStmt() != null) {
getRtePreparedStmt().close();
getRteptPreparedStmt().close();
}
if (getTrkPointsPreparedStmt() != null) {
getTrkPreparedStmt().close();
getTrkSegmentsPreparedStmt().close();
getTrkPointsPreparedStmt().close();
}
}
return success;
}
/**
* Fires whenever an XML start markup is encountered. It takes general
* information about the document. It change the ContentHandler to parse
* specific informations when <wpt>, <rte> or <trk> markup are found.
*
* @param uri URI of the local element
* @param localName Name of the local element (without prefix)
* @param qName qName of the local element (with prefix)
* @param attributes Attributes of the local element (contained in the
* markup)
* @throws SAXException Any SAX exception, possibly wrapping another
* exception
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (localName.compareToIgnoreCase(GPXTags.GPX) == 0) {
version = attributes.getValue(GPXTags.VERSION);
creator = attributes.getValue(GPXTags.CREATOR);
} else if (localName.compareToIgnoreCase(GPXTags.BOUNDS) == 0) {
minLat = Double.parseDouble(attributes.getValue(GPXTags.MINLAT));
maxLat = Double.parseDouble(attributes.getValue(GPXTags.MAXLAT));
minLon = Double.parseDouble(attributes.getValue(GPXTags.MINLON));
maxLon = Double.parseDouble(attributes.getValue(GPXTags.MAXLON));
}
// Clear content buffer
getContentBuffer()
.delete(0, getContentBuffer().length());
// Store name of current element in stack
getElementNames()
.push(qName);
}
/**
* Fires whenever an XML end markup is encountered. It catches attributes of
* the different elements and saves them in corresponding values[].
*
* @param uri URI of the local element
* @param localName Name of the local element (without prefix)
* @param qName qName of the local element (with prefix)
*/
@Override
public void endElement(String uri, String localName, String qName) {
// currentElement represents the last string encountered in the document
setCurrentElement(getElementNames().pop());
if (getCurrentElement().equalsIgnoreCase(GPXTags.WPT)) {
setSpecificElement(false);
} else if (getCurrentElement().equalsIgnoreCase(GPXTags.RTE)) {
setSpecificElement(false);
} else if (getCurrentElement().equalsIgnoreCase(GPXTags.TRK)) {
setSpecificElement(false);
} else if ((getCurrentElement().equalsIgnoreCase(GPXTags.TIME)) && (!isSpecificElement())) {
time = getContentBuffer().toString();
} else if ((getCurrentElement().equalsIgnoreCase(GPXTags.DESC)) && (!isSpecificElement())) {
desc = getContentBuffer().toString();
} else if (localName.equalsIgnoreCase(GPXTags.KEYWORDS)) {
keywords = getContentBuffer().toString();
}
}
/**
* Gives the date when this file is created.
*
* @return
*/
public String getTime() {
return time;
}
/**
* Gives the version number of the GPX document.
*
* @return
*/
public String getVersion() {
return version;
}
/**
* Gives the name or URL of the software that created the GPX document.
*
* @return
*/
public String getCreator() {
return creator;
}
/**
* Gives the minimum longitude given by <bounds> element.
*
* @return
*/
public double getMinLon() {
return minLon;
}
/**
* Gives the maximum longitude given by <bounds> element.
*
* @return
*/
public double getMaxLon() {
return maxLon;
}
/**
* Gives the minimum latitude given by <bounds> element.
*
* @return
*/
public double getMinLat() {
return minLat;
}
/**
* Gives the maximum latitude given by <bounds> element.
*
* @return
*/
public double getMaxLat() {
return maxLat;
}
/**
* Gives a description of the contents of the GPX file.
*
* @return
*/
public String getDesc() {
return desc;
}
/**
* Gives keywords associated with the file. Search engines or databases can
* use this information to classify the data.
*
* @return
*/
public String getKeywords() {
return keywords;
}
/**
* Gives URLs associated with the location described in the file.
*
* @return
*/
public String getFullLink() {
return "Link : " + link + "\nText of hyperlink : " + linkText;
}
/**
* Gives the name of person or organization who created the GPX file. Also
* gives an email address if exist. Also gives a link to Web site or other
* external information about person if exist.
*
* @return
*/
public String getFullAuthor() {
return "Author : " + authorName + "\nEmail : " + email + "\nLink : " + authorLink + "\nText : " + authorLinkText;
}
/**
* Set the link related to the author of the ducument.
*
* @param authorLink
*/
public void setAuthorLink(String authorLink) {
this.authorLink = authorLink;
}
/**
* Set the description of the link related to the author.
*
* @param authorLinkText
*/
public void setAuthorLinkText(String authorLinkText) {
this.authorLinkText = authorLinkText;
}
/**
* Set the name of the author of the document.
*
* @param authorName
*/
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
/**
* Set the email of the author of the document.
*
* @param email
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Set the link related to the document.
*
* @param link
*/
public void setLink(String link) {
this.link = link;
}
/**
* Set the description of hte document link.
*
* @param linkText
*/
public void setLinkText(String linkText) {
this.linkText = linkText;
}
/**
* Gives the name of the document.
*
* @return
*/
public String getName() {
return name;
}
/**
* Set the name of the document.
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gives the parser used to parse waypoint.
*
* @return
*/
public AbstractGpxParserWpt getWptParser() {
return wptParser;
}
/**
* Set the parser used to parse waypoint.
*
* @param wptParser
*/
public void setWptParser(AbstractGpxParserWpt wptParser) {
this.wptParser = wptParser;
}
/**
* Set the parser used to parse routes.
*
* @param rteParser
*/
public void setRteParser(AbstractGpxParserRte rteParser) {
this.rteParser = rteParser;
}
/**
* Gives the parser used to parse routes.
*
* @return
*/
public AbstractGpxParserRte getRteParser() {
return rteParser;
}
/**
* Set the parser used to parse the track
*
* @param trkParser
*/
public void setTrkParser(AbstractGpxParserTrk trkParser) {
this.trkParser = trkParser;
}
/**
* Givers the parser used to parse the track
*
* @return
*/
public AbstractGpxParserTrk getTrkParser() {
return trkParser;
}
}