aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/export/GpxSerializer.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/export/GpxSerializer.java')
-rw-r--r--main/src/cgeo/geocaching/export/GpxSerializer.java92
1 files changed, 71 insertions, 21 deletions
diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java
index 1e39be4..ecc687f 100644
--- a/main/src/cgeo/geocaching/export/GpxSerializer.java
+++ b/main/src/cgeo/geocaching/export/GpxSerializer.java
@@ -1,9 +1,10 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.Trackable;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
@@ -11,13 +12,14 @@ import cgeo.geocaching.utils.TextUtils;
import cgeo.geocaching.utils.XmlUtils;
import cgeo.org.kxml2.io.KXmlSerializer;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.Writer;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -27,10 +29,12 @@ import java.util.Set;
public final class GpxSerializer {
- private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+ private static final FastDateFormat dateFormatZ = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
public static final String PREFIX_XSI = "http://www.w3.org/2001/XMLSchema-instance";
public static final String PREFIX_GPX = "http://www.topografix.com/GPX/1/0";
public static final String PREFIX_GROUNDSPEAK = "http://www.groundspeak.com/cache/1/0";
+ public static final String PREFIX_GSAK = "http://www.gsak.net/xmlv1/4";
+ public static final String PREFIX_CGEO = "http://www.cgeo.org/wptext/1/0";
/**
* During the export, only this number of geocaches is fully loaded into memory.
@@ -61,12 +65,15 @@ public final class GpxSerializer {
gpx.setPrefix("", PREFIX_GPX);
gpx.setPrefix("xsi", PREFIX_XSI);
gpx.setPrefix("groundspeak", PREFIX_GROUNDSPEAK);
+ gpx.setPrefix("gsak", PREFIX_GSAK);
+ gpx.setPrefix("cgeo", PREFIX_CGEO);
gpx.startTag(PREFIX_GPX, "gpx");
gpx.attribute("", "version", "1.0");
gpx.attribute("", "creator", "c:geo - http://www.cgeo.org/");
gpx.attribute(PREFIX_XSI, "schemaLocation",
PREFIX_GPX + " http://www.topografix.com/GPX/1/0/gpx.xsd " +
- PREFIX_GROUNDSPEAK + " http://www.groundspeak.com/cache/1/0/1/cache.xsd");
+ PREFIX_GROUNDSPEAK + " http://www.groundspeak.com/cache/1/0/1/cache.xsd " +
+ PREFIX_GSAK + " http://www.gsak.net/xmlv1/4/gsak.xsd");
// Split the overall set of geocodes into small chunks. That is a compromise between memory efficiency (because
// we don't load all caches fully into memory) and speed (because we don't query each cache separately).
@@ -81,7 +88,7 @@ public final class GpxSerializer {
}
private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException {
- final Set<Geocache> caches = cgData.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY);
+ final Set<Geocache> caches = DataStore.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY);
for (final Geocache cache : caches) {
gpx.startTag(PREFIX_GPX, "wpt");
gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude()));
@@ -103,7 +110,7 @@ public final class GpxSerializer {
gpx.startTag(PREFIX_GROUNDSPEAK, "cache");
gpx.attribute("", "id", cache.getCacheId());
gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False");
- gpx.attribute("", "archives", cache.isArchived() ? "True" : "False");
+ gpx.attribute("", "archived", cache.isArchived() ? "True" : "False");
XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
"name", cache.getName(),
@@ -130,6 +137,7 @@ public final class GpxSerializer {
gpx.endTag(PREFIX_GROUNDSPEAK, "long_description");
writeLogs(cache);
+ writeTravelBugs(cache);
gpx.endTag(PREFIX_GROUNDSPEAK, "cache");
gpx.endTag(PREFIX_GPX, "wpt");
@@ -147,29 +155,35 @@ public final class GpxSerializer {
final List<Waypoint> waypoints = cache.getWaypoints();
final List<Waypoint> ownWaypoints = new ArrayList<Waypoint>(waypoints.size());
final List<Waypoint> originWaypoints = new ArrayList<Waypoint>(waypoints.size());
+ int maxPrefix = 0;
for (final Waypoint wp : cache.getWaypoints()) {
+
+ // Retrieve numerical prefixes to have a basis for assigning prefixes to own waypoints
+ final String prefix = wp.getPrefix();
+ if (StringUtils.isNotBlank(prefix)) {
+ try {
+ final int numericPrefix = Integer.parseInt(prefix);
+ maxPrefix = Math.max(numericPrefix, maxPrefix);
+ } catch (final NumberFormatException ex) {
+ // ignore non numeric prefix, as it should be unique in the list of non-own waypoints already
+ }
+ }
if (wp.isUserDefined()) {
ownWaypoints.add(wp);
} else {
originWaypoints.add(wp);
}
}
- int maxPrefix = 0;
for (final Waypoint wp : originWaypoints) {
- final String prefix = wp.getPrefix();
- try {
- final int numericPrefix = Integer.parseInt(prefix);
- maxPrefix = Math.max(numericPrefix, maxPrefix);
- } catch (final NumberFormatException ex) {
- // ignore non numeric prefix, as it should be unique in the list of non-own waypoints already
- }
- writeCacheWaypoint(wp, prefix);
+ writeCacheWaypoint(wp);
}
- // Prefixes must be unique. There use numeric strings as prefixes in OWN waypoints
+ // Prefixes must be unique. There use numeric strings as prefixes in OWN waypoints where they are missing
for (final Waypoint wp : ownWaypoints) {
- maxPrefix++;
- final String prefix = StringUtils.leftPad(String.valueOf(maxPrefix), 2, '0');
- writeCacheWaypoint(wp, prefix);
+ if (StringUtils.isBlank(wp.getPrefix()) || StringUtils.equalsIgnoreCase(Waypoint.PREFIX_OWN, wp.getPrefix())) {
+ maxPrefix++;
+ wp.setPrefix(StringUtils.leftPad(String.valueOf(maxPrefix), 2, '0'));
+ }
+ writeCacheWaypoint(wp);
}
}
@@ -182,7 +196,7 @@ public final class GpxSerializer {
* @param prefix
* @throws IOException
*/
- private void writeCacheWaypoint(final Waypoint wp, final String prefix) throws IOException {
+ private void writeCacheWaypoint(final Waypoint wp) throws IOException {
final Geopoint coords = wp.getCoords();
// TODO: create some extension to GPX to include waypoint without coords
if (coords != null) {
@@ -190,11 +204,27 @@ public final class GpxSerializer {
gpx.attribute("", "lat", Double.toString(coords.getLatitude()));
gpx.attribute("", "lon", Double.toString(coords.getLongitude()));
XmlUtils.multipleTexts(gpx, PREFIX_GPX,
- "name", prefix + wp.getGeocode().substring(2),
+ "name", wp.getGpxId(),
"cmt", wp.getNote(),
"desc", wp.getName(),
"sym", wp.getWaypointType().toString(), //TODO: Correct identifier string
"type", "Waypoint|" + wp.getWaypointType().toString()); //TODO: Correct identifier string
+ // add parent reference the GSAK-way
+ gpx.startTag(PREFIX_GSAK, "wptExtension");
+ gpx.startTag(PREFIX_GSAK, "Parent");
+ gpx.text(wp.getGeocode());
+ gpx.endTag(PREFIX_GSAK, "Parent");
+ gpx.endTag(PREFIX_GSAK, "wptExtension");
+ if (wp.isVisited()) {
+ gpx.startTag(PREFIX_CGEO, "visited");
+ gpx.text("true");
+ gpx.endTag(PREFIX_CGEO, "visited");
+ }
+ if (wp.isUserDefined()) {
+ gpx.startTag(PREFIX_CGEO, "userdefined");
+ gpx.text("true");
+ gpx.endTag(PREFIX_CGEO, "userdefined");
+ }
gpx.endTag(PREFIX_GPX, "wpt");
}
}
@@ -229,6 +259,26 @@ public final class GpxSerializer {
gpx.endTag(PREFIX_GROUNDSPEAK, "logs");
}
+ private void writeTravelBugs(final Geocache cache) throws IOException {
+ List<Trackable> inventory = cache.getInventory();
+ if (CollectionUtils.isEmpty(inventory)) {
+ return;
+ }
+ gpx.startTag(PREFIX_GROUNDSPEAK, "travelbugs");
+
+ for (final Trackable trackable : inventory) {
+ gpx.startTag(PREFIX_GROUNDSPEAK, "travelbug");
+
+ // in most cases the geocode will be empty (only the guid is known). those travel bugs cannot be imported again!
+ gpx.attribute("", "ref", trackable.getGeocode());
+ XmlUtils.simpleText(gpx, PREFIX_GROUNDSPEAK, "name", trackable.getName());
+
+ gpx.endTag(PREFIX_GROUNDSPEAK, "travelbug");
+ }
+
+ gpx.endTag(PREFIX_GROUNDSPEAK, "travelbugs");
+ }
+
private void writeAttributes(final Geocache cache) throws IOException {
if (cache.getAttributes().isEmpty()) {
return;