diff options
Diffstat (limited to 'src/cgeo/geocaching/files/GPXParser.java')
| -rw-r--r-- | src/cgeo/geocaching/files/GPXParser.java | 1484 |
1 files changed, 742 insertions, 742 deletions
diff --git a/src/cgeo/geocaching/files/GPXParser.java b/src/cgeo/geocaching/files/GPXParser.java index a9978c5..1e1458a 100644 --- a/src/cgeo/geocaching/files/GPXParser.java +++ b/src/cgeo/geocaching/files/GPXParser.java @@ -1,17 +1,15 @@ package cgeo.geocaching.files; -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; +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.geopoint.Geopoint; import org.apache.commons.lang3.StringUtils; import org.xml.sax.Attributes; @@ -25,435 +23,437 @@ import android.sax.RootElement; import android.sax.StartElementListener; import android.util.Log; import android.util.Xml; -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.geopoint.Geopoint; + +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 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 = validate(body.toLowerCase()); - } - }); - - // waypoint.cache.attributes - // @see issue #299 + // 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 = validate(body.toLowerCase()); + } + }); + + // waypoint.cache.attributes + // @see issue #299 // <groundspeak:attributes> // <groundspeak:attribute id="32" inc="1">Bicycles</groundspeak:attribute> @@ -474,10 +474,10 @@ public abstract class GPXParser extends FileParser { 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); + if (cache.attributes == null) { + cache.attributes = new ArrayList<String>(); + } + cache.attributes.add(internalId); } } } catch (NumberFormatException e) { @@ -487,308 +487,308 @@ public abstract class GPXParser extends FileParser { }); // 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(); - } + 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(); + } } |
