diff options
Diffstat (limited to 'main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java')
| -rw-r--r-- | main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java | 224 |
1 files changed, 198 insertions, 26 deletions
diff --git a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java index 068ac88..6231c68 100644 --- a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java +++ b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java @@ -1,10 +1,15 @@ package cgeo.geocaching.connector.oc; +import cgeo.geocaching.Geocache; +import cgeo.geocaching.Image; import cgeo.geocaching.LogEntry; +import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.connector.gc.GCConnector; +import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; @@ -15,6 +20,7 @@ import org.apache.commons.lang3.StringUtils; import org.xml.sax.Attributes; import org.xml.sax.SAXException; +import android.content.res.Resources; import android.sax.Element; import android.sax.EndElementListener; import android.sax.EndTextElementListener; @@ -42,14 +48,18 @@ public class OC11XMLParser { private static Pattern STRIP_DATE = Pattern.compile("\\+0([0-9]){1}\\:00"); private static Pattern LOCAL_URL = Pattern.compile("href=\"(.*)\""); private static final int CACHE_PARSE_LIMIT = 250; + private static final Resources res = cgeoapplication.getInstance().getResources(); + + private static ImageHolder imageHolder = null; private static class CacheHolder { - public cgCache cache; + public Geocache cache; public String latitude; public String longitude; } private static class CacheLog { + public String id; public String cacheId; public LogEntry logEntry; } @@ -61,6 +71,13 @@ public class OC11XMLParser { public String hint; } + private static class ImageHolder { + public String url; + public String objectId; + protected String title; + protected boolean isSpoiler = false; + } + private static Date parseFullDate(final String date) { final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US); ISO8601DATEFORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -160,7 +177,7 @@ public class OC11XMLParser { } } - private static void setCacheStatus(final int statusId, final cgCache cache) { + private static void setCacheStatus(final int statusId, final Geocache cache) { switch (statusId) { case 1: cache.setArchived(false); @@ -178,7 +195,7 @@ public class OC11XMLParser { } private static void resetCache(final CacheHolder cacheHolder) { - cacheHolder.cache = new cgCache(null); + cacheHolder.cache = new Geocache(null); cacheHolder.cache.setReliableLatLon(true); cacheHolder.cache.setDescription(StringUtils.EMPTY); cacheHolder.latitude = "0.0"; @@ -197,9 +214,22 @@ public class OC11XMLParser { desc.hint = StringUtils.EMPTY; } - public static Collection<cgCache> parseCaches(final InputStream stream) throws IOException { + protected static int attributeId; + + public static Collection<Geocache> parseCaches(final InputStream stream) throws IOException { + // parse and return caches without filtering + return parseCaches(stream, true); + } + + public static Collection<Geocache> parseCachesFiltered(final InputStream stream) throws IOException { + // parse caches and filter result + return parseCaches(stream, false); + } + + private static Collection<Geocache> parseCaches(final InputStream stream, boolean ignoreFiltersIn) throws IOException { - final Map<String, cgCache> caches = new HashMap<String, cgCache>(); + final Map<String, Geocache> caches = new HashMap<String, Geocache>(); + final Map<String, LogEntry> logs = new HashMap<String, LogEntry>(); final CacheHolder cacheHolder = new CacheHolder(); final CacheLog logHolder = new CacheLog(); @@ -208,6 +238,8 @@ public class OC11XMLParser { final RootElement root = new RootElement("oc11xml"); final Element cacheNode = root.getChild("cache"); + final boolean ignoreFilters = ignoreFiltersIn; + // cache cacheNode.setStartElementListener(new StartElementListener() { @@ -222,17 +254,31 @@ public class OC11XMLParser { @Override public void end() { - cgCache cache = cacheHolder.cache; + Geocache cache = cacheHolder.cache; Geopoint coords = new Geopoint(cacheHolder.latitude, cacheHolder.longitude); - if (StringUtils.isNotBlank(cache.getGeocode()) - && !coords.equals(Geopoint.ZERO) - && !cache.isArchived() - && caches.size() < CACHE_PARSE_LIMIT) { - cache.setCoords(coords); + cache.setCoords(coords); + if (caches.size() < CACHE_PARSE_LIMIT && isValid(cache) && (ignoreFilters || !isExcluded(cache))) { cache.setDetailedUpdatedNow(); caches.put(cache.getCacheId(), cache); } } + + private boolean isExcluded(Geocache cache) { + if (cache.isArchived()) { + return true; + } + if (cache.isDisabled() && Settings.isExcludeDisabledCaches()) { + return true; + } + if ((cache.isFound() || cache.isOwner()) && Settings.isExcludeMyCaches()) { + return true; + } + return !Settings.getCacheType().contains(cache); + } + + private boolean isValid(Geocache cache) { + return StringUtils.isNotBlank(cache.getGeocode()) && !cache.getCoords().equals(Geopoint.ZERO); + } }); // cache.id @@ -289,7 +335,7 @@ public class OC11XMLParser { if (attrs.getIndex("gccom") > -1) { String gccode = attrs.getValue("gccom"); if (!StringUtils.isBlank(gccode)) { - cacheHolder.cache.setDescription(String.format("Listed on geocaching com: <a href=\"http://coord.info/%s\">%s</a><br /><br />", gccode, gccode)); + cacheHolder.cache.setDescription(res.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()) + ": <a href=\"http://coord.info/" + gccode + "\">" + gccode + "</a><br /><br />"); } } } @@ -363,7 +409,7 @@ public class OC11XMLParser { } }); - // cache.terrain + // cache.datehidden cacheNode.getChild("datehidden").setEndTextElementListener(new EndTextElementListener() { @Override @@ -373,12 +419,56 @@ public class OC11XMLParser { } }); + // cache.userid + final Element useridNode = cacheNode.getChild("userid"); + + useridNode.setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attributes) { + if (attributes.getIndex("id") > -1) { + cacheHolder.cache.setOwnerUserId(attributes.getValue("id")); + } + } + }); + + useridNode.setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + cacheHolder.cache.setOwnerDisplayName(body); + } + }); + // cache.attributes.attribute - cacheNode.getChild("attributes").getChild("attribute").setEndTextElementListener(new EndTextElementListener() { + final Element attributeNode = cacheNode.getChild("attributes").getChild("attribute"); + + attributeNode.setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attributes) { + if (attributes.getIndex("id") > -1) { + try { + attributeId = Integer.parseInt(attributes.getValue("id")); + } catch (NumberFormatException e) { + Log.w(String.format("Failed to parse attribute id of cache '%s'.", cacheHolder.cache.getGeocode())); + } + } + } + }); + + attributeNode.setEndTextElementListener(new EndTextElementListener() { @Override public void end(String body) { - if (StringUtils.isNotBlank(body)) { - cacheHolder.cache.getAttributes().add(body.trim()); + CacheAttribute attribute = CacheAttribute.getByOcId(attributeId); + if (attribute != null) { + // semantic of attributes on opencaching is always "yes" + cacheHolder.cache.getAttributes().add(attribute.getAttributeName(true)); + } + else { + if (StringUtils.isNotBlank(body)) { + cacheHolder.cache.getAttributes().add(body.trim()); + } } } }); @@ -398,9 +488,9 @@ public class OC11XMLParser { @Override public void end() { - final cgCache cache = caches.get(descHolder.cacheId); + final Geocache cache = caches.get(descHolder.cacheId); if (cache != null) { - cache.setShortdesc(descHolder.shortDesc); + cache.setShortDescription(descHolder.shortDesc); cache.setDescription(cache.getDescription() + descHolder.desc); cache.setHint(descHolder.hint); } @@ -441,8 +531,7 @@ public class OC11XMLParser { @Override public void end(String body) { - final String content = body.trim(); - descHolder.hint = content; + descHolder.hint = body.trim(); } }); @@ -461,10 +550,11 @@ public class OC11XMLParser { @Override public void end() { - final cgCache cache = caches.get(logHolder.cacheId); + final Geocache cache = caches.get(logHolder.cacheId); if (cache != null && logHolder.logEntry.type != LogType.UNKNOWN) { - cache.getLogs().prepend(logHolder.logEntry); - if (logHolder.logEntry.type == LogType.FOUND_IT + logs.put(logHolder.id, logHolder.logEntry); + cache.getLogs().add(0, logHolder.logEntry); + if ((logHolder.logEntry.type == LogType.FOUND_IT || logHolder.logEntry.type == LogType.ATTENDED) && StringUtils.equalsIgnoreCase(logHolder.logEntry.author, Settings.getOCConnectorUserName())) { cache.setFound(true); cache.setVisitedDate(logHolder.logEntry.date); @@ -473,6 +563,15 @@ public class OC11XMLParser { } }); + // cachelog.id + cacheLog.getChild("id").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + logHolder.id = StringUtils.trim(body); + } + }); + // cachelog.cacheid cacheLog.getChild("cacheid").setEndTextElementListener(new EndTextElementListener() { @@ -530,6 +629,76 @@ public class OC11XMLParser { } }); + // pictures + final Element picture = root.getChild("picture"); + + picture.setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attrs) { + imageHolder = new ImageHolder(); + } + }); + + picture.setEndElementListener(new EndElementListener() { + + @Override + public void end() { + if (imageHolder.isSpoiler) { + final Geocache cache = caches.get(imageHolder.objectId); + if (cache != null) { + Image spoiler = new Image(imageHolder.url, imageHolder.title); + cache.addSpoiler(spoiler); + } + } + else { + final LogEntry log = logs.get(imageHolder.objectId); + if (log != null) { + log.addLogImage(new Image(imageHolder.url, imageHolder.title)); + } + } + } + }); + + // picture.object + picture.getChild("object").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + imageHolder.objectId = StringUtils.trim(body); + } + }); + + // picture.title + picture.getChild("title").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + imageHolder.title = StringUtils.trim(body); + } + }); + + // picture.url + picture.getChild("url").setEndTextElementListener(new EndTextElementListener() { + + @Override + public void end(String body) { + imageHolder.url = StringUtils.trim(body); + } + }); + + // picture.attributes + picture.getChild("attributes").setStartElementListener(new StartElementListener() { + + @Override + public void start(Attributes attributes) { + if (attributes.getIndex("spoiler") > -1) { + String spoiler = attributes.getValue("spoiler"); + imageHolder.isSpoiler = ("1".equals(spoiler)); + } + } + }); + try { Xml.parse(stream, Xml.Encoding.UTF_8, root.getContentHandler()); return caches.values(); @@ -539,6 +708,9 @@ public class OC11XMLParser { } } + /** + * Converts local links to absolute links targeting the OC website. + */ private static String linkify(String input) { String result = input; Matcher matcher = LOCAL_URL.matcher(result); @@ -561,8 +733,8 @@ public class OC11XMLParser { protected static String stripMarkup(String input) { if (StringUtils.startsWith(input, PARAGRAPH_BEGIN) && StringUtils.endsWith(input, PARAGRAPH_END)) { String inner = input.substring(PARAGRAPH_BEGIN.length(), input.length() - PARAGRAPH_END.length()); - if (inner.indexOf(PARAGRAPH_BEGIN) < 0) { - return inner; + if (!inner.contains(PARAGRAPH_BEGIN)) { + return inner.trim(); } } return input; |
