/**
Copyright 2015 Tim Engler, Rareventure LLC
This file is part of Tiny Travel Tracker.
Tiny Travel Tracker 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.
Tiny Travel Tracker 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 Tiny Travel Tracker. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rareventure.gpx;
import java.util.Locale;
import java.util.TimeZone;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import com.rareventure.gps2.database.TimeZoneTimeRow;
import com.rareventure.gps2.gpx.GpxReader;
import com.rareventure.util.OutputStreamToInputStreamPipe;
import com.rareventure.util.OutputStreamToInputStreamPipe.PipeClosedException;
/**
* Pass gpx data into this thing and it will make GPX xml available for reading:
*
* Order of operation is
*
* startDoc()
* startTrack()
* startSegment()
* addPoint()
* endSegment()
* endTrack()
* endDoc()
*/
public class GpxWriter
{
private OutputStreamToInputStreamPipe buf;
public GpxWriter(OutputStreamToInputStreamPipe buf) {
this.buf = buf;
}
public void startDoc(String appName, String version)
{
write("<?xml version=\"1.0\"?>\n"+
"<gpx\n"+
" version=\"1.1\"\n"+
" creator=\""+xmlSanitize(appName+" "+version)+" - http://www.rareventure.com\"\n"+
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"+
" xmlns=\"http://www.topografix.com/GPX/1/1\"\n"+
" xmlns:rareventure=\"http://www.rareventure.com/xmlschemas/GpxExtensions/v1\"\n"+
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n");
}
private synchronized void write(String string) {
byte [] bytes = string.getBytes();
try {
buf.addBytes(bytes, 0, bytes.length);
} catch (PipeClosedException e) {
throw new IllegalStateException(e);
}
}
public void startTrack(String name)
{
write("\t<trk>\n"+
"\t\t<name>"+xmlSanitize(name)+"</name>\n");
}
public void startSegment()
{
write("\t\t<trkseg>\n");
}
private String xmlSanitize(String content) {
return content.replaceAll("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]", "_");
}
// private static final DateTimeFormatter XML_DATE_TIME_FORMAT =
// ISODateTimeFormat.dateTimeNoMillis();
private DateTimeFormatter XML_DATE_TIME_FORMAT =
ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
public void addPoint(double lat, double lon, double alt, long time, TimeZoneTimeRow tz)
{
String timeStr = XML_DATE_TIME_FORMAT.print(time);
write(String.format(Locale.ENGLISH,"\t\t\t<trkpt lat=\"%f\" lon=\"%f\" >\n"+
"\t\t\t\t<ele>%f</ele>\n"+
"\t\t\t\t<time>%s</time>\n"+
(tz == null ? "" :
"\t\t\t\t<extensions><rareventure:"+GpxReader.TAG_NEW_TIME_ZONE+" id=\""+(tz.getTimeZone() == null ? "UNKNOWN" : tz.getTimeZone().getID())+"\" />" +
"</extensions>\n")+
"\t\t\t</trkpt>\n", lat, lon, alt, timeStr
//in some cases we don't know the time zone (if we restored and the input data didn't have it)
//and in this case we want to show the users current timezone, so we set it as unknown
));
}
public void endSegment() {
write("\t\t</trkseg>\n");
}
public void endTrack() {
write("\t\t</trk>\n");
}
public void endDoc()
{
write("</gpx>\n");
buf.finishWriting();
}
}