aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/files/GPXParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/files/GPXParser.java')
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java795
1 files changed, 795 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
new file mode 100644
index 0000000..a0da184
--- /dev/null
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -0,0 +1,795 @@
+package cgeo.geocaching.files;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgBase;
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.cgLog;
+import cgeo.geocaching.cgSearch;
+import cgeo.geocaching.cgSettings;
+import cgeo.geocaching.cgTrackable;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.enumerations.CacheSize;
+import cgeo.geocaching.geopoint.Geopoint;
+
+import org.apache.commons.lang3.StringUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import android.os.Handler;
+import android.sax.Element;
+import android.sax.EndElementListener;
+import android.sax.EndTextElementListener;
+import android.sax.RootElement;
+import android.sax.StartElementListener;
+import android.util.Log;
+import android.util.Xml;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public abstract class GPXParser extends FileParser {
+
+ private static final SimpleDateFormat formatSimple = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // 2010-04-20T07:00:00Z
+ private static final SimpleDateFormat formatTimezone = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.000'Z"); // 2010-04-20T01:01:03.000-04:00
+
+ private static final Pattern patternGeocode = Pattern.compile("([A-Z]{2}[0-9A-Z]+)", Pattern.CASE_INSENSITIVE);
+ private static final Pattern patternGuid = Pattern.compile(".*" + Pattern.quote("guid=") + "([0-9a-z\\-]+)", Pattern.CASE_INSENSITIVE);
+ private static final String[] nsGCList = new String[] {
+ "http://www.groundspeak.com/cache/1/1", // PQ 1.1
+ "http://www.groundspeak.com/cache/1/0/1", // PQ 1.0.1
+ "http://www.groundspeak.com/cache/1/0", // PQ 1.0
+ };
+
+ private static final String GSAK_NS = "http://www.gsak.net/xmlv1/5";
+
+ private static cgeoapplication app = null;
+ private int listId = 1;
+ private cgSearch search = null;
+ final protected String namespace;
+ final private String version;
+ private Handler handler = null;
+
+ private cgCache cache = new cgCache();
+ private cgTrackable trackable = new cgTrackable();
+ private cgLog log = new cgLog();
+
+ private String type = null;
+ private String sym = null;
+ private String name = null;
+ private String cmt = null;
+ private String desc = null;
+ protected String[] userData = new String[5]; // take 5 cells, that makes indexing 1..4 easier
+
+ private final class UserDataListener implements EndTextElementListener {
+ private int index;
+
+ public UserDataListener(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public void end(String user) {
+ userData[index] = validate(user);
+ }
+ }
+
+ private static final class CacheAttributeTranslator {
+ // List of cache attributes matching IDs used in GPX files.
+ // The ID is represented by the position of the String in the array.
+ // Strings are not used as text but as resource IDs of strings, just to be aware of changes
+ // made in strings.xml which then will lead to compile errors here and not to runtime errors.
+ private static final int[] CACHE_ATTRIBUTES = {
+ -1, // 0
+ R.string.attribute_dogs_yes, // 1
+ R.string.attribute_fee_yes, // 2
+ R.string.attribute_rappelling_yes, // 3
+ R.string.attribute_boat_yes, // 4
+ R.string.attribute_scuba_yes, // 5
+ R.string.attribute_kids_yes, // 6
+ R.string.attribute_onehour_yes, // 7
+ R.string.attribute_scenic_yes, // 8
+ R.string.attribute_hiking_yes, // 9
+ R.string.attribute_climbing_yes, // 10
+ R.string.attribute_wading_yes, // 11
+ R.string.attribute_swimming_yes, // 12
+ R.string.attribute_available_yes, // 13
+ R.string.attribute_night_yes, // 14
+ R.string.attribute_winter_yes, // 15
+ -1, // 16
+ R.string.attribute_poisonoak_yes, // 17
+ R.string.attribute_dangerousanimals_yes, // 18
+ R.string.attribute_ticks_yes, // 19
+ R.string.attribute_mine_yes, // 20
+ R.string.attribute_cliff_yes, // 21
+ R.string.attribute_hunting_yes, // 22
+ R.string.attribute_danger_yes, // 23
+ R.string.attribute_wheelchair_yes, // 24
+ R.string.attribute_parking_yes, // 25
+ R.string.attribute_public_yes, // 26
+ R.string.attribute_water_yes, // 27
+ R.string.attribute_restrooms_yes, // 28
+ R.string.attribute_phone_yes, // 29
+ R.string.attribute_picnic_yes, // 30
+ R.string.attribute_camping_yes, // 31
+ R.string.attribute_bicycles_yes, // 32
+ R.string.attribute_motorcycles_yes, // 33
+ R.string.attribute_quads_yes, // 34
+ R.string.attribute_jeeps_yes, // 35
+ R.string.attribute_snowmobiles_yes, // 36
+ R.string.attribute_horses_yes, // 37
+ R.string.attribute_campfires_yes, // 38
+ R.string.attribute_thorn_yes, // 39
+ R.string.attribute_stealth_yes, // 40
+ R.string.attribute_stroller_yes, // 41
+ R.string.attribute_firstaid_yes, // 42
+ R.string.attribute_cow_yes, // 43
+ R.string.attribute_flashlight_yes, // 44
+ R.string.attribute_landf_yes, // 45
+ R.string.attribute_rv_yes, // 46
+ R.string.attribute_field_puzzle_yes, // 47
+ R.string.attribute_uv_yes, // 48
+ R.string.attribute_snowshoes_yes, // 49
+ R.string.attribute_skiis_yes, // 50
+ R.string.attribute_s_tool_yes, // 51
+ R.string.attribute_nightcache_yes, // 52
+ R.string.attribute_parkngrab_yes, // 53
+ R.string.attribute_abandonedbuilding_yes, // 54
+ R.string.attribute_hike_short_yes, // 55
+ R.string.attribute_hike_med_yes, // 56
+ R.string.attribute_hike_long_yes, // 57
+ R.string.attribute_fuel_yes, // 58
+ R.string.attribute_food_yes, // 59
+ R.string.attribute_wirelessbeacon_yes, // 60
+ R.string.attribute_partnership_yes, // 61
+ R.string.attribute_seasonal_yes, // 62
+ R.string.attribute_touristok_yes, // 63
+ R.string.attribute_treeclimbing_yes, // 64
+ R.string.attribute_frontyard_yes, // 65
+ R.string.attribute_teamwork_yes, // 66
+ };
+ private static final String YES = "_yes";
+ private static final String NO = "_no";
+ private static final Pattern BASENAME_PATTERN = Pattern.compile("^.*attribute_(.*)(_yes|_no)");
+
+ // map GPX-Attribute-Id to baseName
+ public static String getBaseName(final int id) {
+ // get String out of array
+ if (CACHE_ATTRIBUTES.length <= id) {
+ return null;
+ }
+ final int stringId = CACHE_ATTRIBUTES[id];
+ if (stringId == -1) {
+ return null; // id not found
+ }
+ // get text for string
+ String stringName = null;
+ try {
+ stringName = app.getResources().getResourceName(stringId);
+ } catch (NullPointerException e) {
+ return null;
+ }
+ if (stringName == null) {
+ return null;
+ }
+ // cut out baseName
+ final Matcher m = BASENAME_PATTERN.matcher(stringName);
+ if (!m.matches()) {
+ return null;
+ }
+ return m.group(1);
+ }
+
+ // @return baseName + "_yes" or "_no" e.g. "food_no" or "uv_yes"
+ public static String getInternalId(final int attributeId, final boolean active) {
+ final String baseName = CacheAttributeTranslator.getBaseName(attributeId);
+ if (baseName == null) {
+ return null;
+ }
+ return baseName + (active ? YES : NO);
+ }
+ }
+
+ protected GPXParser(cgeoapplication appIn, int listIdIn, cgSearch searchIn, String namespaceIn, String versionIn) {
+ app = appIn;
+ listId = listIdIn;
+ search = searchIn;
+ namespace = namespaceIn;
+ version = versionIn;
+ }
+
+ private static Date parseDate(String inputUntrimmed) throws ParseException {
+ final String input = inputUntrimmed.trim();
+ if (input.length() >= 3 && input.charAt(input.length() - 3) == ':') {
+ final String removeColon = input.substring(0, input.length() - 3) + input.substring(input.length() - 2);
+ return formatTimezone.parse(removeColon);
+ }
+ return formatSimple.parse(input);
+ }
+
+ public UUID parse(final InputStream stream, Handler handlerIn) {
+ handler = handlerIn;
+
+ final RootElement root = new RootElement(namespace, "gpx");
+ final Element waypoint = root.getChild(namespace, "wpt");
+
+ // waypoint - attributes
+ waypoint.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("lat") > -1 && attrs.getIndex("lon") > -1) {
+ cache.coords = new Geopoint(new Double(attrs.getValue("lat")),
+ 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() {
+
+ @Override
+ public void end() {
+ if (StringUtils.isBlank(cache.geocode)) {
+ // try to find geocode somewhere else
+ findGeoCode(name);
+ findGeoCode(desc);
+ findGeoCode(cmt);
+ }
+
+ if (StringUtils.isNotBlank(cache.geocode)
+ && cache.coords != null
+ && ((type == null && sym == null)
+ || (type != null && type.indexOf("geocache") > -1)
+ || (sym != null && sym.indexOf("geocache") > -1))) {
+ fixCache(cache);
+ cache.reason = listId;
+ cache.detailed = true;
+
+ if (StringUtils.isBlank(cache.personalNote)) {
+ StringBuilder buffer = new StringBuilder();
+ for (int i = 0; i < userData.length; i++) {
+ if (StringUtils.isNotBlank(userData[i])) {
+ buffer.append(' ').append(userData[i]);
+ }
+ }
+ String note = buffer.toString().trim();
+ if (StringUtils.isNotBlank(note)) {
+ cache.personalNote = note;
+ }
+ }
+
+ app.addCacheToSearch(search, cache);
+ }
+
+ showFinishedMessage(handler, search);
+
+ resetCache();
+ }
+ });
+
+ // waypoint.time
+ waypoint.getChild(namespace, "time").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ try {
+ cache.hidden = parseDate(body);
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse cache date: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.name
+ waypoint.getChild(namespace, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ name = body;
+
+ final String content = body.trim();
+ cache.name = content;
+
+ findGeoCode(cache.name);
+ findGeoCode(cache.description);
+ }
+ });
+
+ // waypoint.desc
+ waypoint.getChild(namespace, "desc").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ desc = body;
+
+ cache.shortdesc = validate(body);
+ }
+ });
+
+ // waypoint.cmt
+ waypoint.getChild(namespace, "cmt").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ cmt = body;
+
+ cache.description = validate(body);
+ }
+ });
+
+ // waypoint.type
+ waypoint.getChild(namespace, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String[] content = body.split("\\|");
+ if (content.length > 0) {
+ type = content[0].toLowerCase().trim();
+ }
+ }
+ });
+
+ // waypoint.sym
+ waypoint.getChild(namespace, "sym").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ body = body.toLowerCase();
+ sym = body;
+ if (body.indexOf("geocache") != -1 && body.indexOf("found") != -1) {
+ cache.found = true;
+ }
+ }
+ });
+
+ // waypoint.url
+ waypoint.getChild(namespace, "url").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String url) {
+ final Matcher matcher = patternGuid.matcher(url);
+ if (matcher.matches()) {
+ String guid = matcher.group(1);
+ if (StringUtils.isNotBlank(guid)) {
+ cache.guid = guid;
+ }
+ }
+ }
+ });
+
+ // for GPX 1.0, cache info comes from waypoint node (so called private children,
+ // for GPX 1.1 from extensions node
+ final Element cacheParent = getCacheParent(waypoint);
+
+ // GSAK extensions
+ final Element gsak = cacheParent.getChild(GSAK_NS, "wptExtension");
+ gsak.getChild(GSAK_NS, "Watch").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String watchList) {
+ cache.onWatchlist = Boolean.valueOf(watchList.trim());
+ }
+ });
+
+ gsak.getChild(GSAK_NS, "UserData").setEndTextElementListener(new UserDataListener(1));
+
+ for (int i = 2; i <= 4; i++) {
+ gsak.getChild(GSAK_NS, "User" + i).setEndTextElementListener(new UserDataListener(i));
+ }
+
+ // 3 different versions of the GC schema
+ for (String nsGC : nsGCList) {
+ // waypoints.cache
+ final Element gcCache = cacheParent.getChild(nsGC, "cache");
+
+ gcCache.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("id") > -1) {
+ cache.cacheId = attrs.getValue("id");
+ }
+ if (attrs.getIndex("archived") > -1) {
+ cache.archived = attrs.getValue("archived").equalsIgnoreCase("true");
+ }
+ if (attrs.getIndex("available") > -1) {
+ cache.disabled = !attrs.getValue("available").equalsIgnoreCase("true");
+ }
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse cache attributes.");
+ }
+ }
+ });
+
+ // waypoint.cache.name
+ gcCache.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String cacheName) {
+ cache.name = validate(cacheName);
+ }
+ });
+
+ // waypoint.cache.owner
+ gcCache.getChild(nsGC, "owner").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String cacheOwner) {
+ cache.owner = validate(cacheOwner);
+ }
+ });
+
+ // waypoint.cache.type
+ gcCache.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ setType(validate(body.toLowerCase()));
+ }
+ });
+
+ // waypoint.cache.container
+ gcCache.getChild(nsGC, "container").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ cache.size = CacheSize.FIND_BY_ID.get(validate(body.toLowerCase()));
+ }
+ });
+
+ // waypoint.cache.attributes
+ // @see issue #299
+
+ // <groundspeak:attributes>
+ // <groundspeak:attribute id="32" inc="1">Bicycles</groundspeak:attribute>
+ // <groundspeak:attribute id="13" inc="1">Available at all times</groundspeak:attribute>
+ // where inc = 0 => _no, inc = 1 => _yes
+ // IDs see array CACHE_ATTRIBUTES
+ final Element gcAttributes = gcCache.getChild(nsGC, "attributes");
+
+ // waypoint.cache.attribute
+ final Element gcAttribute = gcAttributes.getChild(nsGC, "attribute");
+
+ gcAttribute.setStartElementListener(new StartElementListener() {
+ @Override
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("id") > -1 && attrs.getIndex("inc") > -1) {
+ int attributeId = Integer.parseInt(attrs.getValue("id"));
+ boolean attributeActive = Integer.parseInt(attrs.getValue("inc")) != 0;
+ String internalId = CacheAttributeTranslator.getInternalId(attributeId, attributeActive);
+ if (internalId != null) {
+ if (cache.attributes == null) {
+ cache.attributes = new ArrayList<String>();
+ }
+ cache.attributes.add(internalId);
+ }
+ }
+ } catch (NumberFormatException e) {
+ // nothing
+ }
+ }
+ });
+
+ // waypoint.cache.difficulty
+ gcCache.getChild(nsGC, "difficulty").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ 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() {
+
+ @Override
+ 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() {
+
+ @Override
+ public void end(String country) {
+ if (StringUtils.isBlank(cache.location)) {
+ cache.location = validate(country);
+ } else {
+ cache.location = cache.location + ", " + country.trim();
+ }
+ }
+ });
+
+ // waypoint.cache.state
+ gcCache.getChild(nsGC, "state").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String state) {
+ if (StringUtils.isBlank(cache.location)) {
+ cache.location = validate(state);
+ } else {
+ cache.location = state.trim() + ", " + cache.location;
+ }
+ }
+ });
+
+ // waypoint.cache.encoded_hints
+ gcCache.getChild(nsGC, "encoded_hints").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String encoded) {
+ cache.hint = validate(encoded);
+ }
+ });
+
+ gcCache.getChild(nsGC, "short_description").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String shortDesc) {
+ cache.shortdesc = validate(shortDesc);
+ }
+ });
+
+ gcCache.getChild(nsGC, "long_description").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String desc) {
+ cache.description = validate(desc);
+ }
+ });
+
+ // waypoint.cache.travelbugs
+ final Element gcTBs = gcCache.getChild(nsGC, "travelbugs");
+
+ // waypoint.cache.travelbugs.travelbug
+ gcTBs.getChild(nsGC, "travelbug").setStartElementListener(new StartElementListener() {
+
+ @Override
+ 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() {
+
+ @Override
+ public void end() {
+ if (StringUtils.isNotBlank(trackable.geocode) && StringUtils.isNotBlank(trackable.name)) {
+ 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() {
+
+ @Override
+ public void end(String tbName) {
+ trackable.name = validate(tbName);
+ }
+ });
+
+ // waypoint.cache.logs
+ final Element gcLogs = gcCache.getChild(nsGC, "logs");
+
+ // waypoint.cache.log
+ final Element gcLog = gcLogs.getChild(nsGC, "log");
+
+ gcLog.setStartElementListener(new StartElementListener() {
+
+ @Override
+ 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() {
+
+ @Override
+ public void end() {
+ if (StringUtils.isNotBlank(log.log)) {
+ 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() {
+
+ @Override
+ public void end(String body) {
+ try {
+ log.date = parseDate(body).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() {
+
+ @Override
+ public void end(String body) {
+ final String logType = validate(body).toLowerCase();
+ if (cgBase.logTypes0.containsKey(logType)) {
+ log.type = cgBase.logTypes0.get(logType);
+ } else {
+ log.type = cgBase.LOG_NOTE;
+ }
+ }
+ });
+
+ // waypoint.cache.logs.log.finder
+ gcLog.getChild(nsGC, "finder").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String finderName) {
+ log.author = validate(finderName);
+ }
+ });
+
+ // waypoint.cache.logs.log.text
+ gcLog.getChild(nsGC, "text").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String logText) {
+ log.log = validate(logText);
+ }
+ });
+ }
+ boolean parsed = false;
+ try {
+ Xml.parse(stream, Xml.Encoding.UTF_8, root.getContentHandler());
+ parsed = true;
+ } catch (IOException e) {
+ Log.e(cgSettings.tag, "Cannot parse .gpx file as GPX " + version + ": could not read file!");
+ } catch (SAXException e) {
+ Log.e(cgSettings.tag, "Cannot parse .gpx file as GPX " + version + ": could not parse XML - " + e.toString());
+ }
+ return parsed ? search.getCurrentId() : null;
+ }
+
+ private UUID parse(final File file, final Handler handlerIn) {
+ if (file == null) {
+ return null;
+ }
+
+ FileInputStream fis = null;
+ UUID result = null;
+ try {
+ fis = new FileInputStream(file);
+ result = parse(fis, handlerIn);
+ } catch (FileNotFoundException e) {
+ Log.e(cgSettings.tag, "Cannot parse .gpx file " + file.getAbsolutePath() + " as GPX " + version + ": file not found!");
+ }
+ try {
+ if (fis != null) {
+ fis.close();
+ }
+ } catch (IOException e) {
+ Log.e(cgSettings.tag, "Error after parsing .gpx file " + file.getAbsolutePath() + " as GPX " + version + ": could not close file!");
+ }
+ return result;
+ }
+
+ protected abstract Element getCacheParent(Element waypoint);
+
+ protected static String validate(String input) {
+ if ("nil".equalsIgnoreCase(input)) {
+ return "";
+ }
+ return input.trim();
+ }
+
+ private void setType(String parsedString) {
+ final String knownType = cgBase.cacheTypes.get(parsedString);
+ if (knownType != null) {
+ cache.type = knownType;
+ }
+ else {
+ if (StringUtils.isBlank(cache.type)) {
+ cache.type = "mystery"; // default for not recognized types
+ }
+ }
+ }
+
+ private void findGeoCode(final String input) {
+ if (input == null || StringUtils.isNotBlank(cache.geocode)) {
+ return;
+ }
+ final Matcher matcherGeocode = patternGeocode.matcher(input);
+ if (matcherGeocode.find()) {
+ if (matcherGeocode.groupCount() > 0) {
+ final String geocode = matcherGeocode.group(1);
+ if (ConnectorFactory.canHandle(geocode)) {
+ cache.geocode = geocode;
+ }
+ }
+ }
+ }
+
+ private void resetCache() {
+ type = null;
+ sym = null;
+ name = null;
+ desc = null;
+ cmt = null;
+
+ cache = new cgCache();
+ for (int i = 0; i < userData.length; i++) {
+ userData[i] = null;
+ }
+ }
+
+ public static UUID parseGPX(cgeoapplication app, File file, int listId, Handler handler) {
+ final cgSearch search = new cgSearch();
+ UUID searchId = null;
+
+ try {
+ GPXParser parser = new GPX10Parser(app, listId, search);
+ searchId = parser.parse(file, handler);
+ if (searchId == null) {
+ parser = new GPX11Parser(app, listId, search);
+ searchId = parser.parse(file, handler);
+ }
+ } catch (Exception e) {
+ Log.e(cgSettings.tag, "cgBase.parseGPX: " + e.toString());
+ }
+
+ Log.i(cgSettings.tag, "Caches found in .gpx file: " + app.getCount(searchId));
+
+ return search.getCurrentId();
+ }
+}