diff options
| author | rsudev <rasch@munin-soft.de> | 2013-11-23 22:12:24 +0100 |
|---|---|---|
| committer | rsudev <rasch@munin-soft.de> | 2013-11-23 22:13:06 +0100 |
| commit | 652722134c0d18dbe77dd952903a71ae14755d27 (patch) | |
| tree | d3613d8d906b938de5d612b5f75b3cc72605f9c2 | |
| parent | 6240d934fc7e0d6b52fdf3b2cf21d0e72fdbf7c7 (diff) | |
| download | cgeo-652722134c0d18dbe77dd952903a71ae14755d27.zip cgeo-652722134c0d18dbe77dd952903a71ae14755d27.tar.gz cgeo-652722134c0d18dbe77dd952903a71ae14755d27.tar.bz2 | |
Implements stable keys for opencaching waypoints
additionally extend ex- and import (gpx) to also contain visited and
userdefined.
| -rw-r--r-- | main/project/xsd/cgeo.xsd | 16 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/DataStore.java | 14 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/Geocache.java | 8 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/Waypoint.java | 21 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/connector/AbstractConnector.java | 12 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/connector/IConnector.java | 19 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/connector/gc/GCConnector.java | 18 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/connector/oc/OkapiClient.java | 1 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/export/GpxSerializer.java | 59 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/files/GPXParser.java | 57 | ||||
| -rw-r--r-- | tests/res/raw/ocddd2.gpx | 133 | ||||
| -rw-r--r-- | tests/src/cgeo/geocaching/export/GpxSerializerTest.java | 10 | ||||
| -rw-r--r-- | tests/src/cgeo/geocaching/files/GPXImporterTest.java | 23 |
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.<br />
+<br />
+Zum einen der inzwischen abgetragene Grabhügel aus der späten Hallstattzeit, 6. Jahrhundert v. Chr. Informationen über ihn findet Ihr vor Ort.<br />
+<br />
+Zum anderen gegenüber ein Kaiserstein. Zwischen 1867 und 1918 wurden im deutschsprachigen Raum mehr als 1000 Kaiser-Wilhelm-Denkmäler errichtet.<br />
+<br />
+Um den Code zum Loggen zu erhalten, sucht vor Ort die Antworten auf folgende Fragen:<br />
+1. Am Kaiserstein (N 48 53.050 E 009 10.596) ist eine metallene Tafel angebracht. Wieviele Buchstaben hat die letzte Zeile ihrer Inschrift?<br />
+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?<br />
+3. An der Rückseite des Kaisersteins steht eine Sitzgelegenheit. Wieviele Beine hat sie?<br />
+Der Code besteht aus den 3 Antworten, direkt hintereinandergeschrieben (Beispiel für das Format: 48Cache9 ).<br />
+<br />
+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<br />
+<br />
+Viel Spaß!<p><em>© <a href='http://www.opencaching.de/viewprofile.php?userid=114440' target='_blank'>Emmett</a>, <a href='http://www.opencaching.de/viewcache.php?cacheid=159890' target='_blank'>Opencaching.de</a>, <a href='http://creativecommons.org/licenses/by-nc-nd/3.0/de/' target='_blank'>CC BY-NC-ND</a>, Stand: 10.11.2013; alle Logeinträge © jeweiliger Autor</em></p> +<br /></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"><p>Dankeschön für die Suche!</p> +<p>Habe den Cache am ersten schönen Frühlingstag gemacht!</p> +<p>Andi</p></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!!! <br />
+:-)</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"><p>War mein erster Cache überhaupt.</p> +<p>Hat echt Spaß gemacht. Gut für Grundschulkinder geeignet.</p> +<p>12.05.2012</p> +<p>R2-D2</p></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 { |
