diff options
| author | rsudev <rasch@munin-soft.de> | 2013-05-26 17:44:10 +0200 |
|---|---|---|
| committer | rsudev <rasch@munin-soft.de> | 2013-05-26 17:44:10 +0200 |
| commit | 8e2ec9dd830d9c5c370ae8aa77163c22364e47e0 (patch) | |
| tree | 2ed070f00896c636867b01f0c5dadf78ac2a828f /main/src/cgeo/geocaching/connector/oc | |
| parent | ea5cfa107123deaf358bf75a7cf8835fc95acc8f (diff) | |
| download | cgeo-8e2ec9dd830d9c5c370ae8aa77163c22364e47e0.zip cgeo-8e2ec9dd830d9c5c370ae8aa77163c22364e47e0.tar.gz cgeo-8e2ec9dd830d9c5c370ae8aa77163c22364e47e0.tar.bz2 | |
Implements OKAPI access for oc.de
Enable OKAPI for opencaching.de
Enhance OKAPI to allow nearby and livemap searches
Enhance OKAPI to allow posting logs and watchlist changes
Diffstat (limited to 'main/src/cgeo/geocaching/connector/oc')
8 files changed, 597 insertions, 986 deletions
diff --git a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java deleted file mode 100644 index d03062f..0000000 --- a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java +++ /dev/null @@ -1,762 +0,0 @@ -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.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; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.utils.Log; - -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; -import android.sax.RootElement; -import android.sax.StartElementListener; -import android.util.Xml; - -import java.io.IOException; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class OC11XMLParser { - - private static final String[] MARKUP = new String[] { "p", "span" }; - 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 final Pattern WHITESPACE = Pattern.compile("<p>(\\s| )*</p>"); - - - private static ImageHolder imageHolder = null; - - private static class CacheHolder { - public Geocache cache; - public String latitude; - public String longitude; - } - - private static class CacheLog { - public String id; - public String cacheId; - public LogEntry logEntry; - } - - private static class CacheDescription { - public String cacheId; - public String shortDesc; - public String desc; - 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")); - final String strippedDate = STRIP_DATE.matcher(date).replaceAll("+0$100"); - try { - return ISO8601DATEFORMAT.parse(strippedDate); - } catch (ParseException e) { - Log.e("OC11XMLParser.parseFullDate", e); - } - return null; - } - - private static Date parseDayDate(final String date) { - final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US); - ISO8601DATEFORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - final String strippedDate = STRIP_DATE.matcher(date).replaceAll("+0$100"); - try { - return ISO8601DATEFORMAT.parse(strippedDate); - } catch (ParseException e) { - Log.e("OC11XMLParser.parseDayDate", e); - } - return null; - } - - private static CacheSize getCacheSize(final String sizeId) { - try { - int size = Integer.parseInt(sizeId); - - switch (size) { - case 1: - return CacheSize.OTHER; - case 2: - return CacheSize.MICRO; - case 3: - return CacheSize.SMALL; - case 4: - return CacheSize.REGULAR; - case 5: - case 6: - return CacheSize.LARGE; - case 8: - return CacheSize.VIRTUAL; - default: - break; - } - } catch (NumberFormatException e) { - Log.e("OC11XMLParser.getCacheSize", e); - } - return CacheSize.NOT_CHOSEN; - } - - private static CacheType getCacheType(final String typeId) { - try { - int type = Integer.parseInt(typeId); - switch (type) { - case 1: // Other/unbekannter Cachetyp - return CacheType.UNKNOWN; - case 2: // Trad./normaler Cache - return CacheType.TRADITIONAL; - case 3: // Multi/Multicache - return CacheType.MULTI; - case 4: // Virt./virtueller Cache - return CacheType.VIRTUAL; - case 5: // ICam./Webcam-Cache - return CacheType.WEBCAM; - case 6: // Event/Event-Cache - return CacheType.EVENT; - case 7: // Quiz/Rätselcache - return CacheType.MYSTERY; - case 8: // Math/Mathe-/Physikcache - return CacheType.MYSTERY; - case 9: // Moving/beweglicher Cache - return CacheType.VIRTUAL; - case 10: // Driv./Drive-In - return CacheType.TRADITIONAL; - default: - return CacheType.UNKNOWN; - } - } catch (NumberFormatException e) { - Log.e("OC11XMLParser.getCacheType", e); - } - return CacheType.UNKNOWN; - } - - private static LogType getLogType(final int typeId) { - switch (typeId) { - case 1: - return LogType.FOUND_IT; - case 2: - return LogType.DIDNT_FIND_IT; - case 3: - return LogType.NOTE; - case 7: - return LogType.ATTENDED; - case 8: - return LogType.WILL_ATTEND; - default: - return LogType.UNKNOWN; - } - } - - private static void setCacheStatus(final int statusId, final Geocache cache) { - switch (statusId) { - case 1: - cache.setArchived(false); - cache.setDisabled(false); - break; - case 2: - cache.setArchived(false); - cache.setDisabled(true); - break; - default: - cache.setArchived(true); - cache.setDisabled(false); - break; - } - } - - private static void resetCache(final CacheHolder cacheHolder) { - cacheHolder.cache = new Geocache(null); - cacheHolder.cache.setReliableLatLon(true); - cacheHolder.cache.setDescription(StringUtils.EMPTY); - cacheHolder.latitude = "0.0"; - cacheHolder.longitude = "0.0"; - } - - private static void resetLog(final CacheLog log) { - log.cacheId = StringUtils.EMPTY; - log.logEntry = new LogEntry("", 0, LogType.UNKNOWN, ""); - } - - private static void resetDesc(final CacheDescription desc) { - desc.cacheId = StringUtils.EMPTY; - desc.shortDesc = StringUtils.EMPTY; - desc.desc = StringUtils.EMPTY; - desc.hint = StringUtils.EMPTY; - } - - private 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, 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(); - final CacheDescription descHolder = new CacheDescription(); - - final RootElement root = new RootElement("oc11xml"); - final Element cacheNode = root.getChild("cache"); - - final boolean ignoreFilters = ignoreFiltersIn; - - // cache - cacheNode.setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attributes) { - resetCache(cacheHolder); - } - - }); - - cacheNode.setEndElementListener(new EndElementListener() { - - @Override - public void end() { - Geocache cache = cacheHolder.cache; - Geopoint coords = new Geopoint(cacheHolder.latitude, cacheHolder.longitude); - 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 - cacheNode.getChild("id").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - cacheHolder.cache.setCacheId(body); - } - }); - - // cache.longitude - cacheNode.getChild("longitude").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - String longitude = body.trim(); - if (StringUtils.isNotBlank(longitude)) { - cacheHolder.longitude = longitude; - } - } - }); - - // cache.latitude - cacheNode.getChild("latitude").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - String latitude = body.trim(); - if (StringUtils.isNotBlank(latitude)) { - cacheHolder.latitude = latitude; - } - } - }); - - // cache.name - cacheNode.getChild("name").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - final String content = body.trim(); - cacheHolder.cache.setName(content); - } - }); - - // cache.waypoints[oc] - cacheNode.getChild("waypoints").setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attrs) { - if (attrs.getIndex("oc") > -1) { - cacheHolder.cache.setGeocode(attrs.getValue("oc")); - } - if (attrs.getIndex("gccom") > -1) { - String gccode = attrs.getValue("gccom"); - if (!StringUtils.isBlank(gccode)) { - cacheHolder.cache.setDescription(res.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()) + ": <a href=\"http://coord.info/" + gccode + "\">" + gccode + "</a><br /><br />"); - } - } - } - }); - - // cache.type[id] - cacheNode.getChild("type").setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attrs) { - if (attrs.getIndex("id") > -1) { - final String typeId = attrs.getValue("id"); - cacheHolder.cache.setType(getCacheType(typeId)); - } - } - }); - - // cache.status[id] - cacheNode.getChild("status").setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attrs) { - if (attrs.getIndex("id") > -1) { - try { - final int statusId = Integer.parseInt(attrs.getValue("id")); - setCacheStatus(statusId, cacheHolder.cache); - } catch (NumberFormatException e) { - Log.w(String.format("Failed to parse status of cache '%s'.", cacheHolder.cache.getGeocode())); - } - } - } - }); - - // cache.size[id] - cacheNode.getChild("size").setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attrs) { - if (attrs.getIndex("id") > -1) { - final String typeId = attrs.getValue("id"); - cacheHolder.cache.setSize(getCacheSize(typeId)); - } - } - }); - - // cache.difficulty - cacheNode.getChild("difficulty").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - final String content = body.trim(); - try { - cacheHolder.cache.setDifficulty(Float.valueOf(content)); - } catch (NumberFormatException e) { - Log.e("OC11XMLParser: unknown difficulty " + content, e); - } - } - }); - - // cache.terrain - cacheNode.getChild("terrain").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - final String content = body.trim(); - try { - cacheHolder.cache.setTerrain(Float.valueOf(content)); - } catch (NumberFormatException e) { - Log.e("OC11XMLParser: unknown terrain " + content, e); - } - } - }); - - // cache.datehidden - cacheNode.getChild("datehidden").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - final String content = body.trim(); - cacheHolder.cache.setHidden(parseFullDate(content)); - } - }); - - // 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 - 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) { - 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()); - } - } - } - }); - - // cachedesc - final Element cacheDesc = root.getChild("cachedesc"); - - cacheDesc.setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attributes) { - resetDesc(descHolder); - } - }); - - cacheDesc.setEndElementListener(new EndElementListener() { - - @Override - public void end() { - final Geocache cache = caches.get(descHolder.cacheId); - if (cache != null) { - cache.setShortDescription(descHolder.shortDesc); - cache.setDescription(cache.getDescription() + descHolder.desc); - cache.setHint(descHolder.hint); - } - } - }); - - // cachedesc.cacheid - cacheDesc.getChild("cacheid").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - descHolder.cacheId = body; - } - }); - - // cachedesc.desc - cacheDesc.getChild("shortdesc").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - final String content = body.trim(); - descHolder.shortDesc = linkify(stripEmptyText(content)); - } - }); - - // cachedesc.desc - cacheDesc.getChild("desc").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - final String content = body.trim(); - descHolder.desc = linkify(stripEmptyText(content)); - } - }); - - // cachedesc.hint - cacheDesc.getChild("hint").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - descHolder.hint = body.trim(); - } - }); - - // cachelog - final Element cacheLog = root.getChild("cachelog"); - - cacheLog.setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attrs) { - resetLog(logHolder); - } - }); - - cacheLog.setEndElementListener(new EndElementListener() { - - @Override - public void end() { - final Geocache cache = caches.get(logHolder.cacheId); - if (cache != null && logHolder.logEntry.type != LogType.UNKNOWN) { - 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); - } - } - } - }); - - // 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() { - - @Override - public void end(String body) { - logHolder.cacheId = body; - } - }); - - // cachelog.date - cacheLog.getChild("date").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String body) { - try { - logHolder.logEntry.date = parseDayDate(body).getTime(); - } catch (NullPointerException e) { - Log.w("Failed to parse log date", e); - } - } - }); - - // cachelog.logtype - cacheLog.getChild("logtype").setStartElementListener(new StartElementListener() { - - @Override - public void start(Attributes attrs) { - if (attrs.getIndex("id") > -1) { - final String id = attrs.getValue("id"); - try { - final int typeId = Integer.parseInt(id); - logHolder.logEntry.type = getLogType(typeId); - } catch (NumberFormatException e) { - Log.e("OC11XMLParser, unknown logtype " + id, e); - } - } - } - }); - - // cachelog.userid - cacheLog.getChild("userid").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String finderName) { - logHolder.logEntry.author = finderName; - } - }); - - // cachelog.text - cacheLog.getChild("text").setEndTextElementListener(new EndTextElementListener() { - - @Override - public void end(String logText) { - logHolder.logEntry.log = stripEmptyText(logText); - } - }); - - // 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(); - } catch (SAXException e) { - Log.e("Cannot parse .gpx file as oc11xml: could not parse XML", e); - return null; - } - } - - /** - * 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); - while (matcher.find()) { - String url = matcher.group(1); - if (!url.contains(":/")) { - IConnector ocConnector = ConnectorFactory.getConnector("OCXXX"); - String prefix = "http://" + ocConnector.getHost() + "/"; - result = StringUtils.replace(result, url, prefix + url); - matcher = LOCAL_URL.matcher(result); - } - } - return result; - } - - /** - * Removes some unneeded markup and whitespace. Log texts are typically encapsulated in paragraph tags which lead to - * more empty space on rendering. - */ - protected static String stripEmptyText(String input) { - final Matcher matcher = WHITESPACE.matcher(input); - String result = matcher.replaceAll("").trim(); - if (!StringUtils.startsWith(result, "<")) { - return result; - } - return stripMarkup(result); - } - - private static String stripMarkup(final String input) { - String result = input; - for (String tagName : MARKUP) { - final String startTag = "<" + tagName + ">"; - if (StringUtils.startsWith(result, startTag)) { - final String endTag = "</" + tagName + ">"; - if (StringUtils.endsWith(result, endTag)) { - String inner = result.substring(startTag.length(), result.length() - endTag.length()).trim(); - String nested = stripMarkup(inner); - if (!nested.contains(startTag)) { - result = nested; - } - } - } - } - return result; - } -}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java index 69cf8a4..a236a0e 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java @@ -23,7 +23,7 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { @Override public String getLicenseText(final Geocache cache) { // NOT TO BE TRANSLATED - return "<a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons BY-SA 3.0 License"; + return "©" + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, CC-BY-NC-ND, alle Logeinträge © jeweiliger Autor"; } @Override @@ -40,4 +40,8 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { // currently always active, but only for details download return true; } + + public String getCK() { + return CryptUtils.rot13(cK); + } } diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java new file mode 100644 index 0000000..a578aac --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java @@ -0,0 +1,78 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.cgData; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.connector.ILoggingManager; +import cgeo.geocaching.connector.capability.ISearchByCenter; +import cgeo.geocaching.connector.capability.ISearchByViewPort; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.utils.CryptUtils; + +import android.app.Activity; + +public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort { + + private String cS; + + public OCApiLiveConnector(String name, String host, String prefix, int cKResId, int cSResId) { + super(name, host, prefix, CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cKResId))); + + cS = CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cSResId)); + } + + @Override + public SearchResult searchByViewport(Viewport viewport, String[] tokens) { + return new SearchResult(OkapiClient.getCachesBBox(viewport, this)); + } + + @Override + public SearchResult searchByCenter(Geopoint center) { + + return new SearchResult(OkapiClient.getCachesAround(center, this)); + } + + public String getCS() { + return CryptUtils.rot13(cS); + } + + @Override + public boolean supportsWatchList() { + return true; + } + + @Override + public boolean addToWatchlist(Geocache cache) { + final boolean added = OkapiClient.setWatchState(cache, true, this); + + if (added) { + cgData.saveChangedCache(cache); + } + + return added; + } + + @Override + public boolean removeFromWatchlist(Geocache cache) { + final boolean removed = OkapiClient.setWatchState(cache, false, this); + + if (removed) { + cgData.saveChangedCache(cache); + } + + return removed; + } + + @Override + public boolean supportsLogging() { + return true; + } + + @Override + public ILoggingManager getLoggingManager(Activity activity, Geocache cache) { + return new OkapiLoggingManager(activity, this, cache); + } + +} diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java new file mode 100644 index 0000000..779c1c5 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java @@ -0,0 +1,109 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.R; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.network.OAuthAuthorizationActivity; + +import org.apache.commons.lang3.tuple.ImmutablePair; + +public class OCAuthorizationActivity extends OAuthAuthorizationActivity { + + private final int siteResId = R.string.auth_ocde; + + public OCAuthorizationActivity() { + super("www.opencaching.de", + "/okapi/services/oauth/request_token", + "/okapi/services/oauth/authorize", + "/okapi/services/oauth/access_token", + false, + cgeoapplication.getInstance().getResources().getString(R.string.oc_de_okapi_consumer_key), + cgeoapplication.getInstance().getResources().getString(R.string.oc_de_okapi_consumer_secret)); + } + + @Override + protected ImmutablePair<String, String> getTempToken() { + return Settings.getTempOCDEToken(); + } + + @Override + protected void setTempTokens(String tokenPublic, String tokenSecret) { + Settings.setOCDETempTokens(tokenPublic, tokenSecret); + } + + @Override + protected void setTokens(String tokenPublic, String tokenSecret, boolean enable) { + Settings.setOCDETokens(tokenPublic, tokenSecret, enable); + } + + @Override + protected String getAuthTitle() { + return res.getString(siteResId); + } + + @Override + protected String getAuthAgain() { + return res.getString(R.string.auth_again_oc); + } + + @Override + protected String getErrAuthInitialize() { + return res.getString(R.string.err_auth_initialize); + } + + @Override + protected String getAuthStart() { + return res.getString(R.string.auth_start_oc); + } + + @Override + protected String getAuthDialogCompleted() { + return res.getString(R.string.auth_dialog_completed_oc, getAuthTitle()); + } + + @Override + protected String getErrAuthProcess() { + return res.getString(R.string.err_auth_process); + } + + @Override + protected String getAuthDialogWait() { + return res.getString(R.string.auth_dialog_wait_oc, getAuthTitle()); + } + + @Override + protected String getAuthDialogPinTitle() { + return res.getString(R.string.auth_dialog_pin_title_oc); + } + + @Override + protected String getAuthDialogPinMessage() { + return res.getString(R.string.auth_dialog_pin_message_oc, getAuthTitle()); + } + + @Override + protected String getAboutAuth1() { + return res.getString(R.string.about_auth_1_oc, getAuthTitle()); + } + + @Override + protected String getAboutAuth2() { + return res.getString(R.string.about_auth_2_oc, getAuthTitle(), getAuthTitle()); + } + + @Override + protected String getAuthAuthorize() { + return res.getString(R.string.auth_authorize_oc); + } + + @Override + protected String getAuthPinHint() { + return res.getString(R.string.auth_pin_hint_oc, getAuthTitle()); + } + + @Override + protected String getAuthFinish() { + return res.getString(R.string.auth_finish_oc); + } + +} diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java deleted file mode 100644 index 43fdcfc..0000000 --- a/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java +++ /dev/null @@ -1,67 +0,0 @@ -package cgeo.geocaching.connector.oc; - -import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; -import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; -import cgeo.geocaching.connector.capability.ISearchByCenter; -import cgeo.geocaching.connector.capability.ISearchByGeocode; -import cgeo.geocaching.connector.capability.ISearchByViewPort; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; -import cgeo.geocaching.ui.Formatter; -import cgeo.geocaching.utils.CancellableHandler; - -import org.apache.commons.lang3.StringUtils; - -public class OCXMLApiConnector extends OCConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort { - - private final static double SEARCH_DISTANCE_LIMIT = 15.0; - private final static double NEARBY_SEARCH_DISTANCE = 5.0; - - public OCXMLApiConnector(String name, String host, String prefix) { - super(name, host, prefix); - } - - @Override - public SearchResult searchByGeocode(final String geocode, final String guid, CancellableHandler handler) { - final Geocache cache = OCXMLClient.getCache(geocode); - if (cache == null) { - return null; - } - return new SearchResult(cache); - } - - @Override - public SearchResult searchByCenter(final Geopoint center) { - return new SearchResult(OCXMLClient.getCachesAround(center, NEARBY_SEARCH_DISTANCE)); - } - - @Override - public SearchResult searchByViewport(final Viewport viewport, final String[] tokens) { - final Geopoint center = viewport.getCenter(); - double distance = center.distanceTo(viewport.bottomLeft) * 1.15; - if (distance > SEARCH_DISTANCE_LIMIT) { - distance = SEARCH_DISTANCE_LIMIT; - } - return new SearchResult(OCXMLClient.getCachesAround(center, distance)); - } - - @Override - public boolean isActivated() { - // currently only tested and working with oc.de - return Settings.isOCConnectorActive(); - } - - @Override - public boolean isOwner(ICache cache) { - return StringUtils.equalsIgnoreCase(cache.getOwnerDisplayName(), Settings.getOCConnectorUserName()); - } - - @Override - public String getLicenseText(Geocache cache) { - // not to be translated - return "© " + cache.getOwnerDisplayName() + ", " + "<a href=\"" + getCacheUrl(cache) + "\">www.opencaching.de</a>, CC-BY-NC-ND, Stand: " + Formatter.formatFullDate(cache.getUpdated()); - } - -} diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java b/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java deleted file mode 100644 index df75682..0000000 --- a/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java +++ /dev/null @@ -1,122 +0,0 @@ -package cgeo.geocaching.connector.oc; - -import cgeo.geocaching.Geocache; -import cgeo.geocaching.cgData; -import cgeo.geocaching.connector.ConnectorFactory; -import cgeo.geocaching.connector.IConnector; -import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; -import cgeo.geocaching.network.Network; -import cgeo.geocaching.network.Parameters; -import cgeo.geocaching.utils.IOUtils; -import cgeo.geocaching.utils.Log; - -import ch.boye.httpclientandroidlib.HttpResponse; - -import org.apache.commons.lang3.StringUtils; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.Collections; -import java.util.Locale; -import java.util.zip.GZIPInputStream; - -public class OCXMLClient { - - private static final String SERVICE_CACHE = "/xml/ocxml11.php"; - - // Url for single cache requests - // http://www.opencaching.de/xml/ocxml11.php?modifiedsince=20060320000000&user=0&cache=1&cachedesc=1&cachelog=1&picture=1&removedobject=0&session=0&doctype=0&charset=utf-8&wp=OCC9BE - - public static Geocache getCache(final String geoCode) { - try { - final Parameters params = getOCXmlQueryParameters(true, true, true); - params.put("wp", geoCode); - final InputStream data = request(ConnectorFactory.getConnector(geoCode), SERVICE_CACHE, params); - - if (data == null) { - return null; - } - - final BufferedInputStream stream = new BufferedInputStream(new GZIPInputStream(data)); - Collection<Geocache> caches = OC11XMLParser.parseCaches(stream); - if (caches.iterator().hasNext()) { - Geocache cache = caches.iterator().next(); - cgData.saveCache(cache, LoadFlags.SAVE_ALL); - IOUtils.closeQuietly(stream); - return cache; - } - return null; - } catch (IOException e) { - Log.e("Error parsing cache '" + geoCode + "'", e); - return null; - } - } - - public static Collection<Geocache> getCachesAround(final Geopoint center, final double distance) { - try { - final Parameters params = getOCXmlQueryParameters(false, false, false); - params.put("lat", GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center)); - params.put("lon", GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center)); - params.put("distance", String.format(Locale.US, "%f", distance)); - final InputStream data = request(ConnectorFactory.getConnector("OCXXX"), SERVICE_CACHE, params); - - if (data == null) { - return Collections.emptyList(); - } - - final BufferedInputStream stream = new BufferedInputStream(new GZIPInputStream(data)); - final Collection<Geocache> result = OC11XMLParser.parseCachesFiltered(stream); - IOUtils.closeQuietly(stream); - return result; - } catch (IOException e) { - Log.e("Error parsing nearby search result", e); - return Collections.emptyList(); - } - } - - private static InputStream request(final IConnector connector, final String service, final Parameters params) { - if (connector == null) { - return null; - } - if (!(connector instanceof OCXMLApiConnector)) { - return null; - } - - final String host = connector.getHost(); - if (StringUtils.isBlank(host)) { - return null; - } - - final String uri = "http://" + host + service; - HttpResponse resp = Network.getRequest(uri, params); - if (resp != null) { - try { - return resp.getEntity().getContent(); - } catch (IllegalStateException e) { - // fall through and return null - } catch (IOException e) { - // fall through and return null - } - } - return null; - } - - private static Parameters getOCXmlQueryParameters(final boolean withDescription, final boolean withLogs, final boolean withImages) { - return new Parameters("modifiedsince", "20000101000000", - "user", "0", - "cache", "1", - "cachedesc", withDescription ? "1" : "0", - "cachelog", withLogs ? "1" : "0", - "picture", withImages ? "1" : "0", - "removedobject", "0", - "session", "0", - "doctype", "0", - "charset", "utf-8", - "zip", "gzip", - "picturefromcachelog", withImages ? "1" : "0"); - } -} diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index 0673605..3224549 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -3,16 +3,27 @@ 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.Waypoint; import cgeo.geocaching.cgData; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.connector.LogResult; +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.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.enumerations.StatusCode; +import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.OAuth; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.Log; @@ -27,12 +38,36 @@ import android.text.Html; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.EnumSet; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; final public class OkapiClient { + + private static final SimpleDateFormat logDateFormat; + + static { + logDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.US); + logDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + private static final String CACHE_ATTRNAMES = "attrnames"; + private static final String WPT_LOCATION = "location"; + private static final String WPT_DESCRIPTION = "description"; + private static final String WPT_TYPE = "type"; + private static final String WPT_NAME = "name"; + private static final String CACHE_IS_WATCHED = "is_watched"; + private static final String CACHE_WPTS = "alt_wpts"; + private static final String CACHE_STATUS_ARCHIVED = "Archived"; + private static final String CACHE_STATUS_DISABLED = "Temporarily unavailable"; + private static final String CACHE_IS_FOUND = "is_found"; private static final String CACHE_SIZE = "size"; private static final String CACHE_VOTES = "rating_votes"; private static final String CACHE_NOTFOUNDS = "notfounds"; @@ -64,12 +99,22 @@ final public class OkapiClient { private static final String USER_USERNAME = "username"; private static final String SERVICE_CACHE = "/okapi/services/caches/geocache"; - private static final String SERVICE_CACHE_FIELDS = "code|name|location|type|status|owner|founds|notfounds|size|difficulty|terrain|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden"; - private static final String SERVICE_NEAREST = "/okapi/services/caches/search/nearest"; + private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size|is_found"; + private static final String SERVICE_CACHE_FIELDS = SERVICE_CACHE_CORE_FIELDS + "|owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|attribution_note|alt_wpts|is_watched|attrnames|gc_code"; + + private static final String SERVICE_SEARCH_AND_RETRIEVE = "/okapi/services/caches/shortcuts/search_and_retrieve"; + + private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest"; + private static final String METHOD_SEARCH_BBOX = "services/caches/search/bbox"; + private static final String METHOD_RETRIEVE_CACHES = "services/caches/geocaches"; + + private static final String SERVICE_MARK_CACHE = "/okapi/services/caches/mark"; + + private static final String SERVICE_SUBMIT_LOG = "/okapi/services/logs/submit"; public static Geocache getCache(final String geoCode) { - final Parameters params = new Parameters("cache_code", geoCode, "fields", SERVICE_CACHE_FIELDS); + final Parameters params = new Parameters("cache_code", geoCode, "fields", SERVICE_CACHE_FIELDS, "attribution_append", "none"); final JSONObject data = request(ConnectorFactory.getConnector(geoCode), SERVICE_CACHE, params); if (data == null) { @@ -81,30 +126,115 @@ final public class OkapiClient { public static List<Geocache> getCachesAround(final Geopoint center, IConnector connector) { String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + "|" + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center); - final Parameters params = new Parameters("center", centerString); - final JSONObject data = request(connector, SERVICE_NEAREST, params); + final Parameters params = new Parameters("search_method", METHOD_SEARCH_NEAREST); + final Map<String, String> valueMap = new LinkedHashMap<String, String>(); + valueMap.put("center", centerString); + valueMap.put("limit", "20"); + + addFilterParams(valueMap); + + params.add("search_params", new JSONObject(valueMap).toString()); + + addRetrieveParams(params); + + final JSONObject data = request(connector, SERVICE_SEARCH_AND_RETRIEVE, params); if (data == null) { - return null; + return Collections.emptyList(); + } + + return parseCaches(data); + } + + public static List<Geocache> getCachesBBox(final Viewport viewport, IConnector connector) { + + if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) { + return Collections.emptyList(); + } + + String bboxString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.bottomLeft) + + "|" + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.bottomLeft) + + "|" + GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.topRight) + + "|" + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.topRight); + final Parameters params = new Parameters("search_method", METHOD_SEARCH_BBOX); + final Map<String, String> valueMap = new LinkedHashMap<String, String>(); + valueMap.put("bbox", bboxString); + + addFilterParams(valueMap); + + params.add("search_params", new JSONObject(valueMap).toString()); + + addRetrieveParams(params); + + final JSONObject data = request(connector, SERVICE_SEARCH_AND_RETRIEVE, params); + + if (data == null) { + return Collections.emptyList(); } return parseCaches(data); } + public static boolean setWatchState(final Geocache cache, final boolean watched, IConnector connector) { + final Parameters params = new Parameters("cache_code", cache.getGeocode()); + params.add("watched", watched ? "true" : "false"); + + final JSONObject data = request(connector, SERVICE_MARK_CACHE, params); + + if (data == null) { + return false; + } + + cache.setOnWatchlist(watched); + + return true; + } + + public static LogResult postLog(final Geocache cache, LogType logType, Calendar date, String log, IConnector connector) { + final Parameters params = new Parameters("cache_code", cache.getGeocode()); + params.add("logtype", logType.oc_type); + params.add("comment", log); + params.add("comment_format", "plaintext"); + params.add("when", logDateFormat.format(date.getTime())); + if (logType.equals(LogType.NEEDS_MAINTENANCE)) { + params.add("needs_maintenance", "true"); + } + + final JSONObject data = request(connector, SERVICE_SUBMIT_LOG, params); + + if (data == null) { + return new LogResult(StatusCode.LOG_POST_ERROR, ""); + } + + try { + if (data.getBoolean("success")) { + return new LogResult(StatusCode.NO_ERROR, data.getString("log_uuid")); + } + + return new LogResult(StatusCode.LOG_POST_ERROR, ""); + } catch (JSONException e) { + Log.e("OkapiClient.postLog", e); + } + return new LogResult(StatusCode.LOG_POST_ERROR, ""); + } + private static List<Geocache> parseCaches(final JSONObject response) { try { - final JSONArray cachesResponse = response.getJSONArray("results"); + // Check for empty result + final String result = response.getString("results"); + if (StringUtils.isBlank(result) || StringUtils.equals(result, "[]")) { + return Collections.emptyList(); + } + + // Get and iterate result list + final JSONObject cachesResponse = response.getJSONObject("results"); if (cachesResponse != null) { - ArrayList<String> geocodes = new ArrayList<String>(cachesResponse.length()); - for (int i = 0; i < cachesResponse.length(); i++) { - String geocode = cachesResponse.getString(i); - if (StringUtils.isNotBlank(geocode)) { - geocodes.add(geocode); - } - } - List<Geocache> caches = new ArrayList<Geocache>(geocodes.size()); - for (String geocode : geocodes) { - Geocache cache = getCache(geocode); + List<Geocache> caches = new ArrayList<Geocache>(cachesResponse.length()); + @SuppressWarnings("unchecked") + Iterator<String> keys = cachesResponse.keys(); + while (keys.hasNext()) { + String key = keys.next(); + Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key)); if (cache != null) { caches.add(cache); } @@ -112,24 +242,31 @@ final public class OkapiClient { return caches; } } catch (JSONException e) { - Log.e("OkapiClient.parseCaches", e); + Log.e("OkapiClient.parseCachesResult", e); } - return null; + return Collections.emptyList(); + } + + private static Geocache parseSmallCache(final JSONObject response) { + final Geocache cache = new Geocache(); + cache.setReliableLatLon(true); + try { + + parseCoreCache(response, cache); + + cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE)); + } catch (JSONException e) { + Log.e("OkapiClient.parseSmallCache", e); + } + return cache; } private static Geocache parseCache(final JSONObject response) { final Geocache cache = new Geocache(); cache.setReliableLatLon(true); try { - cache.setGeocode(response.getString(CACHE_CODE)); - cache.setName(response.getString(CACHE_NAME)); - // not used: names - setLocation(cache, response.getString(CACHE_LOCATION)); - cache.setType(getCacheType(response.getString(CACHE_TYPE))); - final String status = response.getString(CACHE_STATUS); - cache.setDisabled(status.equalsIgnoreCase("Temporarily unavailable")); - cache.setArchived(status.equalsIgnoreCase("Archived")); + parseCoreCache(response, cache); // not used: url final JSONObject owner = response.getJSONObject(CACHE_OWNER); @@ -137,9 +274,7 @@ final public class OkapiClient { cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS)); cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS)); - cache.setSize(getCacheSize(response)); - cache.setDifficulty((float) response.getDouble(CACHE_DIFFICULTY)); - cache.setTerrain((float) response.getDouble(CACHE_TERRAIN)); + if (!response.isNull(CACHE_RATING)) { cache.setRating((float) response.getDouble(CACHE_RATING)); } @@ -147,8 +282,22 @@ final public class OkapiClient { cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS)); // not used: req_password - cache.setDescription(response.getString(CACHE_DESCRIPTION)); - cache.setHint(Html.fromHtml(response.getString(CACHE_HINT)).toString()); + // Prepend gc-link to description if available + StringBuilder description = new StringBuilder(500); + if (!response.isNull("gc_code")) { + String gccode = response.getString("gc_code"); + description.append(cgeoapplication.getInstance().getResources() + .getString(R.string.cache_listed_on, GCConnector.getInstance().getName())) + .append(": <a href=\"http://coord.info/") + .append(gccode) + .append("\">") + .append(gccode) + .append("</a><br /><br />"); + } + description.append(response.getString(CACHE_DESCRIPTION)); + cache.setDescription(description.toString()); + + cache.setHint(Html.escapeHtml(response.getString(CACHE_HINT))); // not used: hints final JSONArray images = response.getJSONArray(CACHE_IMAGES); @@ -163,9 +312,13 @@ final public class OkapiClient { } } - // not used: attrnames + cache.setAttributes(parseAttributes(response.getJSONArray(CACHE_ATTRNAMES))); cache.setLogs(parseLogs(response.getJSONArray(CACHE_LATEST_LOGS))); cache.setHidden(parseDate(response.getString(CACHE_HIDDEN))); + //TODO: Store license per cache + //cache.setLicense(response.getString("attribution_note")); + cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false); + cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED)); cache.setDetailedUpdatedNow(); // save full detailed caches @@ -176,6 +329,24 @@ final public class OkapiClient { return cache; } + private static void parseCoreCache(final JSONObject response, final Geocache cache) throws JSONException { + cache.setGeocode(response.getString(CACHE_CODE)); + cache.setName(response.getString(CACHE_NAME)); + // not used: names + setLocation(cache, response.getString(CACHE_LOCATION)); + cache.setType(getCacheType(response.getString(CACHE_TYPE))); + + final String status = response.getString(CACHE_STATUS); + cache.setDisabled(status.equalsIgnoreCase(CACHE_STATUS_DISABLED)); + cache.setArchived(status.equalsIgnoreCase(CACHE_STATUS_ARCHIVED)); + + cache.setSize(getCacheSize(response)); + cache.setDifficulty((float) response.getDouble(CACHE_DIFFICULTY)); + cache.setTerrain((float) response.getDouble(CACHE_TERRAIN)); + + cache.setFound(response.getBoolean(CACHE_IS_FOUND)); + } + private static String absoluteUrl(String url, String geocode) { final Uri uri = Uri.parse(url); @@ -214,6 +385,30 @@ final public class OkapiClient { return result; } + private static List<Waypoint> parseWaypoints(JSONArray wptsJson) { + List<Waypoint> result = null; + for (int i = 0; i < wptsJson.length(); i++) { + try { + JSONObject wptResponse = wptsJson.getJSONObject(i); + Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME), + parseWptType(wptResponse.getString(WPT_TYPE)), + false); + wpt.setNote(wptResponse.getString(WPT_DESCRIPTION)); + Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION)); + if (pt != null) { + wpt.setCoords(pt); + } + if (result == null) { + result = new ArrayList<Waypoint>(); + } + result.add(wpt); + } catch (JSONException e) { + Log.e("OkapiClient.parseWaypoints", e); + } + } + return result; + } + private static LogType parseLogType(String logType) { if ("Found it".equalsIgnoreCase(logType)) { return LogType.FOUND_IT; @@ -224,6 +419,31 @@ final public class OkapiClient { return LogType.NOTE; } + private static WaypointType parseWptType(String wptType) { + if ("parking".equalsIgnoreCase(wptType)) { + return WaypointType.PARKING; + } + if ("path".equalsIgnoreCase(wptType)) { + return WaypointType.TRAILHEAD; + } + if ("stage".equalsIgnoreCase(wptType)) { + return WaypointType.STAGE; + } + if ("physical-stage".equalsIgnoreCase(wptType)) { + return WaypointType.STAGE; + } + if ("virtual-stage".equalsIgnoreCase(wptType)) { + return WaypointType.PUZZLE; + } + if ("final".equalsIgnoreCase(wptType)) { + return WaypointType.FINAL; + } + if ("poi".equalsIgnoreCase(wptType)) { + return WaypointType.TRAILHEAD; + } + return WaypointType.WAYPOINT; + } + private static Date parseDate(final String date) { final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault()); final String strippedDate = date.replaceAll("\\+0([0-9]){1}\\:00", "+0$100"); @@ -235,6 +455,36 @@ final public class OkapiClient { return null; } + private static Geopoint parseCoords(final String location) { + final String latitude = StringUtils.substringBefore(location, "|"); + final String longitude = StringUtils.substringAfter(location, "|"); + if (StringUtils.isNotBlank(latitude) && StringUtils.isNotBlank(longitude)) { + return new Geopoint(latitude, longitude); + } + + return null; + } + + private static List<String> parseAttributes(JSONArray nameList) { + + List<String> result = new ArrayList<String>(); + + for (int i = 0; i < nameList.length(); i++) { + try { + String name = nameList.getString(i); + CacheAttribute attr = CacheAttribute.getByOcId(AttributeParser.getOcDeId(name)); + + if (attr != null) { + result.add(attr.rawName); + } + } catch (JSONException e) { + Log.e("OkapiClient.parseAttributes", e); + } + } + + return result; + } + private static void setLocation(final Geocache cache, final String location) { final String latitude = StringUtils.substringBefore(location, "|"); final String longitude = StringUtils.substringAfter(location, "|"); @@ -281,6 +531,18 @@ final public class OkapiClient { if (cacheType.equalsIgnoreCase("Virtual")) { return CacheType.VIRTUAL; } + if (cacheType.equalsIgnoreCase("Event")) { + return CacheType.EVENT; + } + if (cacheType.equalsIgnoreCase("Webcam")) { + return CacheType.WEBCAM; + } + if (cacheType.equalsIgnoreCase("Math/Physics")) { + return CacheType.MYSTERY; + } + if (cacheType.equalsIgnoreCase("Drive-In")) { + return CacheType.TRADITIONAL; + } return CacheType.UNKNOWN; } @@ -297,9 +559,10 @@ final public class OkapiClient { return null; } - ((OCApiConnector) connector).addAuthentication(params); params.add("langpref", getPreferredLanguage()); + OAuth.signOAuth(host, service, "GET", false, params, Settings.getOCDETokenPublic(), Settings.getOCDETokenSecret(), ((OCApiLiveConnector) connector).getCK(), ((OCApiLiveConnector) connector).getCS()); + final String uri = "http://" + host + service; return Network.requestJSON(uri, params); } @@ -311,4 +574,43 @@ final public class OkapiClient { } return "en"; } + + private static void addFilterParams(final Map<String, String> valueMap) { + if (!Settings.isExcludeDisabledCaches()) { + valueMap.put("status", "Available|Temporarily unavailable"); + } + if (Settings.isExcludeMyCaches()) { + valueMap.put("exclude_my_own", "true"); + valueMap.put("found_status", "notfound_only"); + } + if (Settings.getCacheType() != CacheType.ALL) { + valueMap.put("type", getFilterFromType(Settings.getCacheType())); + } + } + + private static void addRetrieveParams(final Parameters params) { + params.add("retr_method", METHOD_RETRIEVE_CACHES); + params.add("retr_params", "{\"fields\": \"" + SERVICE_CACHE_CORE_FIELDS + "\"}"); + params.add("wrap", "true"); + } + + private static String getFilterFromType(CacheType cacheType) { + switch (cacheType) { + case EVENT: + return "Event"; + case MULTI: + return "Multi"; + case MYSTERY: + return "Quiz"; + case TRADITIONAL: + return "Traditional"; + case VIRTUAL: + return "Virtual"; + case WEBCAM: + return "Webcam"; + default: + return ""; + } + } + } diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java new file mode 100644 index 0000000..24c6b79 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java @@ -0,0 +1,69 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.TrackableLog; +import cgeo.geocaching.VisitCacheActivity; +import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.connector.ILoggingManager; +import cgeo.geocaching.connector.ImageResult; +import cgeo.geocaching.connector.LogResult; +import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.enumerations.StatusCode; + +import android.app.Activity; +import android.net.Uri; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; + +public class OkapiLoggingManager implements ILoggingManager { + + private final IConnector connector; + private final Geocache cache; + private VisitCacheActivity activity; + + private final static List<LogType> standardLogTypes = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE, LogType.NEEDS_MAINTENANCE); + private final static List<LogType> eventLogTypes = Arrays.asList(LogType.WILL_ATTEND, LogType.ATTENDED, LogType.NOTE); + + public OkapiLoggingManager(Activity activity, IConnector connector, Geocache cache) { + this.connector = connector; + this.cache = cache; + this.activity = (VisitCacheActivity) activity; + } + + @Override + public void init() { + activity.onLoadFinished(); + } + + @Override + public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) { + return OkapiClient.postLog(cache, logType, date, log, connector); + } + + @Override + public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) { + return new ImageResult(StatusCode.LOG_POST_ERROR, ""); + } + + @Override + public boolean hasLoaderError() { + return false; + } + + @Override + public List<TrackableLog> getTrackables() { + return Collections.emptyList(); + } + + @Override + public List<LogType> getPossibleLogTypes() { + if (cache.isEventCache()) { + return eventLogTypes; + } + + return standardLogTypes; + } +} |
