aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main/project/xsd/cgeo.xsd16
-rw-r--r--main/src/cgeo/geocaching/DataStore.java14
-rw-r--r--main/src/cgeo/geocaching/Geocache.java8
-rw-r--r--main/src/cgeo/geocaching/Waypoint.java21
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java12
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java19
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java18
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java1
-rw-r--r--main/src/cgeo/geocaching/export/GpxSerializer.java59
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java57
-rw-r--r--tests/res/raw/ocddd2.gpx133
-rw-r--r--tests/src/cgeo/geocaching/export/GpxSerializerTest.java10
-rw-r--r--tests/src/cgeo/geocaching/files/GPXImporterTest.java23
13 files changed, 358 insertions, 33 deletions
diff --git a/main/project/xsd/cgeo.xsd b/main/project/xsd/cgeo.xsd
new file mode 100644
index 0000000..35a5983
--- /dev/null
+++ b/main/project/xsd/cgeo.xsd
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.cgeo.org/wptext/1/0" elementFormDefault="qualified">
+<xsd:annotation><xsd:documentation>
+This schema defines additional properties c:geo needs to store in a waypoint in a gpx file.
+The root element is intended to be used in the appropriate extension point in the gpx waypoint type
+(see http://www.topografix.com/GPX/1/0/gpx.xsd or http://www.topografix.com/GPX/1/1/gpx.xsd for details)
+Currently two items are defined: visited and userdefined.
+</xsd:documentation></xsd:annotation>
+<xsd:element name="cgeo">
+<xsd:complexType>
+<xsd:sequence>
+<xsd:element name="visited" type="xsd:boolean" />
+<xsd:element name="userdefined" type="xsd:boolean" />
+</xsd:sequence>
+</xsd:complexType></xsd:element>
+</xsd:schema> \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java
index a231e8b..9075d45 100644
--- a/main/src/cgeo/geocaching/DataStore.java
+++ b/main/src/cgeo/geocaching/DataStore.java
@@ -1107,7 +1107,7 @@ public class DataStore {
try {
saveAttributesWithoutTransaction(cache);
- saveOriginalWaypointsWithoutTransaction(cache);
+ saveWaypointsWithoutTransaction(cache);
saveSpoilersWithoutTransaction(cache);
saveLogsWithoutTransaction(cache.getGeocode(), cache.getLogs());
saveLogCountsWithoutTransaction(cache);
@@ -1175,7 +1175,7 @@ public class DataStore {
database.beginTransaction();
try {
- saveOriginalWaypointsWithoutTransaction(cache);
+ saveWaypointsWithoutTransaction(cache);
database.setTransactionSuccessful();
return true;
} catch (Exception e) {
@@ -1186,7 +1186,7 @@ public class DataStore {
return false;
}
- private static void saveOriginalWaypointsWithoutTransaction(final Geocache cache) {
+ private static void saveWaypointsWithoutTransaction(final Geocache cache) {
String geocode = cache.getGeocode();
List<Waypoint> waypoints = cache.getWaypoints();
@@ -1195,10 +1195,6 @@ public class DataStore {
ContentValues values = new ContentValues();
long timeStamp = System.currentTimeMillis();
for (Waypoint oneWaypoint : waypoints) {
- if (oneWaypoint.isUserDefined()) {
- currentWaypointIds.add(Integer.toString(oneWaypoint.getId()));
- continue;
- }
values.clear();
values.put("geocode", geocode);
@@ -1227,7 +1223,7 @@ public class DataStore {
/**
* remove all waypoints of the given cache, where the id is not in the given list
- *
+ *
* @param cache
* @param remainingWaypointIds
* ids of waypoints which shall not be deleted
@@ -1239,7 +1235,7 @@ public class DataStore {
/**
* Save coordinates into a ContentValues
- *
+ *
* @param values
* a ContentValues to save coordinates in
* @param oneWaypoint
diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java
index 8cfedb3..731f214 100644
--- a/main/src/cgeo/geocaching/Geocache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -1771,4 +1771,12 @@ public class Geocache implements ICache, IWaypoint {
public void setLogPasswordRequired(boolean required) {
logPasswordRequired = required;
}
+
+ public String getWaypointGpxId(String prefix) {
+ return getConnector().getWaypointGpxId(prefix, geocode);
+ }
+
+ public String getWaypointPrefix(String name) {
+ return getConnector().getWaypointPrefix(name);
+ }
}
diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java
index facd914..dda83d9 100644
--- a/main/src/cgeo/geocaching/Waypoint.java
+++ b/main/src/cgeo/geocaching/Waypoint.java
@@ -1,5 +1,6 @@
package cgeo.geocaching;
+import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
@@ -265,4 +266,24 @@ public class Waypoint implements IWaypoint {
return left.order() - right.order();
}
};
+
+ /**
+ * Delegates the creation of the waypoint-id for gpx-export to the waypoint
+ *
+ * @param prefix
+ * @return
+ */
+ public String getGpxId() {
+
+ String gpxId = prefix;
+
+ if (StringUtils.isNotBlank(geocode)) {
+ Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ if (cache != null) {
+ gpxId = cache.getWaypointGpxId(prefix);
+ }
+ }
+
+ return gpxId;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 3ec0580..b10366e 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -188,4 +188,16 @@ public abstract class AbstractConnector implements IConnector {
}
return logTypes;
}
+
+ @Override
+ public String getWaypointGpxId(String prefix, String geocode) {
+ // Default: just return the prefix
+ return prefix;
+ }
+
+ @Override
+ public String getWaypointPrefix(String name) {
+ // Default: just return the name
+ return name;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java
index 2262e47..a96ee10 100644
--- a/main/src/cgeo/geocaching/connector/IConnector.java
+++ b/main/src/cgeo/geocaching/connector/IConnector.java
@@ -215,9 +215,26 @@ public interface IConnector {
/**
* Get the list of <b>potentially</b> possible log types for a cache. Those may still be filter further during the
* actual logging activity.
- *
+ *
* @param geocache
* @return
*/
public List<LogType> getPossibleLogTypes(Geocache geocache);
+
+ /**
+ * Get the gpx id for a waypoint when exporting. For some connectors there is an inherent name logic,
+ * for others its just the 'prefix'
+ *
+ * @param prefix
+ * @return
+ */
+ public String getWaypointGpxId(String prefix, String geocode);
+
+ /**
+ * Get the 'prefix' (key) for a waypoint from the 'name' in the gpx file
+ *
+ * @param name
+ * @return
+ */
+ public String getWaypointPrefix(String name);
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index d5f7bf4..6a61405 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -335,4 +335,22 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean isLoggedIn() {
return Login.isActualLoginStatus();
}
+
+ @Override
+ public String getWaypointGpxId(String prefix, String geocode) {
+ String gpxId = prefix;
+ if (StringUtils.isNotBlank(geocode) && geocode.length() > 2) {
+ gpxId += geocode.substring(2);
+ }
+ return gpxId;
+ }
+
+ @Override
+ public String getWaypointPrefix(String name) {
+ String prefix = name;
+ if (StringUtils.isNotBlank(prefix) && prefix.length() >= 2) {
+ prefix = name.substring(0, 2);
+ }
+ return prefix;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 686e314..24e30e7 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -445,6 +445,7 @@ final class OkapiClient {
if (result == null) {
result = new ArrayList<Waypoint>();
}
+ wpt.setPrefix(wpt.getName());
result.add(wpt);
} catch (final JSONException e) {
Log.e("OkapiClient.parseWaypoints", e);
diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java
index 3ff8879..7d6067e 100644
--- a/main/src/cgeo/geocaching/export/GpxSerializer.java
+++ b/main/src/cgeo/geocaching/export/GpxSerializer.java
@@ -33,6 +33,8 @@ public final class GpxSerializer {
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.
@@ -63,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).
@@ -150,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("OWN", wp.getPrefix())) {
+ maxPrefix++;
+ wp.setPrefix(StringUtils.leftPad(String.valueOf(maxPrefix), 2, '0'));
+ }
+ writeCacheWaypoint(wp);
}
}
@@ -185,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) {
@@ -193,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");
}
}
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index e01c191..3e96291 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -70,9 +70,14 @@ public abstract class GPXParser extends FileParser {
* supported GSAK extension of the GPX format
*/
private static final String[] GSAK_NS = new String[] {
+ "http://www.gsak.net/xmlv1/4",
"http://www.gsak.net/xmlv1/5",
"http://www.gsak.net/xmlv1/6"
};
+ /**
+ * c:geo extensions of the gpx format
+ */
+ private static final String CGEO_NS = "http://www.cgeo.org/wptext/1/0";
private static final Pattern PATTERN_MILLISECONDS = Pattern.compile("\\.\\d{3,7}");
@@ -90,6 +95,9 @@ public abstract class GPXParser extends FileParser {
private String cmt = null;
private String desc = null;
protected final String[] userData = new String[5]; // take 5 cells, that makes indexing 1..4 easier
+ private String parentCacheCode = null;
+ private boolean wptVisited = false;
+ private boolean wptUserDefined = false;
/**
* Parser result. Maps geocode to cache.
@@ -328,20 +336,25 @@ public abstract class GPXParser extends FileParser {
private void addWaypointToCache() {
fixCache(cache);
- if (cache.getName().length() > 2) {
- final String cacheGeocodeForWaypoint = "GC" + cache.getName().substring(2).toUpperCase(Locale.US);
+ if (cache.getName().length() > 2 || StringUtils.isNotBlank(parentCacheCode)) {
+ if (StringUtils.isBlank(parentCacheCode)) {
+ parentCacheCode = "GC" + cache.getName().substring(2).toUpperCase(Locale.US);
+ }
// lookup cache for waypoint in already parsed caches
- final Geocache cacheForWaypoint = DataStore.loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cacheForWaypoint = DataStore.loadCache(parentCacheCode, LoadFlags.LOAD_CACHE_OR_DB);
if (cacheForWaypoint != null) {
final Waypoint waypoint = new Waypoint(cache.getShortDescription(), convertWaypointSym2Type(sym), false);
+ if (wptUserDefined) {
+ waypoint.setUserDefined();
+ }
waypoint.setId(-1);
- waypoint.setGeocode(cacheGeocodeForWaypoint);
- waypoint.setPrefix(cache.getName().substring(0, 2));
+ waypoint.setGeocode(parentCacheCode);
+ waypoint.setPrefix(cacheForWaypoint.getWaypointPrefix(cache.getName()));
waypoint.setLookup("---");
// there is no lookup code in gpx file
waypoint.setCoords(cache.getCoords());
waypoint.setNote(cache.getDescription());
-
+ waypoint.setVisited(wptVisited);
final ArrayList<Waypoint> mergedWayPoints = new ArrayList<Waypoint>();
mergedWayPoints.addAll(cacheForWaypoint.getWaypoints());
@@ -480,8 +493,37 @@ public abstract class GPXParser extends FileParser {
for (int i = 2; i <= 4; i++) {
gsak.getChild(gsakNamespace, "User" + i).setEndTextElementListener(new UserDataListener(i));
}
+
+ gsak.getChild(gsakNamespace, "Parent").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ parentCacheCode = body;
+ }
+ });
}
+ // c:geo extensions
+ final Element cgeoVisited = cacheParent.getChild(CGEO_NS, "visited");
+
+ cgeoVisited.setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String visited) {
+ wptVisited = Boolean.valueOf(visited.trim());
+ }
+ });
+
+ final Element cgeoUserDefined = cacheParent.getChild(CGEO_NS, "userdefined");
+
+ cgeoUserDefined.setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String userDefined) {
+ wptUserDefined = Boolean.valueOf(userDefined.trim());
+ }
+ });
+
// 3 different versions of the GC schema
for (final String nsGC : GROUNDSPEAK_NAMESPACE) {
// waypoints.cache
@@ -869,6 +911,9 @@ public abstract class GPXParser extends FileParser {
name = null;
desc = null;
cmt = null;
+ parentCacheCode = null;
+ wptVisited = false;
+ wptUserDefined = false;
cache = new Geocache(this);
diff --git a/tests/res/raw/ocddd2.gpx b/tests/res/raw/ocddd2.gpx
new file mode 100644
index 0000000..9ce18b1
--- /dev/null
+++ b/tests/res/raw/ocddd2.gpx
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cgeo="http://www.cgeo.org/wptext/1/0" version="1.0" creator="Opencaching.de - http://www.opencaching.de" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd" xmlns="http://www.topografix.com/GPX/1/0">
+ <name>Cache listing generated from Opencaching.de</name>
+ <desc>This is a waypoint file generated from Opencaching.de</desc>
+ <author>Opencaching.de</author>
+ <email>contact@opencaching.de</email>
+ <url>http://www.opencaching.de</url>
+ <urlname>Opencaching.de - Geocaching in Deutschland, Oesterreich und der Schweiz</urlname>
+ <time>2013-11-10T14:52:05Z</time>
+ <keywords>cache, geocache, opencaching, waypoint</keywords>
+ <wpt lat="48.88417" lon="9.17660">
+ <time>2012-03-23T00:00:00Z</time>
+ <name>OCDDD2</name>
+ <desc>Kaiserstein und Grabhügel Ludwigsburg</desc>
+ <src>www.opencaching.de</src>
+ <url>http://www.opencaching.de/viewcache.php?cacheid=159890</url>
+ <urlname>Kaiserstein und Grabhügel Ludwigsburg</urlname>
+ <sym>Geocache</sym>
+ <type>Geocache|Virtual Cache</type>
+ <groundspeak:cache id="159890" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>Kaiserstein und Grabhügel Ludwigsburg</groundspeak:name>
+ <groundspeak:placed_by>Emmett</groundspeak:placed_by>
+ <groundspeak:owner id="114440">Emmett</groundspeak:owner>
+ <groundspeak:type>Virtual Cache</groundspeak:type>
+ <groundspeak:container>Virtual</groundspeak:container>
+ <groundspeak:attributes>
+ <groundspeak:attribute id="106" inc="1">Only loggable at Opencaching</groundspeak:attribute>
+ <groundspeak:attribute id="25" inc="1">Parking available</groundspeak:attribute>
+ <groundspeak:attribute id="13" inc="1">Available at all times</groundspeak:attribute>
+ <groundspeak:attribute id="62" inc="0">Seasonal access</groundspeak:attribute>
+ </groundspeak:attributes>
+ <groundspeak:difficulty>1.5</groundspeak:difficulty>
+ <groundspeak:terrain>1.5</groundspeak:terrain>
+ <groundspeak:country>Germany</groundspeak:country>
+ <groundspeak:state>Baden-Württemberg</groundspeak:state>
+ <groundspeak:short_description html="True">Virtueller Cache am Römerhügelweg Ludwigsburg</groundspeak:short_description>
+ <groundspeak:long_description html="True">Im Süden der Stadt Ludwigsburg am heutigen Römerhügelweg liegen zwei Stellen, an denen zum Gedenken an zu ihrer Zeit gesellschaftlich bedeutende Menschen gebaut wurde.&lt;br /&gt;
+&lt;br /&gt;
+Zum einen der inzwischen abgetragene Grabhügel aus der späten Hallstattzeit, 6. Jahrhundert v. Chr. Informationen über ihn findet Ihr vor Ort.&lt;br /&gt;
+&lt;br /&gt;
+Zum anderen gegenüber ein Kaiserstein. Zwischen 1867 und 1918 wurden im deutschsprachigen Raum mehr als 1000 Kaiser-Wilhelm-Denkmäler errichtet.&lt;br /&gt;
+&lt;br /&gt;
+Um den Code zum Loggen zu erhalten, sucht vor Ort die Antworten auf folgende Fragen:&lt;br /&gt;
+1. Am Kaiserstein (N 48 53.050 E 009 10.596) ist eine metallene Tafel angebracht. Wieviele Buchstaben hat die letzte Zeile ihrer Inschrift?&lt;br /&gt;
+2. Südlich des Wasserturms ist eine Tafel mit 2 numerierten Abbildungen zu sehen (N 48 53.070 E 009 10.594). Was ist das 2. Wort der 8. Zeile des (unteren) Abschnittes links der Abbildung 2?&lt;br /&gt;
+3. An der Rückseite des Kaisersteins steht eine Sitzgelegenheit. Wieviele Beine hat sie?&lt;br /&gt;
+Der Code besteht aus den 3 Antworten, direkt hintereinandergeschrieben (Beispiel für das Format: 48Cache9 ).&lt;br /&gt;
+&lt;br /&gt;
+Parkmöglichkeiten: N 48 53.125 E 009 10.224 oder N 48 53.023 E 009 10.870 abends und am Wochenende, siehe Beschilderung&lt;br /&gt;
+&lt;br /&gt;
+Viel Spaß!&lt;p&gt;&lt;em&gt;© &lt;a href='http://www.opencaching.de/viewprofile.php?userid=114440' target='_blank'&gt;Emmett&lt;/a&gt;, &lt;a href='http://www.opencaching.de/viewcache.php?cacheid=159890' target='_blank'&gt;Opencaching.de&lt;/a&gt;, &lt;a href='http://creativecommons.org/licenses/by-nc-nd/3.0/de/' target='_blank'&gt;CC BY-NC-ND&lt;/a&gt;, Stand: 10.11.2013; alle Logeinträge © jeweiliger Autor&lt;/em&gt;&lt;/p&gt;
+&lt;br /&gt;</groundspeak:long_description>
+ <groundspeak:logs>
+ <groundspeak:log id="871676">
+ <groundspeak:date>2013-03-05T00:00:00Z</groundspeak:date>
+ <groundspeak:type>Found it</groundspeak:type>
+ <groundspeak:finder id="253417">andierdbeere</groundspeak:finder>
+ <groundspeak:text encoded="False">&lt;p&gt;Dankeschön für die Suche!&lt;/p&gt;
+&lt;p&gt;Habe den Cache am ersten schönen Frühlingstag gemacht!&lt;/p&gt;
+&lt;p&gt;Andi&lt;/p&gt;</groundspeak:text>
+ </groundspeak:log>
+ <groundspeak:log id="855833">
+ <groundspeak:date>2012-10-20T00:00:00Z</groundspeak:date>
+ <groundspeak:type>Found it</groundspeak:type>
+ <groundspeak:finder id="248085">Lazumako</groundspeak:finder>
+ <groundspeak:text encoded="False">Geschafft!!! &lt;br /&gt;
+:-)</groundspeak:text>
+ </groundspeak:log>
+ <groundspeak:log id="821979">
+ <groundspeak:date>2012-05-12T00:00:00Z</groundspeak:date>
+ <groundspeak:type>Found it</groundspeak:type>
+ <groundspeak:finder id="233619">R2-D2</groundspeak:finder>
+ <groundspeak:text encoded="False">&lt;p&gt;War mein erster Cache überhaupt.&lt;/p&gt;
+&lt;p&gt;Hat echt Spaß gemacht. Gut für Grundschulkinder geeignet.&lt;/p&gt;
+&lt;p&gt;12.05.2012&lt;/p&gt;
+&lt;p&gt;R2-D2&lt;/p&gt;</groundspeak:text>
+ </groundspeak:log>
+ </groundspeak:logs>
+ <groundspeak:travelbugs>
+ </groundspeak:travelbugs>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.88542" lon="9.17040">
+ <time>2012-03-23T00:00:00Z</time>
+ <name>OCDDD2-1</name>
+ <cmt>Parkmöglichkeit</cmt>
+ <desc>Parkplatz</desc>
+ <url>http://www.opencaching.de/viewcache.php?cacheid=159890</url>
+ <urlname>OCDDD2 Kaiserstein und Grabhügel Ludwigsburg</urlname>
+ <sym>Parking Area</sym>
+ <type>Waypoint|Parking Area</type>
+ <gsak:wptExtension xmlns:gsak="http://www.gsak.net/xmlv1/4">
+ <gsak:Parent>OCDDD2</gsak:Parent>
+ </gsak:wptExtension>
+ </wpt>
+ <wpt lat="48.88372" lon="9.18117">
+ <time>2012-03-23T00:00:00Z</time>
+ <name>OCDDD2-2</name>
+ <cmt>Parkmöglichkeit abends und am Wochenende</cmt>
+ <desc>Parkplatz</desc>
+ <url>http://www.opencaching.de/viewcache.php?cacheid=159890</url>
+ <urlname>OCDDD2 Kaiserstein und Grabhügel Ludwigsburg</urlname>
+ <sym>Parking Area</sym>
+ <type>Waypoint|Parking Area</type>
+ <gsak:wptExtension xmlns:gsak="http://www.gsak.net/xmlv1/4">
+ <gsak:Parent>OCDDD2</gsak:Parent>
+ </gsak:wptExtension>
+ </wpt>
+ <wpt lat="48.88450" lon="9.17657">
+ <time>2012-03-23T00:00:00Z</time>
+ <name>OCDDD2-3</name>
+ <cmt>Tafel</cmt>
+ <desc>Station oder Referenzpunkt</desc>
+ <url>http://www.opencaching.de/viewcache.php?cacheid=159890</url>
+ <urlname>OCDDD2 Kaiserstein und Grabhügel Ludwigsburg</urlname>
+ <sym>Flag, Green</sym>
+ <type>Waypoint|Flag, Green</type>
+ <gsak:wptExtension xmlns:gsak="http://www.gsak.net/xmlv1/4">
+ <gsak:Parent>OCDDD2</gsak:Parent>
+ </gsak:wptExtension>
+ </wpt>
+ <wpt lat="48.885" lon="9.174999999999999">
+ <name>01</name>
+ <cmt>Ttt</cmt>
+ <desc>Wegpunkt 4</desc>
+ <sym>Question to Answer</sym>
+ <type>Waypoint|Question to Answer</type>
+ <gsak:wptExtension xmlns:gsak="http://www.gsak.net/xmlv1/4">
+ <gsak:Parent>OCDDD2</gsak:Parent>
+ </gsak:wptExtension>
+ <cgeo:userdefined>true</cgeo:userdefined>
+ </wpt>
+</gpx> \ No newline at end of file
diff --git a/tests/src/cgeo/geocaching/export/GpxSerializerTest.java b/tests/src/cgeo/geocaching/export/GpxSerializerTest.java
index 5c83b35..9e3c3a4 100644
--- a/tests/src/cgeo/geocaching/export/GpxSerializerTest.java
+++ b/tests/src/cgeo/geocaching/export/GpxSerializerTest.java
@@ -22,7 +22,15 @@ public class GpxSerializerTest extends AbstractResourceInstrumentationTestCase {
public static void testWriteEmptyGPX() throws Exception {
final StringWriter writer = new StringWriter();
new GpxSerializer().writeGPX(Collections.<String> emptyList(), writer, null);
- assertEquals("<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><gpx version=\"1.0\" creator=\"c:geo - http://www.cgeo.org/\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/1/cache.xsd\" xmlns=\"http://www.topografix.com/GPX/1/0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:groundspeak=\"http://www.groundspeak.com/cache/1/0\" />", writer.getBuffer().toString());
+ assertEquals("<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>" +
+ "<gpx version=\"1.0\" creator=\"c:geo - http://www.cgeo.org/\" " +
+ "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd " +
+ "http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/1/cache.xsd " +
+ "http://www.gsak.net/xmlv1/4 http://www.gsak.net/xmlv1/4/gsak.xsd\" " +
+ "xmlns=\"http://www.topografix.com/GPX/1/0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
+ "xmlns:groundspeak=\"http://www.groundspeak.com/cache/1/0\" xmlns:gsak=\"http://www.gsak.net/xmlv1/4\" " +
+ "xmlns:cgeo=\"http://www.cgeo.org/wptext/1/0\" />",
+ writer.getBuffer().toString());
}
public void testProgressReporting() throws IOException, ParserException {
diff --git a/tests/src/cgeo/geocaching/files/GPXImporterTest.java b/tests/src/cgeo/geocaching/files/GPXImporterTest.java
index 8f5d821..ee42d23 100644
--- a/tests/src/cgeo/geocaching/files/GPXImporterTest.java
+++ b/tests/src/cgeo/geocaching/files/GPXImporterTest.java
@@ -80,6 +80,29 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase {
assertTrue(cache.getWaypoints().isEmpty());
}
+ public void testImportOcGpx() throws IOException {
+ final String geocode = "OCDDD2";
+ removeCacheCompletely(geocode);
+ final File ocddd2 = new File(tempDir, "ocddd2.gpx");
+ copyResourceToFile(R.raw.ocddd2, ocddd2);
+
+ final GPXImporter.ImportGpxFileThread importThread = new GPXImporter.ImportGpxFileThread(ocddd2, listId, importStepHandler, progressHandler);
+ runImportThread(importThread);
+
+ assertEquals(4, importStepHandler.messages.size());
+ final Iterator<Message> iMsg = importStepHandler.messages.iterator();
+ assertEquals(GPXImporter.IMPORT_STEP_START, iMsg.next().what);
+ assertEquals(GPXImporter.IMPORT_STEP_READ_FILE, iMsg.next().what);
+ assertEquals(GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, iMsg.next().what);
+ assertEquals(GPXImporter.IMPORT_STEP_FINISHED, iMsg.next().what);
+ final SearchResult search = (SearchResult) importStepHandler.messages.get(3).obj;
+ assertEquals(Collections.singletonList(geocode), new ArrayList<String>(search.getGeocodes()));
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ assertCacheProperties(cache);
+
+ assertEquals("Incorrect number of waypoints imported", 4, cache.getWaypoints().size());
+ }
+
private void runImportThread(GPXImporter.ImportThread importThread) {
importThread.start();
try {