aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java')
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java224
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;