aboutsummaryrefslogtreecommitdiffstats
path: root/src/cgeo/geocaching/cgGPXParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgeo/geocaching/cgGPXParser.java')
-rw-r--r--src/cgeo/geocaching/cgGPXParser.java547
1 files changed, 547 insertions, 0 deletions
diff --git a/src/cgeo/geocaching/cgGPXParser.java b/src/cgeo/geocaching/cgGPXParser.java
new file mode 100644
index 0000000..a4b1961
--- /dev/null
+++ b/src/cgeo/geocaching/cgGPXParser.java
@@ -0,0 +1,547 @@
+package cgeo.geocaching;
+
+import android.os.Handler;
+import android.os.Message;
+import android.sax.Element;
+import android.sax.EndElementListener;
+import android.sax.EndTextElementListener;
+import android.sax.RootElement;
+import android.sax.StartElementListener;
+import android.text.Html;
+import android.util.Log;
+import android.util.Xml;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.xml.sax.Attributes;
+
+public class cgGPXParser {
+
+ private cgeoapplication app = null;
+ private cgBase base = null;
+ private int listId = 1;
+ private cgSearch search = null;
+ private Handler handler = null;
+ private cgCache cache = new cgCache();
+ private cgTrackable trackable = new cgTrackable();
+ private cgLog log = new cgLog();
+ private boolean htmlShort = true;
+ private boolean htmlLong = true;
+ private String type = null;
+ private String sym = null;
+ private String ns = null;
+ private ArrayList<String> nsGCList = new ArrayList<String>();
+ private final Pattern patternGeocode = Pattern.compile("(GC[0-9A-Z]+)", Pattern.CASE_INSENSITIVE);
+ private String name = null;
+ private String cmt = null;
+ private String desc = null;
+
+ public cgGPXParser(cgeoapplication appIn, cgBase baseIn, int listIdIn, cgSearch searchIn) {
+ app = appIn;
+ base = baseIn;
+ listId = listIdIn;
+ search = searchIn;
+
+ nsGCList.add("http://www.groundspeak.com/cache/1/1"); // PQ 1.1
+ nsGCList.add("http://www.groundspeak.com/cache/1/0/1"); // PQ 1.0.1
+ nsGCList.add("http://www.groundspeak.com/cache/1/0"); // PQ 1.0
+ }
+
+ public long parse(File file, int version, Handler handlerIn) {
+ handler = handlerIn;
+ if (file == null) {
+ return 0l;
+ }
+
+ if (version == 11) {
+ ns = "http://www.topografix.com/GPX/1/1"; // GPX 1.1
+ } else {
+ ns = "http://www.topografix.com/GPX/1/0"; // GPX 1.0
+ }
+ final RootElement root = new RootElement(ns, "gpx");
+ final Element waypoint = root.getChild(ns, "wpt");
+
+ // waypoint - attributes
+ waypoint.setStartElementListener(new StartElementListener() {
+
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("lat") > -1) {
+ cache.latitude = new Double(attrs.getValue("lat"));
+ }
+ if (attrs.getIndex("lon") > -1) {
+ cache.longitude = new Double(attrs.getValue("lon"));
+ }
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse waypoint's latitude and/or longitude.");
+ }
+ }
+ });
+
+ // waypoint
+ waypoint.setEndElementListener(new EndElementListener() {
+
+ public void end() {
+ if (cache.geocode == null || cache.geocode.length() == 0) {
+ // try to find geocode somewhere else
+ String geocode = null;
+ Matcher matcherGeocode = null;
+
+ if (name != null && geocode == null) {
+ matcherGeocode = patternGeocode.matcher(name);
+ while (matcherGeocode.find()) {
+ if (matcherGeocode.groupCount() > 0) {
+ geocode = matcherGeocode.group(1);
+ }
+ }
+ }
+
+ if (desc != null && geocode == null) {
+ matcherGeocode = patternGeocode.matcher(desc);
+ while (matcherGeocode.find()) {
+ if (matcherGeocode.groupCount() > 0) {
+ geocode = matcherGeocode.group(1);
+ }
+ }
+ }
+
+ if (cmt != null && geocode == null) {
+ matcherGeocode = patternGeocode.matcher(cmt);
+ while (matcherGeocode.find()) {
+ if (matcherGeocode.groupCount() > 0) {
+ geocode = matcherGeocode.group(1);
+ }
+ }
+ }
+
+ if (geocode != null && geocode.length() > 0) {
+ cache.geocode = geocode;
+ }
+
+ geocode = null;
+ matcherGeocode = null;
+ }
+
+ if (cache.geocode != null && cache.geocode.length() > 0
+ && cache.latitude != null && cache.longitude != null
+ && ((type == null && sym == null)
+ || (type != null && type.indexOf("geocache") > -1)
+ || (sym != null && sym.indexOf("geocache") > -1))) {
+ cache.latitudeString = base.formatCoordinate(cache.latitude, "lat", true);
+ cache.longitudeString = base.formatCoordinate(cache.longitude, "lon", true);
+ if (cache.inventory != null) {
+ cache.inventoryItems = cache.inventory.size();
+ } else {
+ cache.inventoryItems = 0;
+ }
+ cache.reason = listId;
+ cache.updated = new Date().getTime();
+ cache.detailedUpdate = new Date().getTime();
+ cache.detailed = true;
+
+ app.addCacheToSearch(search, cache);
+ }
+
+ if (handler != null) {
+ final Message msg = new Message();
+ msg.obj = search.getCount();
+ handler.sendMessage(msg);
+ }
+
+ htmlShort = true;
+ htmlLong = true;
+ type = null;
+ sym = null;
+ name = null;
+ desc = null;
+ cmt = null;
+
+ cache = null;
+ cache = new cgCache();
+ }
+ });
+
+ // waypoint.time
+ waypoint.getChild(ns, "time").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ try {
+ cache.hidden = cgBase.dateGPXIn.parse(body.trim());
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse cache date: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.name
+ waypoint.getChild(ns, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ name = body;
+
+ final String content = Html.fromHtml(body).toString().trim();
+ cache.name = content;
+ if (cache.name.length() > 2 && cache.name.substring(0, 2).equalsIgnoreCase("GC") == true) {
+ cache.geocode = cache.name.toUpperCase();
+ }
+ }
+ });
+
+ // waypoint.desc
+ waypoint.getChild(ns, "desc").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ desc = body;
+
+ final String content = Html.fromHtml(body).toString().trim();
+ cache.shortdesc = content;
+ }
+ });
+
+ // waypoint.cmt
+ waypoint.getChild(ns, "cmt").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ cmt = body;
+
+ final String content = Html.fromHtml(body).toString().trim();
+ cache.description = content;
+ }
+ });
+
+ // waypoint.type
+ waypoint.getChild(ns, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ final String[] content = body.split("\\|");
+ if (content.length > 0) {
+ type = content[0].toLowerCase().trim();
+ }
+ }
+ });
+
+ // waypoint.sym
+ waypoint.getChild(ns, "sym").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ body = body.toLowerCase();
+ sym = body;
+ if (body.indexOf("geocache") != -1 && body.indexOf("found") != -1) {
+ cache.found = true;
+ }
+ }
+ });
+
+ for (String nsGC : nsGCList) {
+ // waypoints.cache
+ final Element gcCache = waypoint.getChild(nsGC, "cache");
+
+ gcCache.setStartElementListener(new StartElementListener() {
+
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("id") > -1) {
+ cache.cacheid = attrs.getValue("id");
+ }
+ if (attrs.getIndex("archived") > -1) {
+ final String at = attrs.getValue("archived").toLowerCase();
+ if (at.equals("true")) {
+ cache.archived = true;
+ } else {
+ cache.archived = false;
+ }
+ }
+ if (attrs.getIndex("available") > -1) {
+ final String at = attrs.getValue("available").toLowerCase();
+ if (at.equals("true")) {
+ cache.disabled = false;
+ } else {
+ cache.disabled = true;
+ }
+ }
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse cache attributes.");
+ }
+ }
+ });
+
+ // waypoint.cache.name
+ gcCache.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ final String content = Html.fromHtml(body).toString().trim();
+ cache.name = content;
+ }
+ });
+
+ // waypoint.cache.owner
+ gcCache.getChild(nsGC, "owner").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ final String content = Html.fromHtml(body).toString().trim();
+ cache.owner = content;
+ }
+ });
+
+ // waypoint.cache.type
+ gcCache.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ final String content = cgBase.cacheTypes.get(body.toLowerCase());
+ cache.type = content;
+ }
+ });
+
+ // waypoint.cache.container
+ gcCache.getChild(nsGC, "container").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ final String content = body.toLowerCase();
+ cache.size = content;
+ }
+ });
+
+ // waypoint.cache.difficulty
+ gcCache.getChild(nsGC, "difficulty").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ try {
+ cache.difficulty = new Float(body);
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse difficulty: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.cache.terrain
+ gcCache.getChild(nsGC, "terrain").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ try {
+ cache.terrain = new Float(body);
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse terrain: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.cache.country
+ gcCache.getChild(nsGC, "country").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ if (cache.location == null || cache.location.length() == 0) {
+ cache.location = body.trim();
+ } else {
+ cache.location = cache.location + ", " + body.trim();
+ }
+ }
+ });
+
+ // waypoint.cache.state
+ gcCache.getChild(nsGC, "state").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ if (cache.location == null || cache.location.length() == 0) {
+ cache.location = body.trim();
+ } else {
+ cache.location = body.trim() + ", " + cache.location;
+ }
+ }
+ });
+
+ // waypoint.cache.encoded_hints
+ gcCache.getChild(nsGC, "encoded_hints").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ cache.hint = body.trim();
+ }
+ });
+
+ // waypoint.cache.short_description
+ gcCache.getChild(nsGC, "short_description").setStartElementListener(new StartElementListener() {
+
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("html") > -1) {
+ final String at = attrs.getValue("html").toLowerCase();
+ if (at.equals("false")) {
+ htmlShort = false;
+ }
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+ });
+
+ gcCache.getChild(nsGC, "short_description").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ if (htmlShort == false) {
+ cache.shortdesc = Html.fromHtml(body).toString();
+ } else {
+ cache.shortdesc = body;
+ }
+ }
+ });
+
+ // waypoint.cache.long_description
+ gcCache.getChild(nsGC, "long_description").setStartElementListener(new StartElementListener() {
+
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("html") > -1) {
+ final String at = attrs.getValue("html").toLowerCase();
+ if (at.equals("false")) {
+ htmlLong = false;
+ }
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+ });
+
+ gcCache.getChild(nsGC, "long_description").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ if (htmlLong == false) {
+ cache.description = Html.fromHtml(body).toString().trim();
+ } else {
+ cache.description = body;
+ }
+ }
+ });
+
+ // waypoint.cache.travelbugs
+ final Element gcTBs = gcCache.getChild(nsGC, "travelbugs");
+
+ // waypoint.cache.travelbugs.travelbug
+ gcTBs.getChild(nsGC, "travelbug").setStartElementListener(new StartElementListener() {
+
+ public void start(Attributes attrs) {
+ trackable = new cgTrackable();
+
+ try {
+ if (attrs.getIndex("ref") > -1) {
+ trackable.geocode = attrs.getValue("ref").toUpperCase();
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+ });
+
+ // waypoint.cache.travelbug
+ final Element gcTB = gcTBs.getChild(nsGC, "travelbug");
+
+ gcTB.setEndElementListener(new EndElementListener() {
+
+ public void end() {
+ if (trackable.geocode != null && trackable.geocode.length() > 0 && trackable.name != null && trackable.name.length() > 0) {
+ if (cache.inventory == null)
+ cache.inventory = new ArrayList<cgTrackable>();
+ cache.inventory.add(trackable);
+ }
+ }
+ });
+
+ // waypoint.cache.travelbugs.travelbug.name
+ gcTB.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ String content = Html.fromHtml(body).toString();
+ trackable.name = content;
+ }
+ });
+
+ // waypoint.cache.logs
+ final Element gcLogs = gcCache.getChild(nsGC, "logs");
+
+ // waypoint.cache.log
+ final Element gcLog = gcLogs.getChild(nsGC, "log");
+
+ gcLog.setStartElementListener(new StartElementListener() {
+
+ public void start(Attributes attrs) {
+ log = new cgLog();
+
+ try {
+ if (attrs.getIndex("id") > -1) {
+ log.id = Integer.parseInt(attrs.getValue("id"));
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+ });
+
+ gcLog.setEndElementListener(new EndElementListener() {
+
+ public void end() {
+ if (log.log != null && log.log.length() > 0) {
+ if (cache.logs == null)
+ cache.logs = new ArrayList<cgLog>();
+ cache.logs.add(log);
+ }
+ }
+ });
+
+ // waypoint.cache.logs.log.date
+ gcLog.getChild(nsGC, "date").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ try {
+ log.date = cgBase.dateGPXIn.parse(body.trim()).getTime();
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse log date: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.cache.logs.log.type
+ gcLog.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ final String content = body.trim().toLowerCase();
+ if (cgBase.logTypes0.containsKey(content) == true) {
+ log.type = cgBase.logTypes0.get(content);
+ } else {
+ log.type = 4;
+ }
+ }
+ });
+
+ // waypoint.cache.logs.log.finder
+ gcLog.getChild(nsGC, "finder").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ String content = Html.fromHtml(body).toString();
+ log.author = content;
+ }
+ });
+
+ // waypoint.cache.logs.log.finder
+ gcLog.getChild(nsGC, "text").setEndTextElementListener(new EndTextElementListener() {
+
+ public void end(String body) {
+ String content = Html.fromHtml(body).toString();
+ log.log = content;
+ }
+ });
+ }
+
+ try {
+ Xml.parse(new FileInputStream(file), Xml.Encoding.UTF_8, root.getContentHandler());
+
+ return search.getCurrentId();
+ } catch (Exception e) {
+ Log.e(cgSettings.tag, "Cannot parse .gpx file " + file.getAbsolutePath() + " as GPX " + version + ": " + e.toString());
+ }
+
+ return 0l;
+ }
+}