aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/connector
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/connector')
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java45
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java16
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java15
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java5
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java5
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java12
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java5
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java35
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java5
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java9
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java16
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java90
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java29
-rw-r--r--main/src/cgeo/geocaching/connector/gc/SearchHandler.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java5
-rw-r--r--main/src/cgeo/geocaching/connector/gc/UTFGrid.java16
-rw-r--r--main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java9
-rw-r--r--main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java29
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java27
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java75
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCConnector.java14
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java7
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java2
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java7
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java2
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java129
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiError.java87
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java26
-rw-r--r--main/src/cgeo/geocaching/connector/oc/UserInfo.java18
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java4
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java26
31 files changed, 498 insertions, 274 deletions
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 28ad12b..3ec0580 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -1,12 +1,16 @@
package cgeo.geocaching.connector;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.R;
+import cgeo.geocaching.enumerations.CacheType;
+import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Geopoint;
import org.apache.commons.lang3.StringUtils;
-import android.app.Activity;
+import java.util.ArrayList;
+import java.util.List;
public abstract class AbstractConnector implements IConnector {
@@ -79,7 +83,7 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public ILoggingManager getLoggingManager(Activity activity, Geocache cache) {
+ public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) {
return new NoLoggingManager();
}
@@ -147,4 +151,41 @@ public abstract class AbstractConnector implements IConnector {
}
return R.drawable.marker_other;
}
+
+ @Override
+ public List<LogType> getPossibleLogTypes(Geocache geocache) {
+ final List<LogType> logTypes = new ArrayList<LogType>();
+ if (geocache.isEventCache()) {
+ logTypes.add(LogType.WILL_ATTEND);
+ logTypes.add(LogType.ATTENDED);
+ if (geocache.isOwner()) {
+ logTypes.add(LogType.ANNOUNCEMENT);
+ }
+ } else if (CacheType.WEBCAM == geocache.getType()) {
+ logTypes.add(LogType.WEBCAM_PHOTO_TAKEN);
+ } else {
+ logTypes.add(LogType.FOUND_IT);
+ }
+ if (!geocache.isEventCache()) {
+ logTypes.add(LogType.DIDNT_FIND_IT);
+ }
+ logTypes.add(LogType.NOTE);
+ if (!geocache.isEventCache()) {
+ logTypes.add(LogType.NEEDS_MAINTENANCE);
+ }
+ if (geocache.isOwner()) {
+ logTypes.add(LogType.OWNER_MAINTENANCE);
+ if (geocache.isDisabled()) {
+ logTypes.add(LogType.ENABLE_LISTING);
+ }
+ else {
+ logTypes.add(LogType.TEMP_DISABLE_LISTING);
+ }
+ logTypes.add(LogType.ARCHIVE);
+ }
+ if (!geocache.isArchived() && !geocache.isOwner()) {
+ logTypes.add(LogType.NEEDS_ARCHIVE);
+ }
+ return logTypes;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index 54e3447..3fdc11b 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Trackable;
import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByKeyword;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.oc.OCApiConnector;
@@ -60,6 +61,8 @@ public final class ConnectorFactory {
private static final ISearchByCenter[] searchByCenterConns;
+ private static final ISearchByKeyword[] searchByKeywordConns;
+
static {
final List<ISearchByViewPort> vpConns = new ArrayList<ISearchByViewPort>();
for (final IConnector conn : CONNECTORS) {
@@ -77,6 +80,15 @@ public final class ConnectorFactory {
}
}
searchByCenterConns = centerConns.toArray(new ISearchByCenter[centerConns.size()]);
+
+ final List<ISearchByKeyword> keywordConns = new ArrayList<ISearchByKeyword>();
+ for (final IConnector conn : CONNECTORS) {
+ // GCConnector is handled specially, omit it here!
+ if (conn instanceof ISearchByKeyword && !(conn instanceof GCConnector)) {
+ keywordConns.add((ISearchByKeyword) conn);
+ }
+ }
+ searchByKeywordConns = keywordConns.toArray(new ISearchByKeyword[keywordConns.size()]);
}
public static IConnector[] getConnectors() {
@@ -87,6 +99,10 @@ public final class ConnectorFactory {
return searchByCenterConns;
}
+ public static ISearchByKeyword[] getSearchByKeywordConnectors() {
+ return searchByKeywordConns;
+ }
+
public static ILogin[] getActiveLiveConnectors() {
final List<ILogin> liveConns = new ArrayList<ILogin>();
for (final IConnector conn : CONNECTORS) {
diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java
index 0c175cd..2262e47 100644
--- a/main/src/cgeo/geocaching/connector/IConnector.java
+++ b/main/src/cgeo/geocaching/connector/IConnector.java
@@ -2,9 +2,11 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.ICache;
+import cgeo.geocaching.LogCacheActivity;
+import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Geopoint;
-import android.app.Activity;
+import java.util.List;
public interface IConnector {
/**
@@ -87,7 +89,7 @@ public interface IConnector {
*
* @return
*/
- public ILoggingManager getLoggingManager(Activity activity, Geocache cache);
+ public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache);
/**
* get host name of the connector server for dynamic loading of data
@@ -209,4 +211,13 @@ public interface IConnector {
* Whether to return the enabled or disabled marker type
*/
public int getCacheMapMarkerId(boolean disabled);
+
+ /**
+ * Get the list of <b>potentially</b> possible log types for a cache. Those may still be filter further during the
+ * actual logging activity.
+ *
+ * @param geocache
+ * @return
+ */
+ public List<LogType> getPossibleLogTypes(Geocache geocache);
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
index 3fdd61f..91dd094 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
@@ -1,14 +1,13 @@
package cgeo.geocaching.connector.capability;
import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.geopoint.Geopoint;
/**
* connector capability for online searching caches around a center coordinate, sorted by distance
*
*/
-public interface ISearchByCenter {
+public interface ISearchByCenter extends IConnector {
public SearchResult searchByCenter(final Geopoint center);
-
- public boolean isActivated();
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java b/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
index c3d6bba..4c16049 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByGeocode.java
@@ -1,12 +1,13 @@
package cgeo.geocaching.connector.capability;
import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.utils.CancellableHandler;
/**
* connector capability of searching online for a cache by geocode
- *
+ *
*/
-public interface ISearchByGeocode {
+public interface ISearchByGeocode extends IConnector {
public SearchResult searchByGeocode(final String geocode, final String guid, final CancellableHandler handler);
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java b/main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java
new file mode 100644
index 0000000..09b2423
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByKeyword.java
@@ -0,0 +1,12 @@
+package cgeo.geocaching.connector.capability;
+
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
+
+/**
+ * connector capability of searching online for a cache by name
+ *
+ */
+public interface ISearchByKeyword extends IConnector {
+ public SearchResult searchByName(final String name);
+}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
index f1bd2ce..4954017 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
@@ -1,10 +1,9 @@
package cgeo.geocaching.connector.capability;
import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.geopoint.Viewport;
-public interface ISearchByViewPort {
+public interface ISearchByViewPort extends IConnector {
public SearchResult searchByViewport(final Viewport viewport, final String[] tokens);
-
- public boolean isActivated();
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 8888d6b..d5f7bf4 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -1,11 +1,12 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.ICache;
+import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.AbstractConnector;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.capability.ILogin;
@@ -20,10 +21,9 @@ import cgeo.geocaching.settings.SettingsActivity;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import android.app.Activity;
import android.content.Context;
import android.os.Handler;
@@ -104,7 +104,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public ILoggingManager getLoggingManager(Activity activity, Geocache cache) {
+ public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) {
return new GCLoggingManager(activity, cache);
}
@@ -137,10 +137,10 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
if (StringUtils.isEmpty(page)) {
final SearchResult search = new SearchResult();
- if (cgData.isThere(geocode, guid, true, false)) {
+ if (DataStore.isThere(geocode, guid, true, false)) {
if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(guid)) {
Log.i("Loading old cache from cache.");
- search.addGeocode(cgData.getGeocodeForGuid(guid));
+ search.addGeocode(DataStore.getGeocodeForGuid(guid));
} else {
search.addGeocode(geocode);
}
@@ -152,6 +152,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
search.setError(StatusCode.COMMUNICATION_ERROR);
return search;
}
+ assert page != null;
final SearchResult searchResult = GCParser.parseCache(page, handler);
@@ -189,7 +190,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean addToWatchlist(Geocache cache) {
final boolean added = GCParser.addToWatchlist(cache);
if (added) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return added;
}
@@ -198,7 +199,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean removeFromWatchlist(Geocache cache) {
final boolean removed = GCParser.removeFromWatchlist(cache);
if (removed) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return removed;
}
@@ -215,7 +216,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public static boolean addToFavorites(Geocache cache) {
final boolean added = GCParser.addToFavorites(cache);
if (added) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return added;
}
@@ -232,7 +233,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public static boolean removeFromFavorites(Geocache cache) {
final boolean removed = GCParser.removeFromFavorites(cache);
if (removed) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return removed;
}
@@ -241,7 +242,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
final boolean uploaded = GCParser.uploadModifiedCoordinates(cache, wpt);
if (uploaded) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return uploaded;
}
@@ -250,7 +251,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean deleteModifiedCoordinates(Geocache cache) {
final boolean deleted = GCParser.deleteModifiedCoordinates(cache);
if (deleted) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return deleted;
}
@@ -259,7 +260,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
public boolean uploadPersonalNote(Geocache cache) {
final boolean uploaded = GCParser.uploadPersonalNote(cache);
if (uploaded) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return uploaded;
}
@@ -299,13 +300,13 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
final StatusCode status = Login.login();
if (status == StatusCode.NO_ERROR) {
- cgeoapplication.getInstance().checkLogin = false;
+ CgeoApplication.getInstance().checkLogin = false;
Login.detectGcCustomDate();
}
- if (cgeoapplication.getInstance().showLoginToast && handler != null) {
+ if (CgeoApplication.getInstance().showLoginToast && handler != null) {
handler.sendMessage(handler.obtainMessage(0, status));
- cgeoapplication.getInstance().showLoginToast = false;
+ CgeoApplication.getInstance().showLoginToast = false;
// invoke settings activity to insert login details
if (status == StatusCode.NO_LOGIN_INFO_STORED && fromActivity != null) {
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index 6299616..601bebe 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -135,12 +135,12 @@ public final class GCConstants {
public final static Pattern PATTERN_WPTYPE = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg");
public final static Pattern PATTERN_WPPREFIXORLOOKUPORLATLON = Pattern.compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>");
public final static Pattern PATTERN_WPNAME = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>");
- public final static Pattern PATTERN_WPNOTE = Pattern.compile("colspan=\"6\">(.*)<\\/td>");
+ public final static Pattern PATTERN_WPNOTE = Pattern.compile("colspan=\"6\">(.*)" + Pattern.quote("</td>"), Pattern.DOTALL);
/**
* Patterns for different purposes
*/
- /** replace linebreak and paragraph tags */
+ /** replace line break and paragraph tags */
public final static Pattern PATTERN_LINEBREAK = Pattern.compile("<(br|p)[^>]*>");
public final static Pattern PATTERN_TYPEBOX = Pattern.compile("<select name=\"ctl00\\$ContentBody\\$LogBookPanel1\\$ddLogType\" id=\"ctl00_ContentBody_LogBookPanel1_ddLogType\"[^>]*>"
+ "(([^<]*<option[^>]*>[^<]+</option>)+)[^<]*</select>", Pattern.CASE_INSENSITIVE);
@@ -167,7 +167,6 @@ public final class GCConstants {
public final static String STRING_PREMIUMONLY_2 = "Sorry, the owner of this listing has made it viewable to Premium Members only.";
public final static String STRING_PREMIUMONLY_1 = "has chosen to make this cache listing visible to Premium Members only.";
- public final static String STRING_UNPUBLISHED_OWNER = "cache has not been published yet";
public final static String STRING_UNPUBLISHED_OTHER = "you cannot view this cache listing until it has been published";
public final static String STRING_UNPUBLISHED_FROM_SEARCH = "UnpublishedCacheSearchWidget";
public final static String STRING_UNKNOWN_ERROR = "An Error Has Occurred";
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
index 2aa5c75..8bed2ea 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.connector.gc;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.R;
-import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.connector.ILoggingManager;
@@ -13,12 +12,13 @@ import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.loaders.UrlLoader;
import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.Nullable;
-import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
@@ -38,11 +38,12 @@ public class GCLoggingManager implements ILoggingManager, LoaderManager.LoaderCa
private List<LogType> possibleLogTypes;
private boolean hasLoaderError = true;
- public GCLoggingManager(Activity activity, Geocache cache) {
- this.activity = (LogCacheActivity) activity;
+ public GCLoggingManager(final LogCacheActivity activity, final Geocache cache) {
+ this.activity = activity;
this.cache = cache;
}
+ @Nullable
@Override
public Loader<String> onCreateLoader(int arg0, Bundle arg1) {
if (!Settings.isLogin()) { // allow offline logging
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 4fdde56..e2c7dfa 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy;
@@ -19,7 +19,7 @@ import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.utils.LeastRecentlyUsedMap;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
@@ -236,7 +236,9 @@ public class GCMap {
}
Log.d("Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString());
- } catch (Exception e) {
+ } catch (RuntimeException e) {
+ Log.e("GCMap.parseMapJSON", e);
+ } catch (JSONException e) {
Log.e("GCMap.parseMapJSON", e);
}
@@ -253,7 +255,7 @@ public class GCMap {
* @return
*/
public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
- int speed = (int) cgeoapplication.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h
+ int speed = (int) CgeoApplication.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h
Strategy strategy = Settings.getLiveMapStrategy();
if (strategy == Strategy.AUTO) {
strategy = speed >= 30 ? Strategy.FAST : Strategy.DETAILED;
@@ -359,7 +361,7 @@ public class GCMap {
// Check for vanished found caches
if (tiles.iterator().next().getZoomLevel() >= Tile.ZOOMLEVEL_MIN_PERSONALIZED) {
- searchResult.addFilteredGeocodes(cgData.getCachedMissingFromSearch(searchResult, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1));
+ searchResult.addFilteredGeocodes(DataStore.getCachedMissingFromSearch(searchResult, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1));
}
}
@@ -370,7 +372,7 @@ public class GCMap {
SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null);
if (search != null && !search.isEmpty()) {
final Set<String> geocodes = search.getGeocodes();
- lastSearchViewport = cgData.getBounds(geocodes);
+ lastSearchViewport = DataStore.getBounds(geocodes);
searchResult.addGeocodes(geocodes);
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index b373cb1..bfbcaa4 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.Image;
import cgeo.geocaching.LogEntry;
@@ -8,8 +10,6 @@ import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Trackable;
import cgeo.geocaching.TrackableLog;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -31,15 +31,18 @@ import cgeo.geocaching.ui.DirectionImage;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.SynchronizedDateFormat;
import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.ListUtils;
+
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -49,7 +52,6 @@ import android.text.Html;
import java.io.File;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@@ -61,8 +63,8 @@ import java.util.Locale;
import java.util.Set;
public abstract class GCParser {
- private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
- private final static SimpleDateFormat dateTbIn2 = new SimpleDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009
+ private final static SynchronizedDateFormat dateTbIn1 = new SynchronizedDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
+ private final static SynchronizedDateFormat dateTbIn2 = new SynchronizedDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009
private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha, RecaptchaReceiver thread) {
if (StringUtils.isBlank(pageContent)) {
@@ -147,7 +149,7 @@ public abstract class GCParser {
}
}
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
// failed to parse GUID and/or Disabled
Log.w("GCParser.parseSearch: Failed to parse GUID and/or Disabled data");
}
@@ -308,19 +310,15 @@ public abstract class GCParser {
final String coordinates = Network.getResponseData(Network.postRequest("http://www.geocaching.com/seek/nearest.aspx", params), false);
- if (StringUtils.isNotBlank(coordinates)) {
- if (coordinates.contains("You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com")) {
- Log.i("User has not agreed to the license agreement. Can\'t download .loc file.");
-
- searchResult.setError(StatusCode.UNAPPROVED_LICENSE);
-
- return searchResult;
- }
+ if (StringUtils.contains(coordinates, "You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com")) {
+ Log.i("User has not agreed to the license agreement. Can\'t download .loc file.");
+ searchResult.setError(StatusCode.UNAPPROVED_LICENSE);
+ return searchResult;
}
LocParser.parseLoc(searchResult, coordinates);
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
Log.e("GCParser.parseSearch.CIDs", e);
}
}
@@ -345,7 +343,7 @@ public abstract class GCParser {
static SearchResult parseCache(final String page, final CancellableHandler handler) {
final SearchResult searchResult = parseCacheFromText(page, handler);
- // attention: parseCacheFromText already stores implicitely through searchResult.addCache
+ // attention: parseCacheFromText already stores implicitly through searchResult.addCache
if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
final Geocache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
getExtraOnlineInfo(cache, page, handler);
@@ -357,7 +355,7 @@ public abstract class GCParser {
// save full detailed caches
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_cache);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
// update progress message so user knows we're still working. This is more of a place holder than
// actual indication of what the program is doing
@@ -376,7 +374,7 @@ public abstract class GCParser {
final SearchResult searchResult = new SearchResult();
- if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_OWNER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
+ if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
searchResult.setError(StatusCode.UNPUBLISHED_CACHE);
return searchResult;
}
@@ -569,7 +567,7 @@ public abstract class GCParser {
}
cache.setAttributes(attributes);
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
// failed to parse cache attributes
Log.w("GCParser.parseCache: Failed to parse cache attributes");
}
@@ -598,7 +596,7 @@ public abstract class GCParser {
}
cache.addSpoiler(new Image(url, title, description));
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
// failed to parse cache spoilers
Log.w("GCParser.parseCache: Failed to parse cache spoilers");
}
@@ -632,7 +630,7 @@ public abstract class GCParser {
}
}
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
// failed to parse cache inventory
Log.w("GCParser.parseCache: Failed to parse cache inventory (2)");
}
@@ -654,7 +652,7 @@ public abstract class GCParser {
}
}
}
- } catch (final Exception e) {
+ } catch (final NumberFormatException e) {
// failed to parse logs
Log.w("GCParser.parseCache: Failed to parse cache log count");
}
@@ -667,7 +665,7 @@ public abstract class GCParser {
final String originalCoords = TextUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null);
if (null != originalCoords) {
- final Waypoint waypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
+ final Waypoint waypoint = new Waypoint(CgeoApplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
waypoint.setCoords(new Geopoint(originalCoords));
cache.addOrChangeWaypoint(waypoint, false);
cache.setUserModifiedCoords(true);
@@ -706,7 +704,7 @@ public abstract class GCParser {
// waypoint name
// res is null during the unit tests
- final String name = TextUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, cgeoapplication.getInstance().getString(R.string.waypoint), true);
+ final String name = TextUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, CgeoApplication.getInstance().getString(R.string.waypoint), true);
// waypoint type
final String resulttype = TextUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null);
@@ -719,7 +717,7 @@ public abstract class GCParser {
// waypoint lookup
waypoint.setLookup(TextUtils.getMatch(wp[5], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getLookup(), false));
- // waypoint latitude and logitude
+ // waypoint latitude and longitude
latlon = Html.fromHtml(TextUtils.getMatch(wp[7], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, false, 2, "", false)).toString().trim();
if (!StringUtils.startsWith(latlon, "???")) {
waypoint.setLatlon(latlon);
@@ -847,6 +845,7 @@ public abstract class GCParser {
* @param recaptchaReceiver
* @return
*/
+ @Nullable
private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, RecaptchaReceiver recaptchaReceiver) {
insertCacheType(params, cacheType);
@@ -858,6 +857,7 @@ public abstract class GCParser {
Log.e("GCParser.searchByAny: No data from server");
return null;
}
+ assert page != null;
final SearchResult searchResult = parseSearch(fullUri, page, showCaptcha, recaptchaReceiver);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) {
@@ -944,6 +944,7 @@ public abstract class GCParser {
return null;
}
+ @Nullable
public static Trackable searchTrackable(final String geocode, final String guid, final String id) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) {
Log.w("GCParser.searchTrackable: No geocode nor guid nor id given");
@@ -968,6 +969,7 @@ public abstract class GCParser {
Log.e("GCParser.searchTrackable: No data from server");
return trackable;
}
+ assert page != null;
trackable = parseTrackable(page, geocode);
if (trackable == null) {
@@ -1083,7 +1085,7 @@ public abstract class GCParser {
page = Network.getResponseData(Network.postRequest(uri, params));
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
Log.e("GCParser.postLog.confim", e);
}
@@ -1094,7 +1096,7 @@ public abstract class GCParser {
Log.i("Log successfully posted to cache #" + cacheid);
if (geocode != null) {
- cgData.saveVisitDate(geocode);
+ DataStore.saveVisitDate(geocode);
}
Login.getLoginStatus(page);
@@ -1136,6 +1138,7 @@ public abstract class GCParser {
Log.e("GCParser.uploadLogImage: No data from server");
return new ImmutablePair<StatusCode, String>(StatusCode.UNKNOWN_ERROR, null);
}
+ assert page != null;
final String[] viewstates = Login.getViewstates(page);
@@ -1293,7 +1296,8 @@ public abstract class GCParser {
return !guidOnPage; // on watch list (=error) / not on watch list
}
- static String requestHtmlPage(final String geocode, final String guid, final String log, final String numlogs) {
+ @Nullable
+ static String requestHtmlPage(@Nullable final String geocode, @Nullable final String guid, final String log, final String numlogs) {
final Parameters params = new Parameters("decrypt", "y");
if (StringUtils.isNotBlank(geocode)) {
params.put("wp", geocode);
@@ -1396,7 +1400,7 @@ public abstract class GCParser {
trackable.setOwnerGuid(matcherOwner.group(1));
trackable.setOwner(matcherOwner.group(2).trim());
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
// failed to parse trackable owner name
Log.w("GCParser.parseTrackable: Failed to parse trackable owner name");
}
@@ -1427,7 +1431,7 @@ public abstract class GCParser {
if (TextUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) {
trackable.setSpottedType(Trackable.SPOTTED_OWNER);
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
// failed to parse trackable last known place
Log.w("GCParser.parseTrackable: Failed to parse trackable last known place");
}
@@ -1476,12 +1480,12 @@ public abstract class GCParser {
trackable.setDetails(convertLinks(details));
}
}
- } catch (final Exception e) {
+ } catch (final RuntimeException e) {
// failed to parse trackable details & image
Log.w("GCParser.parseTrackable: Failed to parse trackable details & image");
}
if (StringUtils.isEmpty(trackable.getDetails()) && page.contains(GCConstants.ERROR_TB_NOT_ACTIVATED)) {
- trackable.setDetails(cgeoapplication.getInstance().getString(R.string.trackable_not_activated));
+ trackable.setDetails(CgeoApplication.getInstance().getString(R.string.trackable_not_activated));
}
// trackable logs
@@ -1538,8 +1542,8 @@ public abstract class GCParser {
trackable.setTrackingcode(possibleTrackingcode);
}
- if (cgeoapplication.getInstance() != null) {
- cgData.saveTrackable(trackable);
+ if (CgeoApplication.getInstance() != null) {
+ DataStore.saveTrackable(trackable);
}
return trackable;
@@ -1601,8 +1605,17 @@ public abstract class GCParser {
rawResponse = TextUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, "");
}
+ return parseLogs(friends, rawResponse);
+ }
+
+ private static List<LogEntry> parseLogs(final boolean friends, String rawResponse) {
final List<LogEntry> logs = new ArrayList<LogEntry>();
+ // for non logged in users the log book is not shown
+ if (StringUtils.isBlank(rawResponse)) {
+ return logs;
+ }
+
try {
final JSONObject resp = new JSONObject(rawResponse);
if (!resp.getString("status").equals("success")) {
@@ -1629,7 +1642,7 @@ public abstract class GCParser {
// TODO: we should update our log data structure to be able to record
// proper coordinates, and make them clickable. In the meantime, it is
// better to integrate those coordinates into the text rather than not
- // display them as all.
+ // display them at all.
final String latLon = entry.getString("LatLonString");
final LogEntry logDone = new LogEntry(
entry.getString("UserName"),
@@ -1658,9 +1671,10 @@ public abstract class GCParser {
return logs;
}
+ @NonNull
public static List<LogType> parseTypes(String page) {
if (StringUtils.isEmpty(page)) {
- return ListUtils.EMPTY_LIST;
+ return Collections.emptyList();
}
final List<LogType> types = new ArrayList<LogType>();
diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java
index 0d8fb05..beb49f1 100644
--- a/main/src/cgeo/geocaching/connector/gc/Login.java
+++ b/main/src/cgeo/geocaching/connector/gc/Login.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.network.HtmlImage;
@@ -13,10 +13,11 @@ import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
-
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import android.graphics.drawable.BitmapDrawable;
@@ -76,7 +77,7 @@ public abstract class Login {
return StatusCode.NO_LOGIN_INFO_STORED;
}
- Login.setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_working));
+ Login.setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_working));
HttpResponse loginResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx");
String loginData = Network.getResponseData(loginResponse);
if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) {
@@ -119,6 +120,7 @@ public abstract class Login {
// FIXME: should it be CONNECTION_FAILED to match the first attempt?
return StatusCode.COMMUNICATION_ERROR; // no login page
}
+ assert loginData != null; // Caught above
if (Login.getLoginStatus(loginData)) {
Log.i("Successfully logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')');
@@ -171,7 +173,7 @@ public abstract class Login {
resetLoginStatus();
setActualCachesFound(-1);
- setActualStatus(cgeoapplication.getInstance().getString(R.string.err_login));
+ setActualStatus(CgeoApplication.getInstance().getString(R.string.err_login));
}
static void setActualCachesFound(final int found) {
@@ -212,13 +214,14 @@ public abstract class Login {
* @param page
* @return <code>true</code> if user is logged in, <code>false</code> otherwise
*/
- public static boolean getLoginStatus(final String page) {
+ public static boolean getLoginStatus(@Nullable final String page) {
if (StringUtils.isBlank(page)) {
Log.e("Login.checkLogin: No page given");
return false;
}
+ assert page != null;
- setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_ok));
+ setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_ok));
// on every page except login page
setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME));
@@ -246,7 +249,7 @@ public abstract class Login {
return true;
}
- setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_failed));
+ setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_failed));
return false;
}
@@ -276,7 +279,8 @@ public abstract class Login {
public static BitmapDrawable downloadAvatarAndGetMemberStatus() {
try {
- final String profile = TextUtils.replaceWhitespace(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/")));
+ final String responseData = StringUtils.defaultString(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/")));
+ final String profile = TextUtils.replaceWhitespace(responseData);
Settings.setMemberStatus(TextUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null));
if (profile.contains(GCConstants.MEMBER_STATUS_RENEW)) {
@@ -473,10 +477,13 @@ public abstract class Login {
* @param params
* @return
*/
- public static String getRequestLogged(final String uri, final Parameters params) {
- final String data = Network.getResponseData(Network.getRequest(uri, params), canRemoveWhitespace(uri));
+ @Nullable
+ public static String getRequestLogged(@NonNull final String uri, @Nullable final Parameters params) {
+ final HttpResponse response = Network.getRequest(uri, params);
+ final String data = Network.getResponseData(response, canRemoveWhitespace(uri));
- if (getLoginStatus(data)) {
+ // A page not found will not be found if the user logs in either
+ if (Network.isPageNotFound(response) || getLoginStatus(data)) {
return data;
}
diff --git a/main/src/cgeo/geocaching/connector/gc/SearchHandler.java b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java
index 4358399..795ed2f 100644
--- a/main/src/cgeo/geocaching/connector/gc/SearchHandler.java
+++ b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java
@@ -91,7 +91,7 @@ public class SearchHandler extends Handler {
dlg.create().show();
}
- } catch (Exception e) {
+ } catch (MalformedURLException e) {
Log.e("Error in reCAPTCHA handler", e);
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index 4ed53c9..623730a 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -29,11 +29,6 @@ import java.util.Set;
*/
public class Tile {
- public static final double LATITUDE_MIN = -85.05112878;
- public static final double LATITUDE_MAX = 85.05112878;
- public static final double LONGITUDE_MIN = -180;
- public static final double LONGITUDE_MAX = 180;
-
public static final int TILE_SIZE = 256;
public static final int ZOOMLEVEL_MAX = 18;
public static final int ZOOMLEVEL_MIN = 0;
diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
index 6d20eb6..89a3de8 100644
--- a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
+++ b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
@@ -12,22 +12,6 @@ public final class UTFGrid {
public static final int GRID_MAXX = 63;
public static final int GRID_MAXY = 63;
- /**
- * Convert a value from a JSON grid object into an id that can be used as an index
- * It's not used at the moment due to optimizations.
- * But maybe we need it some day...
- */
- public static short getUTFGridId(final char value) {
- short result = (short) value;
- if (result >= 93) {
- result--;
- }
- if (result >= 35) {
- result--;
- }
- return (short) (result - 32);
- }
-
/** Calculate from a list of positions (x/y) the coords */
public static UTFGridPosition getPositionInGrid(List<UTFGridPosition> positions) {
int minX = GRID_MAXX;
diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
index 5965fff..eff193a 100644
--- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
+++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
@@ -15,9 +15,12 @@ public final class UTFGridPosition {
private final static Pattern PATTERN_JSON_KEY = Pattern.compile("[^\\d]*" + "(\\d+),\\s*(\\d+)" + "[^\\d]*"); // (12, 34)
public UTFGridPosition(final int x, final int y) {
- assert x >= 0 && x <= UTFGrid.GRID_MAXX : "x outside bounds";
- assert y >= 0 && y <= UTFGrid.GRID_MAXY : "y outside bounds";
-
+ if (x < 0 || x > UTFGrid.GRID_MAXX) {
+ throw new IllegalArgumentException("x outside bounds");
+ }
+ if (y < 0 || y > UTFGrid.GRID_MAXY) {
+ throw new IllegalArgumentException("y outside bounds");
+ }
this.x = x;
this.y = y;
}
diff --git a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java
index 5a140a1..dacb626 100644
--- a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java
+++ b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java
@@ -3,58 +3,65 @@ package cgeo.geocaching.connector.oc;
public interface IOCAuthParams {
/**
- * The site name: 'www.openaching...'
- *
+ * The site name: 'www.opencaching...'
+ *
* @return
*/
String getSite();
/**
* ResId of the Consumer key
- *
+ *
* @return
*/
int getCKResId();
/**
* ResId of the Consumer secret
- *
+ *
* @return
*/
int getCSResId();
/**
- * ResId ot the Authorization title
- *
+ * ResId of the Authorization title
+ *
* @return
*/
- int getAuthTitelResId();
+ int getAuthTitleResId();
/**
* Preference key of the public token
- *
+ *
* @return
*/
int getTokenPublicPrefKey();
/**
* Preference key of the secret token
- *
+ *
* @return
*/
int getTokenSecretPrefKey();
/**
* Preference key of the temporary public token (OAuth)
- *
+ *
* @return
*/
int getTempTokenPublicPrefKey();
/**
* Preference key of the temporary secret token (OAuth)
- *
+ *
* @return
*/
int getTempTokenSecretPrefKey();
+
+ /**
+ * The URI to use as a callback (OAuth)
+ *
+ * @return
+ */
+ String getCallbackUri();
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
index d35e54b..b1b9088 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java
@@ -1,12 +1,14 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.LogCacheActivity;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.capability.ILogin;
import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByKeyword;
import cgeo.geocaching.connector.capability.ISearchByViewPort;
import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus;
import cgeo.geocaching.geopoint.Geopoint;
@@ -16,11 +18,10 @@ import cgeo.geocaching.utils.CryptUtils;
import org.apache.commons.lang3.StringUtils;
-import android.app.Activity;
import android.content.Context;
import android.os.Handler;
-public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort, ILogin {
+public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort, ILogin, ISearchByKeyword {
private final String cS;
private final int isActivePrefKeyId;
@@ -29,9 +30,9 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
private UserInfo userInfo = new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.NOT_RETRIEVED);
public OCApiLiveConnector(String name, String host, String prefix, String licenseString, int cKResId, int cSResId, int isActivePrefKeyId, int tokenPublicPrefKeyId, int tokenSecretPrefKeyId, ApiSupport apiSupport) {
- super(name, host, prefix, CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cKResId)), licenseString, apiSupport);
+ super(name, host, prefix, CryptUtils.rot13(CgeoApplication.getInstance().getResources().getString(cKResId)), licenseString, apiSupport);
- cS = CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cSResId));
+ cS = CryptUtils.rot13(CgeoApplication.getInstance().getResources().getString(cSResId));
this.isActivePrefKeyId = isActivePrefKeyId;
this.tokenPublicPrefKeyId = tokenPublicPrefKeyId;
this.tokenSecretPrefKeyId = tokenSecretPrefKeyId;
@@ -87,7 +88,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
final boolean added = OkapiClient.setWatchState(cache, true, this);
if (added) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return added;
@@ -98,7 +99,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
final boolean removed = OkapiClient.setWatchState(cache, false, this);
if (removed) {
- cgData.saveChangedCache(cache);
+ DataStore.saveChangedCache(cache);
}
return removed;
@@ -110,7 +111,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
}
@Override
- public ILoggingManager getLoggingManager(Activity activity, Geocache cache) {
+ public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) {
return new OkapiLoggingManager(activity, this, cache);
}
@@ -145,11 +146,17 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente
@Override
public String getLoginStatusString() {
- return cgeoapplication.getInstance().getString(userInfo.getStatus().resId);
+ return CgeoApplication.getInstance().getString(userInfo.getStatus().resId);
}
@Override
public boolean isLoggedIn() {
return userInfo.getStatus() == UserInfoStatus.SUCCESSFUL;
}
+
+ @Override
+ public SearchResult searchByName(final String name) {
+ final Geopoint currentPos = CgeoApplication.getInstance().currentGeo().getCoords();
+ return new SearchResult(OkapiClient.getCachesNamed(currentPos, name, this));
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
index 10d6a66..c082bac 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java
@@ -1,13 +1,14 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.network.OAuthAuthorizationActivity;
import cgeo.geocaching.settings.Settings;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.Nullable;
-public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
+public abstract class OCAuthorizationActivity extends OAuthAuthorizationActivity {
final IOCAuthParams authParams;
@@ -17,8 +18,9 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
"/okapi/services/oauth/authorize",
"/okapi/services/oauth/access_token",
false,
- cgeoapplication.getInstance().getResources().getString(authParams.getCKResId()),
- cgeoapplication.getInstance().getResources().getString(authParams.getCSResId()));
+ CgeoApplication.getInstance().getResources().getString(authParams.getCKResId()),
+ CgeoApplication.getInstance().getResources().getString(authParams.getCSResId()),
+ authParams.getCallbackUri());
this.authParams = authParams;
}
@@ -28,12 +30,12 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
}
@Override
- protected void setTempTokens(String tokenPublic, String tokenSecret) {
+ protected void setTempTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret) {
Settings.setTokens(authParams.getTempTokenPublicPrefKey(), tokenPublic, authParams.getTempTokenSecretPrefKey(), tokenSecret);
}
@Override
- protected void setTokens(String tokenPublic, String tokenSecret, boolean enable) {
+ protected void setTokens(@Nullable final String tokenPublic, @Nullable final String tokenSecret, final boolean enable) {
Settings.setTokens(authParams.getTokenPublicPrefKey(), tokenPublic, authParams.getTokenSecretPrefKey(), tokenSecret);
if (tokenPublic != null) {
Settings.setTokens(authParams.getTempTokenPublicPrefKey(), null, authParams.getTempTokenSecretPrefKey(), null);
@@ -42,22 +44,7 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
@Override
protected String getAuthTitle() {
- return res.getString(authParams.getAuthTitelResId());
- }
-
- @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);
+ return res.getString(authParams.getAuthTitleResId());
}
@Override
@@ -65,48 +52,4 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity {
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/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
index 29cdd10..b5c62ea 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
@@ -4,7 +4,10 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
import cgeo.geocaching.connector.AbstractConnector;
+import cgeo.geocaching.enumerations.LogType;
+import java.util.Arrays;
+import java.util.List;
import java.util.regex.Pattern;
public class OCConnector extends AbstractConnector {
@@ -14,6 +17,9 @@ public class OCConnector extends AbstractConnector {
private final Pattern codePattern;
private static final Pattern GPX_ZIP_FILE_PATTERN = Pattern.compile("oc[a-z]{2,3}\\d{5,}\\.zip", Pattern.CASE_INSENSITIVE);
+ private static final List<LogType> STANDARD_LOG_TYPES = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE);
+ private static final List<LogType> EVENT_LOG_TYPES = Arrays.asList(LogType.WILL_ATTEND, LogType.ATTENDED, LogType.NOTE);
+
public OCConnector(final String name, final String host, final String prefix) {
this.name = name;
this.host = host;
@@ -66,4 +72,12 @@ public class OCConnector extends AbstractConnector {
return R.drawable.marker_oc;
}
+ @Override
+ public final List<LogType> getPossibleLogTypes(Geocache cache) {
+ if (cache.isEventCache()) {
+ return EVENT_LOG_TYPES;
+ }
+
+ return STANDARD_LOG_TYPES;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java
index 734b383..17c1cb8 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCDEAuthParams.java
@@ -20,7 +20,7 @@ public class OCDEAuthParams implements IOCAuthParams {
}
@Override
- public int getAuthTitelResId() {
+ public int getAuthTitleResId() {
return R.string.auth_ocde;
}
@@ -43,4 +43,9 @@ public class OCDEAuthParams implements IOCAuthParams {
public int getTempTokenSecretPrefKey() {
return R.string.pref_temp_ocde_token_secret;
}
+
+ @Override
+ public String getCallbackUri() {
+ return "callback://www.cgeo.org/opencaching.de/";
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java
index caf114c..1d2aa49 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCDEAuthorizationActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.connector.oc;
-public class OCDEAuthorizationActivity extends OCAuthorizationActivity {
+public final class OCDEAuthorizationActivity extends OCAuthorizationActivity {
public OCDEAuthorizationActivity() {
super(new OCDEAuthParams());
diff --git a/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java
index 117e990..dfe03e5 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCPLAuthParams.java
@@ -20,7 +20,7 @@ public class OCPLAuthParams implements IOCAuthParams {
}
@Override
- public int getAuthTitelResId() {
+ public int getAuthTitleResId() {
return R.string.auth_ocpl;
}
@@ -43,4 +43,9 @@ public class OCPLAuthParams implements IOCAuthParams {
public int getTempTokenSecretPrefKey() {
return R.string.pref_temp_ocpl_token_secret;
}
+
+ @Override
+ public String getCallbackUri() {
+ return "callback://www.cgeo.org/opencaching.pl/";
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java
index 4f9ef96..30ea150 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCPLAuthorizationActivity.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.connector.oc;
-public class OCPLAuthorizationActivity extends OCAuthorizationActivity {
+public final class OCPLAuthorizationActivity extends OCAuthorizationActivity {
public OCPLAuthorizationActivity() {
super(new OCPLAuthParams());
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 43ea8ad..686e314 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -1,12 +1,12 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.Image;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
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;
@@ -29,9 +29,15 @@ import cgeo.geocaching.network.OAuth;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.SynchronizedDateFormat;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -39,7 +45,6 @@ import org.json.JSONObject;
import android.net.Uri;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@@ -56,12 +61,8 @@ final class OkapiClient {
private static final char SEPARATOR = '|';
private static final String SEPARATOR_STRING = Character.toString(SEPARATOR);
- private static final SimpleDateFormat LOG_DATE_FORMAT;
- static {
- LOG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.US);
- LOG_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
- private static final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
+ private static final FastDateFormat LOG_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"), Locale.US);
+ private static final SynchronizedDateFormat ISO8601DATEFORMAT = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
private static final String CACHE_ATTRNAMES = "attrnames";
private static final String WPT_LOCATION = "location";
@@ -81,7 +82,6 @@ final class OkapiClient {
private static final String CACHE_LATEST_LOGS = "latest_logs";
private static final String CACHE_IMAGE_URL = "url";
private static final String CACHE_IMAGE_CAPTION = "caption";
- private static final String CACHE_IMAGE_IS_SPOILER = "is_spoiler";
private static final String CACHE_IMAGES = "images";
private static final String CACHE_HINT = "hint";
private static final String CACHE_DESCRIPTION = "description";
@@ -110,14 +110,15 @@ final class OkapiClient {
// the several realms of possible fields for cache retrieval:
// Core: for livemap requests (L3 - only with level 3 auth)
// Additional: additional fields for full cache (L3 - only for level 3 auth, current - only for connectors with current api)
- private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size";
+ private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size|date_hidden";
private static final String SERVICE_CACHE_CORE_L3_FIELDS = "is_found";
- private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|alt_wpts|attrnames|req_passwd";
+ private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|alt_wpts|attrnames|req_passwd";
private static final String SERVICE_CACHE_ADDITIONAL_CURRENT_FIELDS = "gc_code|attribution_note";
private static final String SERVICE_CACHE_ADDITIONAL_L3_FIELDS = "is_watched|my_notes";
- private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest";
+ private static final String METHOD_SEARCH_ALL = "services/caches/search/all";
private static final String METHOD_SEARCH_BBOX = "services/caches/search/bbox";
+ private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest";
private static final String METHOD_RETRIEVE_CACHES = "services/caches/geocaches";
public static Geocache getCache(final String geoCode) {
@@ -132,13 +133,9 @@ final class OkapiClient {
params.add("fields", getFullFields(ocapiConn));
params.add("attribution_append", "none");
- final JSONObject data = request(ocapiConn, OkapiService.SERVICE_CACHE, params);
-
- if (data == null) {
- return null;
- }
+ final JSONResult result = request(ocapiConn, OkapiService.SERVICE_CACHE, params);
- return parseCache(data);
+ return result.isSuccess ? parseCache(result.data) : null;
}
public static List<Geocache> getCachesAround(final Geopoint center, final OCApiConnector connector) {
@@ -152,12 +149,38 @@ final class OkapiClient {
return requestCaches(connector, params, valueMap);
}
+ public static List<Geocache> getCachesNamed(final Geopoint center, final String namePart, final OCApiConnector connector) {
+ final Map<String, String> valueMap = new LinkedHashMap<String, String>();
+ final Parameters params;
+
+ // search around current position, if there is a position
+ if (center != null) {
+ final String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center);
+ params = new Parameters("search_method", METHOD_SEARCH_NEAREST);
+ valueMap.put("center", centerString);
+ valueMap.put("limit", "20");
+ }
+ else {
+ params = new Parameters("search_method", METHOD_SEARCH_ALL);
+ valueMap.put("limit", "20");
+ }
+
+ // full wildcard search, maybe we need to change this after some testing and evaluation
+ valueMap.put("name", "*" + namePart + "*");
+ return requestCaches(connector, params, valueMap);
+ }
+
private static List<Geocache> requestCaches(final OCApiConnector connector, final Parameters params, final Map<String, String> valueMap) {
+ // if a global type filter is set, and OKAPI does not know that type, then return an empty list instead of all caches
+ if (Settings.getCacheType() != CacheType.ALL && StringUtils.isBlank(getFilterFromType())) {
+ return Collections.emptyList();
+ }
+
addFilterParams(valueMap, connector);
params.add("search_params", new JSONObject(valueMap).toString());
addRetrieveParams(params, connector);
- final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params);
+ final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data;
if (data == null) {
return Collections.emptyList();
@@ -166,7 +189,9 @@ final class OkapiClient {
return parseCaches(data);
}
- // Assumes level 3 OAuth
+ /**
+ * Assumes level 3 OAuth.
+ */
public static List<Geocache> getCachesBBox(final Viewport viewport, final OCApiConnector connector) {
if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) {
@@ -188,7 +213,7 @@ final class OkapiClient {
final Parameters params = new Parameters("cache_code", cache.getGeocode());
params.add("watched", watched ? "true" : "false");
- final JSONObject data = request(connector, OkapiService.SERVICE_MARK_CACHE, params);
+ final JSONObject data = request(connector, OkapiService.SERVICE_MARK_CACHE, params).data;
if (data == null) {
return false;
@@ -212,7 +237,7 @@ final class OkapiClient {
params.add("password", logPassword);
}
- final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params);
+ final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data;
if (data == null) {
return new LogResult(StatusCode.LOG_POST_ERROR, "");
@@ -265,7 +290,7 @@ final class OkapiClient {
parseCoreCache(response, cache);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
} catch (final JSONException e) {
Log.e("OkapiClient.parseSmallCache", e);
}
@@ -297,7 +322,7 @@ final class OkapiClient {
final StringBuilder description = new StringBuilder(500);
if (!response.isNull("gc_code")) {
final String gccode = response.getString("gc_code");
- description.append(cgeoapplication.getInstance().getResources()
+ description.append(CgeoApplication.getInstance().getResources()
.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()))
.append(": <a href=\"http://coord.info/")
.append(gccode)
@@ -318,13 +343,13 @@ final class OkapiClient {
final JSONObject imageResponse = images.getJSONObject(i);
final String title = imageResponse.getString(CACHE_IMAGE_CAPTION);
final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode());
+ // all images are added as spoiler images, although OKAPI has spoiler and non spoiler images
cache.addSpoiler(new Image(url, title));
}
}
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);
@@ -338,7 +363,7 @@ final class OkapiClient {
cache.setDetailedUpdatedNow();
// save full detailed caches
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
} catch (final JSONException e) {
Log.e("OkapiClient.parseCache", e);
}
@@ -363,6 +388,7 @@ final class OkapiClient {
if (!response.isNull(CACHE_IS_FOUND)) {
cache.setFound(response.getBoolean(CACHE_IS_FOUND));
}
+ cache.setHidden(parseDate(response.getString(CACHE_HIDDEN)));
}
private static String absoluteUrl(final String url, final String geocode) {
@@ -597,14 +623,15 @@ final class OkapiClient {
return res.toString();
}
- private static JSONObject request(final OCApiConnector connector, final OkapiService service, final Parameters params) {
+ @NonNull
+ private static JSONResult request(final OCApiConnector connector, final OkapiService service, final Parameters params) {
if (connector == null) {
- return null;
+ return new JSONResult(null);
}
final String host = connector.getHost();
if (StringUtils.isBlank(host)) {
- return null;
+ return new JSONResult(null);
}
params.add("langpref", getPreferredLanguage());
@@ -617,7 +644,7 @@ final class OkapiClient {
}
final String uri = "http://" + host + service.methodName;
- return Network.requestJSON(uri, params);
+ return new JSONResult(Network.getRequest(uri, params));
}
private static String getPreferredLanguage() {
@@ -637,7 +664,7 @@ final class OkapiClient {
valueMap.put("found_status", "notfound_only");
}
if (Settings.getCacheType() != CacheType.ALL) {
- valueMap.put("type", getFilterFromType(Settings.getCacheType()));
+ valueMap.put("type", getFilterFromType());
}
}
@@ -647,8 +674,8 @@ final class OkapiClient {
params.add("wrap", "true");
}
- private static String getFilterFromType(final CacheType cacheType) {
- switch (cacheType) {
+ private static String getFilterFromType() {
+ switch (Settings.getCacheType()) {
case EVENT:
return "Event";
case MULTI:
@@ -669,12 +696,16 @@ final class OkapiClient {
public static UserInfo getUserInfo(final OCApiLiveConnector connector) {
final Parameters params = new Parameters("fields", USER_INFO_FIELDS);
- final JSONObject data = request(connector, OkapiService.SERVICE_USER, params);
+ final JSONResult result = request(connector, OkapiService.SERVICE_USER, params);
- if (data == null) {
- return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.FAILED);
+ if (!result.isSuccess) {
+ final OkapiError error = new OkapiError(result.data);
+ Log.e("OkapiClient.getUserInfo: error getting user info: '" + error.getMessage() + "'");
+ return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.getFromOkapiError(error.getResult()));
}
+ JSONObject data = result.data;
+
String name = StringUtils.EMPTY;
boolean successUserName = false;
@@ -702,4 +733,28 @@ final class OkapiClient {
return new UserInfo(name, finds, successUserName && successFinds ? UserInfoStatus.SUCCESSFUL : UserInfoStatus.FAILED);
}
+ /**
+ * Encapsulates response state and content of an HTTP-request that expects a JSON result. <code>isSuccess</code> is
+ * only true, if the response state was success and <code>data</code> is not null.
+ */
+ private static class JSONResult {
+
+ public final boolean isSuccess;
+ public final JSONObject data;
+
+ public JSONResult(final @Nullable HttpResponse response) {
+ boolean isSuccess = Network.isSuccess(response);
+ final String responseData = Network.getResponseDataAlways(response);
+ JSONObject data = null;
+ if (responseData != null) {
+ try {
+ data = new JSONObject(responseData);
+ } catch (final JSONException e) {
+ Log.w("JSONResult", e);
+ }
+ }
+ this.data = data;
+ this.isSuccess = isSuccess && data != null;
+ }
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiError.java b/main/src/cgeo/geocaching/connector/oc/OkapiError.java
new file mode 100644
index 0000000..7faf2c7
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiError.java
@@ -0,0 +1,87 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Handles the JSON error response from OKAPI
+ */
+public class OkapiError {
+
+ /**
+ * List of detected errors OKAPI might return
+ */
+ public enum OkapiErrors {
+ NO_ERROR,
+ UNSPECIFIED,
+ INVALID_TIMESTAMP,
+ INVALID_TOKEN;
+ }
+
+ @NonNull private final OkapiErrors state;
+ @NonNull private final String message;
+
+ public OkapiError(@Nullable JSONObject data) {
+
+ // A null-response is by definition an error (some exception occurred somewhere in the flow)
+ if (data == null) {
+ state = OkapiErrors.UNSPECIFIED;
+ message = StringUtils.EMPTY;
+ return;
+ }
+ // Second possibility: we get an error object as return (@see http://opencaching.pl/okapi/introduction.html#errors)
+ if (data.has("error")) {
+ String localmessage = null;
+ OkapiErrors localstate = OkapiErrors.UNSPECIFIED;
+ try {
+ JSONObject error = data.getJSONObject("error");
+ // Check reason_stack element to look for the specific oauth problems we want to report back
+ if (error.has("reason_stack")) {
+ String reason = error.getString("reason_stack");
+ if (StringUtils.contains(reason, "invalid_oauth_request")) {
+ if (StringUtils.contains(reason, "invalid_timestamp")) {
+ localstate = OkapiErrors.INVALID_TIMESTAMP;
+ } else if (StringUtils.contains(reason, "invalid_token")) {
+ localstate = OkapiErrors.INVALID_TOKEN;
+ }
+ }
+ }
+ // Check if we can extract a message as well
+ if (error.has("developer_message")) {
+ localmessage = error.getString("developer_message");
+ assert localmessage != null; // by virtue of defaultString
+ }
+ } catch (JSONException ex) {
+ Log.d("OkapiError: Failed to parse JSON", ex);
+ localstate = OkapiErrors.UNSPECIFIED;
+ }
+ state = localstate;
+ message = StringUtils.defaultString(localmessage);
+ return;
+ }
+
+ // Third possibility: some other response, everything is fine!
+ state = OkapiErrors.NO_ERROR;
+ message = StringUtils.EMPTY;
+ }
+
+ public boolean isError() {
+ return state != OkapiErrors.NO_ERROR;
+ }
+
+ @NonNull
+ public OkapiErrors getResult() {
+ return state;
+ }
+
+ @NonNull
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
index c995975..c6be3cb 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java
@@ -9,10 +9,8 @@ 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;
@@ -23,48 +21,42 @@ public class OkapiLoggingManager implements ILoggingManager {
private final Geocache cache;
private LogCacheActivity activity;
- private final static List<LogType> standardLogTypes = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE);
- private final static List<LogType> eventLogTypes = Arrays.asList(LogType.WILL_ATTEND, LogType.ATTENDED, LogType.NOTE);
-
- public OkapiLoggingManager(Activity activity, OCApiLiveConnector connector, Geocache cache) {
+ public OkapiLoggingManager(final LogCacheActivity activity, final OCApiLiveConnector connector, final Geocache cache) {
this.connector = connector;
this.cache = cache;
- this.activity = (LogCacheActivity) activity;
+ this.activity = activity;
}
@Override
- public void init() {
+ public final void init() {
activity.onLoadFinished();
}
@Override
- public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) {
+ public final LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) {
final LogResult result = OkapiClient.postLog(cache, logType, date, log, logPassword, connector);
connector.login(null, null);
return result;
}
@Override
- public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) {
+ public final ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) {
return new ImageResult(StatusCode.LOG_POST_ERROR, "");
}
@Override
- public boolean hasLoaderError() {
+ public final boolean hasLoaderError() {
return false;
}
@Override
- public List<TrackableLog> getTrackables() {
+ public final List<TrackableLog> getTrackables() {
return Collections.emptyList();
}
@Override
public List<LogType> getPossibleLogTypes() {
- if (cache.isEventCache()) {
- return eventLogTypes;
- }
-
- return standardLogTypes;
+ return connector.getPossibleLogTypes(cache);
}
+
}
diff --git a/main/src/cgeo/geocaching/connector/oc/UserInfo.java b/main/src/cgeo/geocaching/connector/oc/UserInfo.java
index 0dc0440..c8b37cd 100644
--- a/main/src/cgeo/geocaching/connector/oc/UserInfo.java
+++ b/main/src/cgeo/geocaching/connector/oc/UserInfo.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector.oc;
import cgeo.geocaching.R;
+import cgeo.geocaching.connector.oc.OkapiError.OkapiErrors;
public class UserInfo {
@@ -8,13 +9,28 @@ public class UserInfo {
NOT_RETRIEVED(R.string.init_login_popup_working),
SUCCESSFUL(R.string.init_login_popup_ok),
FAILED(R.string.init_login_popup_failed),
- NOT_SUPPORTED(R.string.init_login_popup_not_authorized);
+ NOT_SUPPORTED(R.string.init_login_popup_not_authorized),
+ INVALID_TIMESTAMP(R.string.init_login_popup_invalid_timestamp),
+ INVALID_TOKEN(R.string.init_login_popup_invalid_token);
public final int resId;
UserInfoStatus(int resId) {
this.resId = resId;
}
+
+ public static UserInfoStatus getFromOkapiError(OkapiErrors result) {
+ switch (result) {
+ case NO_ERROR:
+ return SUCCESSFUL;
+ case INVALID_TIMESTAMP:
+ return INVALID_TIMESTAMP;
+ case INVALID_TOKEN:
+ return INVALID_TOKEN;
+ default:
+ return FAILED;
+ }
+ }
}
private final String name;
diff --git a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
index f25e289..9d1dfc7 100644
--- a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
+++ b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.connector.ox;
import cgeo.geocaching.Geocache;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.CryptUtils;
@@ -11,7 +11,7 @@ import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import java.util.Collection;
import java.util.Collections;
diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
index 66ca5f7..67180b3 100644
--- a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
+++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.connector.trackable;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.Trackable;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.Log;
import org.xml.sax.Attributes;
@@ -35,15 +35,23 @@ public class GeokretyParser {
@Override
public void start(Attributes attributes) {
try {
- if (attributes.getIndex("id") > -1) {
+ final int indexId = attributes.getIndex("id");
+ if (indexId > -1) {
trackable.setGeocode(geocode(Integer.valueOf(attributes.getValue("id"))));
}
- if (attributes.getIndex("dist") > -1) {
+ final int indexDist = attributes.getIndex("dist");
+ if (indexDist > -1) {
trackable.setDistance(Float.valueOf(attributes.getValue("dist")));
}
- if (attributes.getIndex("type") > -1) {
+ final int indexType = attributes.getIndex("type");
+ if (indexType > -1) {
trackable.setType(getType(Integer.valueOf(attributes.getValue("type"))));
}
+ final int indexWaypoint = attributes.getIndex("waypoint");
+ if (indexWaypoint > -1) {
+ trackable.setSpottedName(attributes.getValue(indexWaypoint));
+ trackable.setSpottedType(Trackable.SPOTTED_CACHE);
+ }
} catch (final NumberFormatException e) {
Log.e("Parsing geokret", e);
}
@@ -63,15 +71,15 @@ public class GeokretyParser {
protected static String getType(int type) {
switch (type) {
case 0:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_traditional);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_traditional);
case 1:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_book_or_media);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_book_or_media);
case 2:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_human);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_human);
case 3:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_coin);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_coin);
case 4:
- return cgeoapplication.getInstance().getString(R.string.geokret_type_post);
+ return CgeoApplication.getInstance().getString(R.string.geokret_type_post);
}
return null;
}