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.java6
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ILogin.java5
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECApi.java51
-rw-r--r--main/src/cgeo/geocaching/connector/ec/ECLogin.java20
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java5
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java1
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLogin.java7
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java103
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java295
-rw-r--r--main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java6
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java52
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiConnector.java13
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java296
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiError.java14
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java6
15 files changed, 427 insertions, 453 deletions
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 9729e06..a929e2b 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -105,9 +105,9 @@ public abstract class AbstractConnector implements IConnector {
return null;
}
- protected static boolean isNumericId(final String string) {
+ protected static boolean isNumericId(final String str) {
try {
- return Integer.parseInt(string) > 0;
+ return Integer.parseInt(str) > 0;
} catch (NumberFormatException e) {
}
return false;
@@ -295,4 +295,6 @@ public abstract class AbstractConnector implements IConnector {
return actions;
}
+ public void logout() {
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ILogin.java b/main/src/cgeo/geocaching/connector/capability/ILogin.java
index 4a839c8..b8b4975 100644
--- a/main/src/cgeo/geocaching/connector/capability/ILogin.java
+++ b/main/src/cgeo/geocaching/connector/capability/ILogin.java
@@ -23,6 +23,11 @@ public interface ILogin extends IConnector {
boolean login(Handler handler, Context fromActivity);
/**
+ * Log out of the connector if possible.
+ */
+ void logout();
+
+ /**
* Returns the status of the last {@link}login() request
*
* @return
diff --git a/main/src/cgeo/geocaching/connector/ec/ECApi.java b/main/src/cgeo/geocaching/connector/ec/ECApi.java
index 421d112..3e7472e 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECApi.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECApi.java
@@ -14,17 +14,18 @@ import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.utils.JsonUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.SynchronizedDateFormat;
import ch.boye.httpclientandroidlib.HttpResponse;
+import com.fasterxml.jackson.databind.JsonNode;
+
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
@@ -161,7 +162,7 @@ public class ECApi {
}
try {
- return new GPX10Parser(StoredList.TEMPORARY_LIST_ID).parse(response.getEntity().getContent(), null);
+ return new GPX10Parser(StoredList.TEMPORARY_LIST.id).parse(response.getEntity().getContent(), null);
} catch (Exception e) {
Log.e("Error importing gpx from extremcaching.com", e);
return Collections.emptyList();
@@ -171,46 +172,44 @@ public class ECApi {
private static List<Geocache> importCachesFromJSON(final HttpResponse response) {
if (response != null) {
try {
- final String data = Network.getResponseDataAlways(response);
- if (StringUtils.isBlank(data) || StringUtils.equals(data, "[]")) {
+ final JsonNode json = JsonUtils.reader.readTree(Network.getResponseDataAlways(response));
+ if (!json.isArray()) {
return Collections.emptyList();
}
- final JSONArray json = new JSONArray(data);
- final int len = json.length();
- final List<Geocache> caches = new ArrayList<>(len);
- for (int i = 0; i < len; i++) {
- final Geocache cache = parseCache(json.getJSONObject(i));
+ final List<Geocache> caches = new ArrayList<>(json.size());
+ for (final JsonNode node: json) {
+ final Geocache cache = parseCache(node);
if (cache != null) {
caches.add(cache);
}
}
return caches;
- } catch (final JSONException e) {
- Log.w("JSONResult", e);
+ } catch (IOException | ClassCastException e) {
+ Log.w("importCachesFromJSON", e);
}
}
return Collections.emptyList();
}
- private static Geocache parseCache(final JSONObject response) {
- final Geocache cache = new Geocache();
- cache.setReliableLatLon(true);
+ private static Geocache parseCache(final JsonNode response) {
try {
- cache.setGeocode("EC" + response.getString("cache_id"));
- cache.setName(response.getString("title"));
- cache.setCoords(new Geopoint(response.getString("lat"), response.getString("lon")));
- cache.setType(getCacheType(response.getString("type")));
- cache.setDifficulty((float) response.getDouble("difficulty"));
- cache.setTerrain((float) response.getDouble("terrain"));
- cache.setSize(CacheSize.getById(response.getString("size")));
- cache.setFound(response.getInt("found") == 1);
+ final Geocache cache = new Geocache();
+ cache.setReliableLatLon(true);
+ cache.setGeocode("EC" + response.get("cache_id").asText());
+ cache.setName(response.get("title").asText());
+ cache.setCoords(new Geopoint(response.get("lat").asText(), response.get("lon").asText()));
+ cache.setType(getCacheType(response.get("type").asText()));
+ cache.setDifficulty((float) response.get("difficulty").asDouble());
+ cache.setTerrain((float) response.get("terrain").asDouble());
+ cache.setSize(CacheSize.getById(response.get("size").asText()));
+ cache.setFound(response.get("found").asInt() == 1);
DataStore.saveCache(cache, EnumSet.of(SaveFlag.CACHE));
- } catch (final JSONException e) {
+ return cache;
+ } catch (final NullPointerException e) {
Log.e("ECApi.parseCache", e);
return null;
}
- return cache;
}
private static CacheType getCacheType(final String cacheType) {
diff --git a/main/src/cgeo/geocaching/connector/ec/ECLogin.java b/main/src/cgeo/geocaching/connector/ec/ECLogin.java
index 012bdc9..35c2db4 100644
--- a/main/src/cgeo/geocaching/connector/ec/ECLogin.java
+++ b/main/src/cgeo/geocaching/connector/ec/ECLogin.java
@@ -7,14 +7,18 @@ import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.JsonUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.eclipse.jdt.annotation.Nullable;
-import org.json.JSONException;
-import org.json.JSONObject;
+
+import java.io.IOException;
public class ECLogin extends AbstractLogin {
@@ -26,7 +30,7 @@ public class ECLogin extends AbstractLogin {
}
private static class SingletonHolder {
- private static ECLogin INSTANCE = new ECLogin();
+ private final static ECLogin INSTANCE = new ECLogin();
}
public static ECLogin getInstance() {
@@ -93,18 +97,18 @@ public class ECLogin extends AbstractLogin {
setActualStatus(app.getString(R.string.init_login_popup_ok));
try {
- final JSONObject json = new JSONObject(data);
+ final JsonNode json = JsonUtils.reader.readTree(data);
- final String sid = json.getString("sid");
+ final String sid = json.get("sid").asText();
if (!StringUtils.isBlank(sid)) {
sessionId = sid;
setActualLoginStatus(true);
- setActualUserName(json.getString("username"));
- setActualCachesFound(json.getInt("found"));
+ setActualUserName(json.get("username").asText());
+ setActualCachesFound(json.get("found").asInt());
return true;
}
resetLoginStatus();
- } catch (final JSONException e) {
+ } catch (IOException | NullPointerException e) {
Log.e("ECLogin.getLoginStatus", e);
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 3b7c31e..4512979 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -344,6 +344,11 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
+ public void logout() {
+ GCLogin.getInstance().logout();
+ }
+
+ @Override
public String getUserName() {
return GCLogin.getInstance().getActualUserName();
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index 3f16156..c2021bb 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -45,7 +45,6 @@ public final class GCConstants {
public final static Pattern PATTERN_OWNER_USERID = Pattern.compile("other caches <a href=\"/seek/nearest\\.aspx\\?u=(.*?)\">hidden</a> or");
public final static Pattern PATTERN_FOUND = Pattern.compile("ctl00_ContentBody_GeoNav_logText\">(Found It|Attended)");
public final static Pattern PATTERN_FOUND_ALTERNATIVE = Pattern.compile("<div class=\"StatusInformationWidget FavoriteWidget\"");
- public final static Pattern PATTERN_FOUND_DATE = Pattern.compile(">Logged on: ([^<]+?)<");
public final static Pattern PATTERN_OWNER_DISPLAYNAME = Pattern.compile("<div id=\"ctl00_ContentBody_mcd1\">[^<]+<a href=\"[^\"]+\">([^<]+)</a>");
public final static Pattern PATTERN_TYPE = Pattern.compile("<a href=\"/seek/nearest.aspx\\?tx=([0-9a-f-]+)");
public final static Pattern PATTERN_HIDDEN = Pattern.compile("<div id=\"ctl00_ContentBody_mcd2\">\\W*Hidden[\\s:]*([^<]+?)</div>");
diff --git a/main/src/cgeo/geocaching/connector/gc/GCLogin.java b/main/src/cgeo/geocaching/connector/gc/GCLogin.java
index 9f430c0..16f20b8 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCLogin.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCLogin.java
@@ -175,6 +175,9 @@ public class GCLogin extends AbstractLogin {
return StatusCode.NO_ERROR;
}
+ private static String removeDotAndComma(final String str) {
+ return StringUtils.replaceChars(str, ".,", null);
+ }
/**
* Check if the user has been logged in when he retrieved the data.
@@ -201,7 +204,7 @@ public class GCLogin extends AbstractLogin {
setActualUserName(TextUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???"));
int cachesCount = 0;
try {
- cachesCount = Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", ""));
+ cachesCount = Integer.parseInt(removeDotAndComma(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0")));
} catch (final NumberFormatException e) {
Log.e("getLoginStatus: bad cache count", e);
}
@@ -266,7 +269,7 @@ public class GCLogin extends AbstractLogin {
Settings.setGCMemberStatus(GCConstants.MEMBER_STATUS_PM);
}
- setActualCachesFound(Integer.parseInt(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", "")));
+ setActualCachesFound(Integer.parseInt(removeDotAndComma(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1"))));
final String avatarURL = TextUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null);
if (avatarURL != null) {
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 27ce06e..bacaddb 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -9,6 +9,7 @@ import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy;
import cgeo.geocaching.enumerations.LiveMapStrategy.StrategyFlag;
import cgeo.geocaching.enumerations.StatusCode;
+import cgeo.geocaching.files.ParserException;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter.Format;
import cgeo.geocaching.geopoint.Units;
@@ -16,20 +17,23 @@ import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Formatter;
+import cgeo.geocaching.utils.JsonUtils;
import cgeo.geocaching.utils.LeastRecentlyUsedMap;
import cgeo.geocaching.utils.Log;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
import rx.Observable;
import rx.functions.Func2;
import android.graphics.Bitmap;
+import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -60,53 +64,41 @@ public class GCMap {
// {"name":"HP: Hannover - Sahlkamp","gc":"GC2Q97X","g":"a09149ca-00e0-4aa2-b332-db2b4dfb18d2","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"0","difficulty":{"text":1.0,"value":"1"},"terrain":{"text":1.5,"value":"1_5"},"hidden":"5/29/2011","container":{"text":"Small","value":"small.gif"},"type":{"text":"Traditional Cache","value":2},"owner":{"text":"GeoM@n","value":"1deaa69e-6bcc-421d-95a1-7d32b468cb82"}}]
// }
- final JSONObject json = new JSONObject(data);
- final String status = json.getString("status");
+ final ObjectNode json = (ObjectNode) JsonUtils.reader.readTree(data);
+ final String status = json.path("status").asText();
if (StringUtils.isBlank(status)) {
-
- throw new JSONException("No status inside JSON");
+ throw new ParserException("No status inside JSON");
}
if ("success".compareTo(status) != 0) {
- throw new JSONException("Wrong status inside JSON");
+ throw new ParserException("Wrong status inside JSON");
}
- final JSONArray dataArray = json.getJSONArray("data");
+ final ArrayNode dataArray = (ArrayNode) json.get("data");
if (dataArray == null) {
- throw new JSONException("No data inside JSON");
+ throw new ParserException("No data inside JSON");
}
final ArrayList<Geocache> caches = new ArrayList<>();
- for (int j = 0; j < dataArray.length(); j++) {
+ for (final JsonNode dataObject: dataArray) {
final Geocache cache = new Geocache();
-
- JSONObject dataObject = dataArray.getJSONObject(j);
- cache.setName(dataObject.getString("name"));
- cache.setGeocode(dataObject.getString("gc"));
- cache.setGuid(dataObject.getString("g")); // 34c2e609-5246-4f91-9029-d6c02b0f2a82"
- cache.setDisabled(!dataObject.getBoolean("available"));
- cache.setArchived(dataObject.getBoolean("archived"));
- cache.setPremiumMembersOnly(dataObject.getBoolean("subrOnly"));
+ cache.setName(dataObject.path("name").asText());
+ cache.setGeocode(dataObject.path("gc").asText());
+ cache.setGuid(dataObject.path("g").asText()); // 34c2e609-5246-4f91-9029-d6c02b0f2a82"
+ cache.setDisabled(!dataObject.path("available").asBoolean());
+ cache.setArchived(dataObject.path("archived").asBoolean());
+ cache.setPremiumMembersOnly(dataObject.path("subrOnly").asBoolean());
// "li" seems to be "false" always
- cache.setFavoritePoints(Integer.parseInt(dataObject.getString("fp")));
- JSONObject difficultyObj = dataObject.getJSONObject("difficulty");
- cache.setDifficulty(Float.parseFloat(difficultyObj.getString("text"))); // 3.5
- JSONObject terrainObj = dataObject.getJSONObject("terrain");
- cache.setTerrain(Float.parseFloat(terrainObj.getString("text"))); // 1.5
- cache.setHidden(GCLogin.parseGcCustomDate(dataObject.getString("hidden"), "MM/dd/yyyy")); // 7/23/2001
- JSONObject containerObj = dataObject.getJSONObject("container");
- cache.setSize(CacheSize.getById(containerObj.getString("text"))); // Regular
- JSONObject typeObj = dataObject.getJSONObject("type");
- cache.setType(CacheType.getByPattern(typeObj.getString("text"))); // Traditional Cache
- JSONObject ownerObj = dataObject.getJSONObject("owner");
- cache.setOwnerDisplayName(ownerObj.getString("text"));
+ cache.setFavoritePoints(Integer.parseInt(dataObject.path("fp").asText()));
+ cache.setDifficulty(Float.parseFloat(dataObject.path("difficulty").path("text").asText())); // 3.5
+ cache.setTerrain(Float.parseFloat(dataObject.path("terrain").path("text").asText())); // 1.5
+ cache.setHidden(GCLogin.parseGcCustomDate(dataObject.path("hidden").asText(), "MM/dd/yyyy")); // 7/23/2001
+ cache.setSize(CacheSize.getById(dataObject.path("container").path("text").asText())); // Regular
+ cache.setType(CacheType.getByPattern(dataObject.path("type").path("text").asText())); // Traditional Cache
+ cache.setOwnerDisplayName(dataObject.path("owner").path("text").asText());
caches.add(cache);
}
result.addAndPutInCache(caches);
- } catch (JSONException e) {
- result.setError(StatusCode.UNKNOWN_ERROR);
- } catch (ParseException e) {
- result.setError(StatusCode.UNKNOWN_ERROR);
- } catch (NumberFormatException e) {
+ } catch (ParserException | ParseException | IOException | NumberFormatException ignore) {
result.setError(StatusCode.UNKNOWN_ERROR);
}
return result;
@@ -125,7 +117,7 @@ public class GCMap {
final LeastRecentlyUsedMap<String, String> nameCache = new LeastRecentlyUsedMap.LruCache<>(2000); // JSON id, cache name
if (StringUtils.isEmpty(data)) {
- throw new JSONException("No page given");
+ throw new ParserException("No page given");
}
// Example JSON information
@@ -134,34 +126,33 @@ public class GCMap {
// "data":{"55_55":[{"i":"gEaR","n":"Spiel & Sport"}],"55_54":[{"i":"gEaR","n":"Spiel & Sport"}],"17_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"55_53":[{"i":"gEaR","n":"Spiel & Sport"}],"17_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"17_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"57_53":[{"i":"gEaR","n":"Spiel & Sport"}],"57_55":[{"i":"gEaR","n":"Spiel & Sport"}],"3_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"3_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"57_54":[{"i":"gEaR","n":"Spiel & Sport"}],"3_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"15_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"15_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"15_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"4_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"4_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"4_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"16_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"16_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"16_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"2_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"2_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"2_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"56_53":[{"i":"gEaR","n":"Spiel & Sport"}],"56_54":[{"i":"gEaR","n":"Spiel & Sport"}],"56_55":[{"i":"gEaR","n":"Spiel & Sport"}]}
// }
- final JSONObject json = new JSONObject(data);
+ final ObjectNode json = (ObjectNode) JsonUtils.reader.readTree(data);
- final JSONArray grid = json.getJSONArray("grid");
- if (grid == null || grid.length() != (UTFGrid.GRID_MAXY + 1)) {
- throw new JSONException("No grid inside JSON");
+ final ArrayNode grid = (ArrayNode) json.get("grid");
+ if (grid == null || grid.size() != (UTFGrid.GRID_MAXY + 1)) {
+ throw new ParserException("No grid inside JSON");
}
- final JSONArray keys = json.getJSONArray("keys");
+ final ArrayNode keys = (ArrayNode) json.get("keys");
if (keys == null) {
- throw new JSONException("No keys inside JSON");
+ throw new ParserException("No keys inside JSON");
}
- final JSONObject dataObject = json.getJSONObject("data");
+ final ObjectNode dataObject = (ObjectNode) json.get("data");
if (dataObject == null) {
- throw new JSONException("No data inside JSON");
+ throw new ParserException("No data inside JSON");
}
// iterate over the data and construct all caches in this tile
Map<String, List<UTFGridPosition>> positions = new HashMap<>(); // JSON id as key
Map<String, List<UTFGridPosition>> singlePositions = new HashMap<>(); // JSON id as key
- for (int i = 1; i < keys.length(); i++) { // index 0 is empty
- String key = keys.getString(i);
- if (StringUtils.isNotBlank(key)) {
+ for (final JsonNode rawKey: keys) {
+ final String key = rawKey.asText();
+ if (StringUtils.isNotBlank(key)) { // index 0 is empty
UTFGridPosition pos = UTFGridPosition.fromString(key);
- JSONArray dataForKey = dataObject.getJSONArray(key);
- for (int j = 0; j < dataForKey.length(); j++) {
- JSONObject cacheInfo = dataForKey.getJSONObject(j);
- String id = cacheInfo.getString("i");
- nameCache.put(id, cacheInfo.getString("n"));
+ final ArrayNode dataForKey = (ArrayNode) dataObject.get(key);
+ for (final JsonNode cacheInfo: dataForKey) {
+ final String id = cacheInfo.get("i").asText();
+ nameCache.put(id, cacheInfo.get("n").asText());
List<UTFGridPosition> listOfPositions = positions.get(id);
List<UTFGridPosition> singleListOfPositions = singlePositions.get(id);
@@ -174,7 +165,7 @@ public class GCMap {
}
listOfPositions.add(pos);
- if (dataForKey.length() == 1) {
+ if (dataForKey.size() == 1) {
singleListOfPositions.add(pos);
}
@@ -220,9 +211,7 @@ public class GCMap {
searchResult.addAndPutInCache(caches);
Log.d("Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString());
- } catch (RuntimeException e) {
- Log.e("GCMap.parseMapJSON", e);
- } catch (JSONException e) {
+ } catch (RuntimeException | ParserException | IOException e) {
Log.e("GCMap.parseMapJSON", e);
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index c771049..6919173 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -30,6 +30,8 @@ import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.DirectionImage;
import cgeo.geocaching.utils.CancellableHandler;
+import cgeo.geocaching.utils.HtmlUtils;
+import cgeo.geocaching.utils.JsonUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.RxUtils;
@@ -38,15 +40,16 @@ import cgeo.geocaching.utils.TextUtils;
import ch.boye.httpclientandroidlib.HttpResponse;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
import org.apache.commons.collections4.CollectionUtils;
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;
import rx.Observable;
import rx.Observable.OnSubscribe;
@@ -59,6 +62,7 @@ import android.net.Uri;
import android.text.Html;
import java.io.File;
+import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
@@ -75,6 +79,7 @@ import java.util.regex.Pattern;
public abstract class GCParser {
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 final static ImmutablePair<StatusCode, Geocache> UNKNOWN_PARSE_ERROR = ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null);
private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(pageContent)) {
@@ -125,12 +130,12 @@ public abstract class GCParser {
page = page.substring(startPos + 1, endPos - startPos + 1); // cut between <table> and </table>
- final String[] rows = page.split("<tr class=");
- final int rows_count = rows.length;
+ final String[] rows = StringUtils.splitByWholeSeparator(page, "<tr class=");
+ final int rowsCount = rows.length;
int excludedCaches = 0;
final ArrayList<Geocache> caches = new ArrayList<>();
- for (int z = 1; z < rows_count; z++) {
+ for (int z = 1; z < rowsCount; z++) {
final Geocache cache = new Geocache();
final String row = rows[z];
@@ -161,7 +166,7 @@ public abstract class GCParser {
}
} catch (final RuntimeException e) {
// failed to parse GUID and/or Disabled
- Log.w("GCParser.parseSearch: Failed to parse GUID and/or Disabled data");
+ Log.w("GCParser.parseSearch: Failed to parse GUID and/or Disabled data", e);
}
if (Settings.isExcludeDisabledCaches() && (cache.isDisabled() || cache.isArchived())) {
@@ -173,11 +178,11 @@ public abstract class GCParser {
cache.setGeocode(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true));
// cache type
- cache.setType(CacheType.getByPattern(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, true, 1, null, true)));
+ cache.setType(CacheType.getByPattern(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, null)));
// cache direction - image
if (Settings.getLoadDirImg()) {
- final String direction = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 1, null, false);
+ final String direction = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, null);
if (direction != null) {
cache.setDirectionImg(direction);
}
@@ -204,19 +209,19 @@ public abstract class GCParser {
}
// size
- final String container = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_CONTAINER, false, 1, null, false);
+ final String container = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_CONTAINER, false, null);
cache.setSize(CacheSize.getById(container));
// date hidden, makes sorting event caches easier
- final String dateHidden = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_HIDDEN_DATE, false, 1, null, false);
+ final String dateHidden = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_HIDDEN_DATE, false, null);
if (StringUtils.isNotBlank(dateHidden)) {
try {
- Date date = GCLogin.parseGcCustomDate(dateHidden);
+ final Date date = GCLogin.parseGcCustomDate(dateHidden);
if (date != null) {
cache.setHidden(date);
}
- } catch (ParseException e) {
- Log.e("Error parsing event date from search");
+ } catch (final ParseException e) {
+ Log.e("Error parsing event date from search", e);
}
}
@@ -266,7 +271,7 @@ public abstract class GCParser {
cache.setFavoritePoints(Integer.parseInt(result));
}
} catch (final NumberFormatException e) {
- Log.w("GCParser.parseSearch: Failed to parse favorite count");
+ Log.w("GCParser.parseSearch: Failed to parse favorite count", e);
}
caches.add(cache);
@@ -280,7 +285,7 @@ public abstract class GCParser {
searchResult.setTotalCountGC(Integer.parseInt(result) - excludedCaches);
}
} catch (final NumberFormatException e) {
- Log.w("GCParser.parseSearch: Failed to parse cache count");
+ Log.w("GCParser.parseSearch: Failed to parse cache count", e);
}
String recaptchaText = null;
@@ -380,17 +385,20 @@ public abstract class GCParser {
* Parse cache from text and return either an error code or a cache object in a pair. Note that inline logs are
* not parsed nor saved, while the cache itself is.
*
- * @param pageIn the page text to parse
- * @param handler the handler to send the progress notifications to
- * @return a pair, with a {@link StatusCode} on the left, and a non-nulll cache objet on the right
- * iff the status code is {@link StatusCode.NO_ERROR}.
+ * @param pageIn
+ * the page text to parse
+ * @param handler
+ * the handler to send the progress notifications to
+ * @return a pair, with a {@link StatusCode} on the left, and a non-null cache object on the right
+ * iff the status code is {@link StatusCode.NO_ERROR}.
*/
+ @NonNull
static private ImmutablePair<StatusCode, Geocache> parseCacheFromText(final String pageIn, @Nullable final CancellableHandler handler) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details);
if (StringUtils.isBlank(pageIn)) {
Log.e("GCParser.parseCache: No page given");
- return null;
+ return UNKNOWN_PARSE_ERROR;
}
if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
@@ -403,12 +411,12 @@ public abstract class GCParser {
final String cacheName = Html.fromHtml(TextUtils.getMatch(pageIn, GCConstants.PATTERN_NAME, true, "")).toString();
if (GCConstants.STRING_UNKNOWN_ERROR.equalsIgnoreCase(cacheName)) {
- return ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null);
+ return UNKNOWN_PARSE_ERROR;
}
// first handle the content with line breaks, then trim everything for easier matching and reduced memory consumption in parsed fields
String personalNoteWithLineBreaks = "";
- MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_PERSONALNOTE, pageIn);
+ final MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_PERSONALNOTE, pageIn);
if (matcher.find()) {
personalNoteWithLineBreaks = matcher.group(1).trim();
}
@@ -446,7 +454,7 @@ public abstract class GCParser {
final int pos = tableInside.indexOf(GCConstants.STRING_CACHEDETAILS);
if (pos == -1) {
Log.e("GCParser.parseCache: ID \"cacheDetails\" not found on page");
- return null;
+ return UNKNOWN_PARSE_ERROR;
}
tableInside = tableInside.substring(pos);
@@ -490,7 +498,7 @@ public abstract class GCParser {
}
} catch (final ParseException e) {
// failed to parse cache hidden date
- Log.w("GCParser.parseCache: Failed to parse cache hidden (event) date");
+ Log.w("GCParser.parseCache: Failed to parse cache hidden (event) date", e);
}
// favorite
@@ -579,13 +587,13 @@ public abstract class GCParser {
}
} catch (final RuntimeException e) {
// failed to parse cache attributes
- Log.w("GCParser.parseCache: Failed to parse cache attributes");
+ Log.w("GCParser.parseCache: Failed to parse cache attributes", e);
}
// cache spoilers
try {
if (CancellableHandler.isCancelled(handler)) {
- return null;
+ return UNKNOWN_PARSE_ERROR;
}
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers);
@@ -608,7 +616,7 @@ public abstract class GCParser {
}
} catch (final RuntimeException e) {
// failed to parse cache spoilers
- Log.w("GCParser.parseCache: Failed to parse cache spoilers");
+ Log.w("GCParser.parseCache: Failed to parse cache spoilers", e);
}
// cache inventory
@@ -642,7 +650,7 @@ public abstract class GCParser {
}
} catch (final RuntimeException e) {
// failed to parse cache inventory
- Log.w("GCParser.parseCache: Failed to parse cache inventory (2)");
+ Log.w("GCParser.parseCache: Failed to parse cache inventory (2)", e);
}
// cache logs counts
@@ -664,7 +672,7 @@ public abstract class GCParser {
}
} catch (final NumberFormatException e) {
// failed to parse logs
- Log.w("GCParser.parseCache: Failed to parse cache log count");
+ Log.w("GCParser.parseCache: Failed to parse cache log count", e);
}
// waypoints - reset collection
@@ -680,13 +688,13 @@ public abstract class GCParser {
cache.addOrChangeWaypoint(waypoint, false);
cache.setUserModifiedCoords(true);
}
- } catch (final Geopoint.GeopointException e) {
+ } catch (final Geopoint.GeopointException ignored) {
}
int wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
if (wpBegin != -1) { // parse waypoints
if (CancellableHandler.isCancelled(handler)) {
- return null;
+ return UNKNOWN_PARSE_ERROR;
}
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_waypoints);
@@ -707,10 +715,10 @@ public abstract class GCParser {
wpList = wpList.substring(wpBegin + 7, wpEnd);
}
- final String[] wpItems = wpList.split("<tr");
+ final String[] wpItems = StringUtils.splitByWholeSeparator(wpList, "<tr");
for (int j = 1; j < wpItems.length; j++) {
- String[] wp = wpItems[j].split("<td");
+ String[] wp = StringUtils.splitByWholeSeparator(wpItems[j], "<td");
// waypoint name
// res is null during the unit tests
@@ -730,13 +738,12 @@ public abstract class GCParser {
// 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);
waypoint.setCoords(new Geopoint(latlon));
}
j++;
if (wpItems.length > j) {
- wp = wpItems[j].split("<td");
+ wp = StringUtils.splitByWholeSeparator(wpItems[j], "<td");
}
// waypoint note
@@ -751,7 +758,7 @@ public abstract class GCParser {
// last check for necessary cache conditions
if (StringUtils.isBlank(cache.getGeocode())) {
- return ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null);
+ return UNKNOWN_PARSE_ERROR;
}
cache.setDetailedUpdatedNow();
@@ -762,7 +769,7 @@ public abstract class GCParser {
return StringUtils.replaceChars(numberWithPunctuation, ".,", "");
}
- public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByNextPage(final SearchResult search, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (search == null) {
return null;
}
@@ -845,7 +852,7 @@ public abstract class GCParser {
* @return
*/
@Nullable
- private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, RecaptchaReceiver recaptchaReceiver) {
+ private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, final RecaptchaReceiver recaptchaReceiver) {
insertCacheType(params, cacheType);
final String uri = "http://www.geocaching.com/seek/nearest.aspx";
@@ -871,12 +878,12 @@ public abstract class GCParser {
return search;
}
- public static SearchResult searchByCoords(final @NonNull Geopoint coords, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByCoords(final @NonNull Geopoint coords, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
final Parameters params = new Parameters("lat", Double.toString(coords.getLatitude()), "lng", Double.toString(coords.getLongitude()));
return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByKeyword(final @NonNull String keyword, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByKeyword(final @NonNull String keyword, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(keyword)) {
Log.e("GCParser.searchByKeyword: No keyword given");
return null;
@@ -894,7 +901,7 @@ public abstract class GCParser {
return false;
}
- public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(userName)) {
Log.e("GCParser.searchByUsername: No user name given");
return null;
@@ -905,7 +912,7 @@ public abstract class GCParser {
return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByPocketQuery(final String pocketGuid, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByPocketQuery(final String pocketGuid, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(pocketGuid)) {
Log.e("GCParser.searchByPocket: No guid name given");
return null;
@@ -916,7 +923,7 @@ public abstract class GCParser {
return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(userName)) {
Log.e("GCParser.searchByOwner: No user name given");
return null;
@@ -926,32 +933,28 @@ public abstract class GCParser {
return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver);
}
- public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) {
+ public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) {
if (StringUtils.isBlank(address)) {
Log.e("GCParser.searchByAddress: No address given");
return null;
}
- try {
- final JSONObject response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address));
- if (response == null) {
- return null;
- }
- if (!StringUtils.equalsIgnoreCase(response.getString("status"), "success")) {
- return null;
- }
- if (!response.has("data")) {
- return null;
- }
- final JSONObject data = response.getJSONObject("data");
- if (data == null) {
- return null;
- }
- return searchByCoords(new Geopoint(data.getDouble("lat"), data.getDouble("lng")), cacheType, showCaptcha, recaptchaReceiver);
- } catch (final JSONException e) {
- Log.w("GCParser.searchByAddress", e);
+
+ final ObjectNode response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address));
+ if (response == null) {
+ return null;
}
- return null;
+ if (!StringUtils.equalsIgnoreCase(response.path("status").asText(), "success")) {
+ return null;
+ }
+
+ final JsonNode data = response.path("data");
+ final JsonNode latNode = data.get("lat");
+ final JsonNode lngNode = data.get("lng");
+ if (latNode == null || lngNode == null) {
+ return null;
+ }
+ return searchByCoords(new Geopoint(latNode.asDouble(), lngNode.asDouble()), cacheType, showCaptcha, recaptchaReceiver);
}
@Nullable
@@ -1001,13 +1004,13 @@ public abstract class GCParser {
return null;
}
- String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable");
+ final String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable");
if (StringUtils.isEmpty(subPage)) {
Log.e("GCParser.searchPocketQueryList: class \"PocketQueryListTable\" not found on page");
return Collections.emptyList();
}
- List<PocketQueryList> list = new ArrayList<>();
+ final List<PocketQueryList> list = new ArrayList<>();
final MatcherWrapper matcherPocket = new MatcherWrapper(GCConstants.PATTERN_LIST_PQ, subPage);
@@ -1015,7 +1018,7 @@ public abstract class GCParser {
int maxCaches;
try {
maxCaches = Integer.parseInt(matcherPocket.group(1));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
maxCaches = 0;
Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e);
}
@@ -1029,7 +1032,7 @@ public abstract class GCParser {
Collections.sort(list, new Comparator<PocketQueryList>() {
@Override
- public int compare(PocketQueryList left, PocketQueryList right) {
+ public int compare(final PocketQueryList left, final PocketQueryList right) {
return String.CASE_INSENSITIVE_ORDER.compare(left.getName(), right.getName());
}
});
@@ -1483,7 +1486,7 @@ public abstract class GCParser {
}
} catch (final RuntimeException e) {
// failed to parse trackable owner name
- Log.w("GCParser.parseTrackable: Failed to parse trackable owner name");
+ Log.w("GCParser.parseTrackable: Failed to parse trackable owner name", e);
}
// trackable origin
@@ -1514,7 +1517,7 @@ public abstract class GCParser {
}
} catch (final RuntimeException e) {
// failed to parse trackable last known place
- Log.w("GCParser.parseTrackable: Failed to parse trackable last known place");
+ Log.w("GCParser.parseTrackable: Failed to parse trackable last known place", e);
}
// released date - can be missing on the page
@@ -1522,12 +1525,12 @@ public abstract class GCParser {
if (releaseString != null) {
try {
trackable.setReleased(dateTbIn1.parse(releaseString));
- } catch (ParseException e) {
+ } catch (final ParseException ignore) {
if (trackable.getReleased() == null) {
try {
trackable.setReleased(dateTbIn2.parse(releaseString));
- } catch (ParseException e1) {
- Log.e("Could not parse trackable release " + releaseString);
+ } catch (final ParseException e) {
+ Log.e("Could not parse trackable release " + releaseString, e);
}
}
}
@@ -1545,7 +1548,7 @@ public abstract class GCParser {
}
// trackable goal
- trackable.setGoal(convertLinks(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())));
+ trackable.setGoal(HtmlUtils.removeExtraParagraph(convertLinks(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal()))));
// trackable details & image
try {
@@ -1558,12 +1561,12 @@ public abstract class GCParser {
trackable.setImage(StringUtils.replace(image, "/display/", "/large/"));
}
if (StringUtils.isNotEmpty(details) && !StringUtils.equals(details, "No additional details available.")) {
- trackable.setDetails(convertLinks(details));
+ trackable.setDetails(HtmlUtils.removeExtraParagraph(convertLinks(details)));
}
}
} catch (final RuntimeException e) {
// failed to parse trackable details & image
- Log.w("GCParser.parseTrackable: Failed to parse trackable details & image");
+ Log.w("GCParser.parseTrackable: Failed to parse trackable details & image", e);
}
if (StringUtils.isEmpty(trackable.getDetails()) && page.contains(GCConstants.ERROR_TB_NOT_ACTIVATED)) {
trackable.setDetails(CgeoApplication.getInstance().getString(R.string.trackable_not_activated));
@@ -1585,7 +1588,7 @@ public abstract class GCParser {
long date = 0;
try {
date = GCLogin.parseGcCustomDate(matcherLogs.group(2)).getTime();
- } catch (final ParseException e) {
+ } catch (final ParseException ignore) {
}
final LogEntry logDone = new LogEntry(
@@ -1630,7 +1633,7 @@ public abstract class GCParser {
return trackable;
}
- private static String convertLinks(String input) {
+ private static String convertLinks(final String input) {
if (input == null) {
return null;
}
@@ -1691,7 +1694,7 @@ public abstract class GCParser {
Log.e("GCParser.loadLogsFromDetails: error " + statusCode + " when requesting log information");
return Observable.empty();
}
- String rawResponse = Network.getResponseData(response);
+ final String rawResponse = Network.getResponseData(response);
if (rawResponse == null) {
Log.e("GCParser.loadLogsFromDetails: unable to read whole response");
return Observable.empty();
@@ -1712,56 +1715,51 @@ public abstract class GCParser {
}
try {
- final JSONObject resp = new JSONObject(rawResponse);
- if (!resp.getString("status").equals("success")) {
- Log.e("GCParser.loadLogsFromDetails: status is " + resp.getString("status"));
+ final ObjectNode resp = (ObjectNode) JsonUtils.reader.readTree(rawResponse);
+ if (!resp.path("status").asText().equals("success")) {
+ Log.e("GCParser.loadLogsFromDetails: status is " + resp.path("status").asText("[absent]"));
subscriber.onCompleted();
return;
}
- final JSONArray data = resp.getJSONArray("data");
-
- for (int index = 0; index < data.length(); index++) {
- final JSONObject entry = data.getJSONObject(index);
-
+ final ArrayNode data = (ArrayNode) resp.get("data");
+ for (final JsonNode entry: data) {
// FIXME: use the "LogType" field instead of the "LogTypeImage" one.
- final String logIconNameExt = entry.optString("LogTypeImage", ".gif");
+ final String logIconNameExt = entry.path("LogTypeImage").asText(".gif");
final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4);
long date = 0;
try {
- date = GCLogin.parseGcCustomDate(entry.getString("Visited")).getTime();
- } catch (final ParseException e) {
- Log.e("GCParser.loadLogsFromDetails: failed to parse log date.");
+ date = GCLogin.parseGcCustomDate(entry.get("Visited").asText()).getTime();
+ } catch (ParseException | NullPointerException e) {
+ Log.e("GCParser.loadLogsFromDetails: failed to parse log date", e);
}
// 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 at all.
- final String latLon = entry.getString("LatLonString");
- final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "<br/><br/>")) + TextUtils.removeControlCharacters(entry.getString("LogText"));
+ final String latLon = entry.path("LatLonString").asText();
+ final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "<br/><br/>")) + TextUtils.removeControlCharacters(entry.path("LogText").asText());
final LogEntry logDone = new LogEntry(
- TextUtils.removeControlCharacters(entry.getString("UserName")),
+ TextUtils.removeControlCharacters(entry.path("UserName").asText()),
date,
LogType.getByIconName(logIconName),
logText);
- logDone.found = entry.getInt("GeocacheFindCount");
+ logDone.found = entry.path("GeocacheFindCount").asInt();
logDone.friend = markAsFriendsLog;
- final JSONArray images = entry.getJSONArray("Images");
- for (int i = 0; i < images.length(); i++) {
- final JSONObject image = images.getJSONObject(i);
- final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.getString("FileName");
- final String title = TextUtils.removeControlCharacters(image.getString("Name"));
+ final ArrayNode images = (ArrayNode) entry.get("Images");
+ for (final JsonNode image: images) {
+ final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.path("FileName").asText();
+ final String title = TextUtils.removeControlCharacters(image.path("Name").asText());
final Image logImage = new Image(url, title);
logDone.addLogImage(logImage);
}
subscriber.onNext(logDone);
}
- } catch (final JSONException e) {
- // failed to parse logs
+ } catch (final IOException e) {
Log.w("GCParser.loadLogsFromDetails: Failed to parse cache logs", e);
}
subscriber.onCompleted();
@@ -1770,7 +1768,7 @@ public abstract class GCParser {
}
@NonNull
- public static List<LogType> parseTypes(String page) {
+ public static List<LogType> parseTypes(final String page) {
if (StringUtils.isEmpty(page)) {
return Collections.emptyList();
}
@@ -1865,16 +1863,11 @@ public abstract class GCParser {
return;
}
+ CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
final Observable<LogEntry> logs = getLogs(page, Logs.ALL);
- Observable<LogEntry> specialLogs;
- if (Settings.isFriendLogsWanted()) {
- CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
- specialLogs = Observable.merge(getLogs(page, Logs.FRIENDS),
- getLogs(page, Logs.OWN));
- } else {
- CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
- specialLogs = Observable.empty();
- }
+ final Observable<LogEntry> ownLogs = getLogs(page, Logs.OWN).cache();
+ final Observable<LogEntry> specialLogs = Settings.isFriendLogsWanted() ?
+ Observable.merge(getLogs(page, Logs.FRIENDS), ownLogs) : Observable.<LogEntry>empty();
final Observable<List<LogEntry>> mergedLogs = Observable.zip(logs.toList(), specialLogs.toList(),
new Func2<List<LogEntry>, List<LogEntry>, List<LogEntry>>() {
@Override
@@ -1889,6 +1882,16 @@ public abstract class GCParser {
DataStore.saveLogsWithoutTransaction(cache.getGeocode(), logEntries);
}
});
+ if (cache.isFound() && cache.getVisitedDate() == 0) {
+ ownLogs.subscribe(new Action1<LogEntry>() {
+ @Override
+ public void call(final LogEntry logEntry) {
+ if (logEntry.type == LogType.FOUND_IT) {
+ cache.setVisitedDate(logEntry.date);
+ }
+ }
+ });
+ }
if (Settings.isRatingWanted() && !CancellableHandler.isCancelled(handler)) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote);
@@ -1923,75 +1926,61 @@ public abstract class GCParser {
}
}
- public static boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ public static boolean uploadModifiedCoordinates(final Geocache cache, final Geopoint wpt) {
return editModifiedCoordinates(cache, wpt);
}
- public static boolean deleteModifiedCoordinates(Geocache cache) {
+ public static boolean deleteModifiedCoordinates(final Geocache cache) {
return editModifiedCoordinates(cache, null);
}
- public static boolean editModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ public static boolean editModifiedCoordinates(final Geocache cache, final Geopoint wpt) {
final String userToken = getUserToken(cache);
if (StringUtils.isEmpty(userToken)) {
return false;
}
- try {
- JSONObject jo;
- if (wpt != null) {
- jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken)
- .put("data", new JSONObject()
- .put("lat", wpt.getLatitudeE6() / 1E6)
- .put("lng", wpt.getLongitudeE6() / 1E6))));
- } else {
- jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken)));
- }
-
- final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate";
+ final ObjectNode jo = new ObjectNode(JsonUtils.factory);
+ final ObjectNode dto = jo.putObject("dto").put("ut", userToken);
+ if (wpt != null) {
+ dto.putObject("data").put("lat", wpt.getLatitudeE6() / 1E6).put("lng", wpt.getLongitudeE6() / 1E6);
+ }
- final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
- final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
- Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
+ final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate";
- if (response != null && response.getStatusLine().getStatusCode() == 200) {
- Log.i("GCParser.editModifiedCoordinates - edited on GC.com");
- return true;
- }
+ final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
+ final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
+ Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
- } catch (final JSONException e) {
- Log.e("Unknown exception with json wrap code", e);
+ if (response != null && response.getStatusLine().getStatusCode() == 200) {
+ Log.i("GCParser.editModifiedCoordinates - edited on GC.com");
+ return true;
}
+
Log.e("GCParser.deleteModifiedCoordinates - cannot delete modified coords");
return false;
}
- public static boolean uploadPersonalNote(Geocache cache) {
+ public static boolean uploadPersonalNote(final Geocache cache) {
final String userToken = getUserToken(cache);
if (StringUtils.isEmpty(userToken)) {
return false;
}
- try {
- final JSONObject jo = new JSONObject()
- .put("dto", (new JSONObject()
- .put("et", StringUtils.defaultString(cache.getPersonalNote()))
- .put("ut", userToken)));
-
- final String uriSuffix = "SetUserCacheNote";
+ final ObjectNode jo = new ObjectNode(JsonUtils.factory);
+ jo.putObject("dto").put("et", StringUtils.defaultString(cache.getPersonalNote())).put("ut", userToken);
- final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
- final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
- Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
+ final String uriSuffix = "SetUserCacheNote";
- if (response != null && response.getStatusLine().getStatusCode() == 200) {
- Log.i("GCParser.uploadPersonalNote - uploaded to GC.com");
- return true;
- }
+ final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
+ final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
+ Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
- } catch (final JSONException e) {
- Log.e("Unknown exception with json wrap code", e);
+ if (response != null && response.getStatusLine().getStatusCode() == 200) {
+ Log.i("GCParser.uploadPersonalNote - uploaded to GC.com");
+ return true;
}
+
Log.e("GCParser.uploadPersonalNote - cannot upload personal note");
return false;
}
diff --git a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
index 6095514..affeb7d 100644
--- a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
+++ b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java
@@ -42,15 +42,15 @@ public class RecaptchaHandler extends Handler {
}
private void loadChallenge(final ImageView imageView, final View reloadButton) {
- final Observable<Bitmap> captcha = Observable.defer(new Func0<Observable<? extends Bitmap>>() {
+ final Observable<Bitmap> captcha = Observable.defer(new Func0<Observable<Bitmap>>() {
@Override
- public Observable<? extends Bitmap> call() {
+ public Observable<Bitmap> call() {
final String url = "http://www.google.com/recaptcha/api/image?c=" + recaptchaReceiver.getChallenge();
final InputStream is = Network.getResponseStream(Network.getRequest(url));
if (is != null) {
try {
final Bitmap img = BitmapFactory.decodeStream(is);
- return Observable.from(img);
+ return Observable.just(img);
} catch (final Exception e) {
Log.e("RecaptchaHandler.getCaptcha", e);
return Observable.error(e);
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index 18fe65c..ff13fe3 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -56,11 +56,11 @@ public class Tile {
private final int zoomLevel;
private final Viewport viewPort;
- public Tile(Geopoint origin, int zoomlevel) {
+ public Tile(final Geopoint origin, final int zoomlevel) {
this(calcX(origin, clippedZoomlevel(zoomlevel)), calcY(origin, clippedZoomlevel(zoomlevel)), clippedZoomlevel(zoomlevel));
}
- private Tile(int tileX, int tileY, int zoomlevel) {
+ private Tile(final int tileX, final int tileY, final int zoomlevel) {
this.zoomLevel = clippedZoomlevel(zoomlevel);
@@ -74,7 +74,7 @@ public class Tile {
return zoomLevel;
}
- private static int clippedZoomlevel(int zoomlevel) {
+ private static int clippedZoomlevel(final int zoomlevel) {
return Math.max(Math.min(zoomlevel, ZOOMLEVEL_MAX), ZOOMLEVEL_MIN);
}
@@ -95,7 +95,7 @@ public class Tile {
*/
private static int calcY(final Geopoint origin, final int zoomlevel) {
// Optimization from Bing
- double sinLatRad = Math.sin(Math.toRadians(origin.getLatitude()));
+ final double sinLatRad = Math.sin(Math.toRadians(origin.getLatitude()));
// The cut of the fractional part instead of rounding to the nearest integer is intentional and part of the algorithm
return (int) ((0.5 - Math.log((1 + sinLatRad) / (1 - sinLatRad)) / (4 * Math.PI)) * NUMBER_OF_TILES[zoomlevel]);
}
@@ -115,13 +115,13 @@ public class Tile {
* href="http://developers.cloudmade.com/projects/tiles/examples/convert-coordinates-to-tile-numbers">Cloudmade</a>
*/
@NonNull
- public Geopoint getCoord(UTFGridPosition pos) {
+ public Geopoint getCoord(final UTFGridPosition pos) {
- double pixX = tileX * TILE_SIZE + pos.x * 4;
- double pixY = tileY * TILE_SIZE + pos.y * 4;
+ final double pixX = tileX * TILE_SIZE + pos.x * 4;
+ final double pixY = tileY * TILE_SIZE + pos.y * 4;
- double lonDeg = ((360.0 * pixX) / NUMBER_OF_PIXELS[this.zoomLevel]) - 180.0;
- double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / NUMBER_OF_PIXELS[this.zoomLevel])));
+ final double lonDeg = ((360.0 * pixX) / NUMBER_OF_PIXELS[this.zoomLevel]) - 180.0;
+ final double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / NUMBER_OF_PIXELS[this.zoomLevel])));
return new Geopoint(Math.toDegrees(latRad), lonDeg);
}
@@ -153,8 +153,8 @@ public class Tile {
/ Math.log(2)
);
- Tile tileLeft = new Tile(left, zoom);
- Tile tileRight = new Tile(right, zoom);
+ final Tile tileLeft = new Tile(left, zoom);
+ final Tile tileRight = new Tile(right, zoom);
if (Math.abs(tileLeft.tileX - tileRight.tileX) < (numberOfTiles - 1)) {
zoom += 1;
@@ -190,8 +190,8 @@ public class Tile {
) / Math.log(2)
);
- Tile tileBottom = new Tile(bottom, zoom);
- Tile tileTop = new Tile(top, zoom);
+ final Tile tileBottom = new Tile(bottom, zoom);
+ final Tile tileTop = new Tile(top, zoom);
if (Math.abs(tileBottom.tileY - tileTop.tileY) > (numberOfTiles - 1)) {
zoom -= 1;
@@ -200,7 +200,7 @@ public class Tile {
return Math.min(zoom, ZOOMLEVEL_MAX);
}
- private static double tanGrad(double angleGrad) {
+ private static double tanGrad(final double angleGrad) {
return Math.tan(angleGrad / 180.0 * Math.PI);
}
@@ -211,12 +211,12 @@ public class Tile {
* @param x
* @return
*/
- private static double asinh(double x) {
+ private static double asinh(final double x) {
return Math.log(x + Math.sqrt(x * x + 1.0));
}
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
if (this == o) {
return true;
}
@@ -260,7 +260,7 @@ public class Tile {
public Bitmap call() {
try {
return response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null;
- } catch (IOException e) {
+ } catch (final IOException e) {
Log.e("Tile.requestMapTile() ", e);
return null;
}
@@ -298,20 +298,20 @@ public class Tile {
* @return
*/
protected static Set<Tile> getTilesForViewport(final Viewport viewport, final int tilesOnAxis, final int minZoom) {
- Set<Tile> tiles = new HashSet<>();
- int zoom = Math.max(
+ final Set<Tile> tiles = new HashSet<>();
+ final int zoom = Math.max(
Math.min(Tile.calcZoomLon(viewport.bottomLeft, viewport.topRight, tilesOnAxis),
Tile.calcZoomLat(viewport.bottomLeft, viewport.topRight, tilesOnAxis)),
minZoom);
- Tile tileBottomLeft = new Tile(viewport.bottomLeft, zoom);
- Tile tileTopRight = new Tile(viewport.topRight, zoom);
+ final Tile tileBottomLeft = new Tile(viewport.bottomLeft, zoom);
+ final Tile tileTopRight = new Tile(viewport.topRight, zoom);
- int xLow = Math.min(tileBottomLeft.getX(), tileTopRight.getX());
- int xHigh = Math.max(tileBottomLeft.getX(), tileTopRight.getX());
+ final int xLow = Math.min(tileBottomLeft.getX(), tileTopRight.getX());
+ final int xHigh = Math.max(tileBottomLeft.getX(), tileTopRight.getX());
- int yLow = Math.min(tileBottomLeft.getY(), tileTopRight.getY());
- int yHigh = Math.max(tileBottomLeft.getY(), tileTopRight.getY());
+ final int yLow = Math.min(tileBottomLeft.getY(), tileTopRight.getY());
+ final int yHigh = Math.max(tileBottomLeft.getY(), tileTopRight.getY());
for (int xNum = xLow; xNum <= xHigh; xNum++) {
for (int yNum = yLow; yNum <= yHigh; yNum++) {
@@ -324,8 +324,6 @@ public class Tile {
public static class TileCache extends LeastRecentlyUsedSet<Tile> {
- private static final long serialVersionUID = -1942301031192719547L;
-
public TileCache() {
super(64);
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
index 284234e..9e9ec7f 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
@@ -31,7 +31,7 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode {
private final ApiSupport apiSupport;
private final String licenseString;
- public OCApiConnector(String name, String host, String prefix, String cK, String licenseString, ApiSupport apiSupport) {
+ public OCApiConnector(final String name, final String host, final String prefix, final String cK, final String licenseString, final ApiSupport apiSupport) {
super(name, host, prefix);
this.cK = cK;
this.apiSupport = apiSupport;
@@ -39,7 +39,12 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode {
}
public void addAuthentication(final Parameters params) {
- params.put(CryptUtils.rot13("pbafhzre_xrl"), CryptUtils.rot13(cK));
+ final String rotCK = CryptUtils.rot13(cK);
+ // check that developers are not using the Ant defined properties without any values
+ if (StringUtils.startsWith(rotCK, "${")) {
+ throw new IllegalStateException("invalid OKAPI OAuth token " + rotCK);
+ }
+ params.put(CryptUtils.rot13("pbafhzre_xrl"), rotCK);
}
@Override
@@ -93,13 +98,13 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode {
/**
* Checks if a search based on a user name targets the current user
- *
+ *
* @param username
* Name of the user the query is searching after
* @return True - search target and current is same, False - current user not known or not the same as username
*/
@SuppressWarnings("static-method")
- public boolean isSearchForMyCaches(String username) {
+ public boolean isSearchForMyCaches(final String username) {
return false;
}
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index bd87042..f665a1a 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -27,36 +27,40 @@ import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.OAuth;
+import cgeo.geocaching.network.OAuthTokens;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
+import cgeo.geocaching.utils.JsonUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.SynchronizedDateFormat;
import ch.boye.httpclientandroidlib.HttpResponse;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
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;
import android.net.Uri;
+import java.io.IOException;
import java.text.ParseException;
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.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
+import java.util.regex.Pattern;
final class OkapiClient {
@@ -132,6 +136,8 @@ final class OkapiClient {
private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest";
private static final String METHOD_RETRIEVE_CACHES = "services/caches/geocaches";
+ private static final Pattern PATTERN_TIMEZONE = Pattern.compile("([+-][01][0-9]):([03])0");
+
public static Geocache getCache(final String geoCode) {
final Parameters params = new Parameters("cache_code", geoCode);
final IConnector connector = ConnectorFactory.getConnector(geoCode);
@@ -209,10 +215,15 @@ final class OkapiClient {
}
addFilterParams(valueMap, connector, my);
- params.add("search_params", new JSONObject(valueMap).toString());
+ try {
+ params.add("search_params", JsonUtils.writer.writeValueAsString(valueMap));
+ } catch (final JsonProcessingException e) {
+ Log.e("requestCaches", e);
+ return Collections.emptyList();
+ }
addRetrieveParams(params, connector);
- final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data;
+ final ObjectNode data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data;
if (data == null) {
return Collections.emptyList();
@@ -245,7 +256,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).data;
+ final ObjectNode data = request(connector, OkapiService.SERVICE_MARK_CACHE, params).data;
if (data == null) {
return false;
@@ -269,68 +280,58 @@ final class OkapiClient {
params.add("password", logPassword);
}
- final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data;
+ final ObjectNode data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data;
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"));
+ if (data.get("success").asBoolean()) {
+ return new LogResult(StatusCode.NO_ERROR, data.get("log_uuid").asText());
}
return new LogResult(StatusCode.LOG_POST_ERROR, "");
- } catch (final JSONException e) {
+ } catch (final NullPointerException e) {
Log.e("OkapiClient.postLog", e);
}
return new LogResult(StatusCode.LOG_POST_ERROR, "");
}
- private static List<Geocache> parseCaches(final JSONObject response) {
+ private static List<Geocache> parseCaches(final ObjectNode response) {
try {
// Check for empty result
- final String result = response.getString("results");
- if (StringUtils.isBlank(result) || StringUtils.equals(result, "[]")) {
+ final JsonNode results = response.path("results");
+ if (!results.isObject()) {
return Collections.emptyList();
}
// Get and iterate result list
- final JSONObject cachesResponse = response.getJSONObject("results");
- if (cachesResponse != null) {
- final List<Geocache> caches = new ArrayList<>(cachesResponse.length());
- final Iterator<?> keys = cachesResponse.keys();
- while (keys.hasNext()) {
- final Object next = keys.next();
- if (next instanceof String) {
- final String key = (String) next;
- final Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key));
- caches.add(cache);
- }
- }
- return caches;
+ final List<Geocache> caches = new ArrayList<>(results.size());
+ for (final JsonNode cache: results) {
+ caches.add(parseSmallCache((ObjectNode) cache));
}
- } catch (final JSONException e) {
+ return caches;
+ } catch (ClassCastException | NullPointerException e) {
Log.e("OkapiClient.parseCachesResult", e);
}
return Collections.emptyList();
}
- private static Geocache parseSmallCache(final JSONObject response) {
+ private static Geocache parseSmallCache(final ObjectNode response) {
final Geocache cache = new Geocache();
cache.setReliableLatLon(true);
try {
-
parseCoreCache(response, cache);
-
DataStore.saveCache(cache, EnumSet.of(SaveFlag.CACHE));
- } catch (final JSONException e) {
+ } catch (final NullPointerException e) {
+ // FIXME: here we may return a partially filled cache
Log.e("OkapiClient.parseSmallCache", e);
}
return cache;
}
- private static Geocache parseCache(final JSONObject response) {
+ private static Geocache parseCache(final ObjectNode response) {
final Geocache cache = new Geocache();
cache.setReliableLatLon(true);
try {
@@ -338,28 +339,27 @@ final class OkapiClient {
parseCoreCache(response, cache);
// not used: url
- final JSONObject ownerObject = response.getJSONObject(CACHE_OWNER);
- final String owner = parseUser(ownerObject);
+ final String owner = parseUser(response.get(CACHE_OWNER));
cache.setOwnerDisplayName(owner);
// OpenCaching has no distinction between user id and user display name. Set the ID anyway to simplify c:geo workflows.
cache.setOwnerUserId(owner);
- cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS));
- cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS));
+ cache.getLogCounts().put(LogType.FOUND_IT, response.get(CACHE_FOUNDS).asInt());
+ cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.get(CACHE_NOTFOUNDS).asInt());
// only current Api
- cache.getLogCounts().put(LogType.WILL_ATTEND, response.optInt(CACHE_WILLATTENDS));
+ cache.getLogCounts().put(LogType.WILL_ATTEND, response.path(CACHE_WILLATTENDS).asInt());
- if (!response.isNull(CACHE_RATING)) {
- cache.setRating((float) response.getDouble(CACHE_RATING));
+ if (response.has(CACHE_RATING)) {
+ cache.setRating((float) response.get(CACHE_RATING).asDouble());
}
- cache.setVotes(response.getInt(CACHE_VOTES));
+ cache.setVotes(response.get(CACHE_VOTES).asInt());
- cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS));
+ cache.setFavoritePoints(response.get(CACHE_RECOMMENDATIONS).asInt());
// not used: req_password
// Prepend gc-link to description if available
final StringBuilder description = new StringBuilder(500);
- if (!response.isNull("gc_code")) {
- final String gccode = response.getString("gc_code");
+ if (response.hasNonNull("gc_code")) {
+ final String gccode = response.get("gc_code").asText();
description.append(CgeoApplication.getInstance().getResources()
.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()))
.append(": <a href=\"http://coord.info/")
@@ -368,71 +368,70 @@ final class OkapiClient {
.append(gccode)
.append("</a><br /><br />");
}
- description.append(response.getString(CACHE_DESCRIPTION));
+ description.append(response.get(CACHE_DESCRIPTION).asText());
cache.setDescription(description.toString());
// currently the hint is delivered as HTML (contrary to OKAPI documentation), so we can store it directly
- cache.setHint(response.getString(CACHE_HINT));
+ cache.setHint(response.get(CACHE_HINT).asText());
// not used: hints
- final JSONArray images = response.getJSONArray(CACHE_IMAGES);
+ final ArrayNode images = (ArrayNode) response.get(CACHE_IMAGES);
if (images != null) {
- for (int i = 0; i < images.length(); i++) {
- 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());
+ for (final JsonNode imageResponse: images) {
+ final String title = imageResponse.get(CACHE_IMAGE_CAPTION).asText();
+ final String url = absoluteUrl(imageResponse.get(CACHE_IMAGE_URL).asText(), 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), response.optJSONArray(CACHE_ATTR_ACODES)));
+ cache.setAttributes(parseAttributes((ArrayNode) response.path(CACHE_ATTRNAMES), (ArrayNode) response.get(CACHE_ATTR_ACODES)));
//TODO: Store license per cache
//cache.setLicense(response.getString("attribution_note"));
- cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false);
+ cache.setWaypoints(parseWaypoints((ArrayNode) response.path(CACHE_WPTS)), false);
- cache.setInventory(parseTrackables(response.getJSONArray(CACHE_TRACKABLES)));
+ cache.setInventory(parseTrackables((ArrayNode) response.path(CACHE_TRACKABLES)));
- if (!response.isNull(CACHE_IS_WATCHED)) {
- cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED));
+ if (response.has(CACHE_IS_WATCHED)) {
+ cache.setOnWatchlist(response.get(CACHE_IS_WATCHED).asBoolean());
}
- if (!response.isNull(CACHE_MY_NOTES)) {
- cache.setPersonalNote(response.getString(CACHE_MY_NOTES));
+ if (response.hasNonNull(CACHE_MY_NOTES)) {
+ cache.setPersonalNote(response.get(CACHE_MY_NOTES).asText());
cache.parseWaypointsFromNote();
}
- cache.setLogPasswordRequired(response.getBoolean(CACHE_REQ_PASSWORD));
+ cache.setLogPasswordRequired(response.get(CACHE_REQ_PASSWORD).asBoolean());
cache.setDetailedUpdatedNow();
// save full detailed caches
DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB));
- DataStore.saveLogsWithoutTransaction(cache.getGeocode(), parseLogs(response.getJSONArray(CACHE_LATEST_LOGS)));
- } catch (final JSONException e) {
+ DataStore.saveLogsWithoutTransaction(cache.getGeocode(), parseLogs((ArrayNode) response.path(CACHE_LATEST_LOGS)));
+ } catch (ClassCastException | NullPointerException e) {
Log.e("OkapiClient.parseCache", e);
}
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));
+ private static void parseCoreCache(final ObjectNode response, final Geocache cache) {
+ cache.setGeocode(response.get(CACHE_CODE).asText());
+ cache.setName(response.get(CACHE_NAME).asText());
// not used: names
- setLocation(cache, response.getString(CACHE_LOCATION));
- cache.setType(getCacheType(response.getString(CACHE_TYPE)));
+ setLocation(cache, response.get(CACHE_LOCATION).asText());
+ cache.setType(getCacheType(response.get(CACHE_TYPE).asText()));
- final String status = response.getString(CACHE_STATUS);
+ final String status = response.get(CACHE_STATUS).asText();
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.setDifficulty((float) response.get(CACHE_DIFFICULTY).asDouble());
+ cache.setTerrain((float) response.get(CACHE_TERRAIN).asDouble());
- cache.setInventoryItems(response.getInt(CACHE_TRACKABLES_COUNT));
+ cache.setInventoryItems(response.get(CACHE_TRACKABLES_COUNT).asInt());
- if (!response.isNull(CACHE_IS_FOUND)) {
- cache.setFound(response.getBoolean(CACHE_IS_FOUND));
+ if (response.has(CACHE_IS_FOUND)) {
+ cache.setFound(response.get(CACHE_IS_FOUND).asBoolean());
}
- cache.setHidden(parseDate(response.getString(CACHE_HIDDEN)));
+ cache.setHidden(parseDate(response.get(CACHE_HIDDEN).asText()));
}
private static String absoluteUrl(final String url, final String geocode) {
@@ -448,38 +447,36 @@ final class OkapiClient {
return url;
}
- private static String parseUser(final JSONObject user) throws JSONException {
- return user.getString(USER_USERNAME);
+ private static String parseUser(final JsonNode user) {
+ return user.get(USER_USERNAME).asText();
}
- private static List<LogEntry> parseLogs(final JSONArray logsJSON) {
+ private static List<LogEntry> parseLogs(final ArrayNode logsJSON) {
final List<LogEntry> result = new LinkedList<>();
- for (int i = 0; i < logsJSON.length(); i++) {
+ for (final JsonNode logResponse: logsJSON) {
try {
- final JSONObject logResponse = logsJSON.getJSONObject(i);
final LogEntry log = new LogEntry(
- parseUser(logResponse.getJSONObject(LOG_USER)),
- parseDate(logResponse.getString(LOG_DATE)).getTime(),
- parseLogType(logResponse.getString(LOG_TYPE)),
- logResponse.getString(LOG_COMMENT).trim());
+ parseUser(logResponse.get(LOG_USER)),
+ parseDate(logResponse.get(LOG_DATE).asText()).getTime(),
+ parseLogType(logResponse.get(LOG_TYPE).asText()),
+ logResponse.get(LOG_COMMENT).asText().trim());
result.add(log);
- } catch (final JSONException e) {
+ } catch (final NullPointerException e) {
Log.e("OkapiClient.parseLogs", e);
}
}
return result;
}
- private static List<Waypoint> parseWaypoints(final JSONArray wptsJson) {
+ private static List<Waypoint> parseWaypoints(final ArrayNode wptsJson) {
List<Waypoint> result = null;
- for (int i = 0; i < wptsJson.length(); i++) {
+ for (final JsonNode wptResponse: wptsJson) {
try {
- final JSONObject wptResponse = wptsJson.getJSONObject(i);
- final Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME),
- parseWptType(wptResponse.getString(WPT_TYPE)),
+ final Waypoint wpt = new Waypoint(wptResponse.get(WPT_NAME).asText(),
+ parseWptType(wptResponse.get(WPT_TYPE).asText()),
false);
- wpt.setNote(wptResponse.getString(WPT_DESCRIPTION));
- final Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION));
+ wpt.setNote(wptResponse.get(WPT_DESCRIPTION).asText());
+ final Geopoint pt = parseCoords(wptResponse.get(WPT_LOCATION).asText());
if (pt != null) {
wpt.setCoords(pt);
}
@@ -488,26 +485,25 @@ final class OkapiClient {
}
wpt.setPrefix(wpt.getName());
result.add(wpt);
- } catch (final JSONException e) {
+ } catch (final NullPointerException e) {
Log.e("OkapiClient.parseWaypoints", e);
}
}
return result;
}
- private static List<Trackable> parseTrackables(final JSONArray trackablesJson) {
- if (trackablesJson.length() == 0) {
+ private static List<Trackable> parseTrackables(final ArrayNode trackablesJson) {
+ if (trackablesJson.size() == 0) {
return Collections.emptyList();
}
final List<Trackable> result = new ArrayList<>();
- for (int i = 0; i < trackablesJson.length(); i++) {
+ for (final JsonNode trackableResponse: trackablesJson) {
try {
- final JSONObject trackableResponse = trackablesJson.getJSONObject(i);
final Trackable trk = new Trackable();
- trk.setGeocode(trackableResponse.getString(TRK_GEOCODE));
- trk.setName(trackableResponse.getString(TRK_NAME));
+ trk.setGeocode(trackableResponse.get(TRK_GEOCODE).asText());
+ trk.setName(trackableResponse.get(TRK_NAME).asText());
result.add(trk);
- } catch (final JSONException e) {
+ } catch (final NullPointerException e) {
Log.e("OkapiClient.parseWaypoints", e);
// Don't overwrite internal state with possibly partial result
return null;
@@ -576,7 +572,7 @@ final class OkapiClient {
}
private static Date parseDate(final String date) {
- final String strippedDate = date.replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
+ final String strippedDate = PATTERN_TIMEZONE.matcher(date).replaceAll("$1$20");
try {
return ISO8601DATEFORMAT.parse(strippedDate);
} catch (final ParseException e) {
@@ -595,14 +591,14 @@ final class OkapiClient {
return null;
}
- private static List<String> parseAttributes(final JSONArray nameList, final JSONArray acodeList) {
+ private static List<String> parseAttributes(final ArrayNode nameList, final ArrayNode acodeList) {
final List<String> result = new ArrayList<>();
- for (int i = 0; i < nameList.length(); i++) {
+ for (int i = 0; i < nameList.size(); i++) {
try {
- final String name = nameList.getString(i);
- final int acode = acodeList != null ? Integer.parseInt(acodeList.getString(i).substring(1)) : CacheAttribute.NO_ID;
+ final String name = nameList.get(i).asText();
+ final int acode = acodeList != null ? Integer.parseInt(acodeList.get(i).asText().substring(1)) : CacheAttribute.NO_ID;
final CacheAttribute attr = CacheAttribute.getByOcACode(acode);
if (attr != null) {
@@ -610,7 +606,7 @@ final class OkapiClient {
} else {
result.add(name);
}
- } catch (final JSONException e) {
+ } catch (final NullPointerException e) {
Log.e("OkapiClient.parseAttributes", e);
}
}
@@ -624,27 +620,27 @@ final class OkapiClient {
cache.setCoords(new Geopoint(latitude, longitude));
}
- private static CacheSize getCacheSize(final JSONObject response) {
- if (response.isNull(CACHE_SIZE2)) {
+ private static CacheSize getCacheSize(final ObjectNode response) {
+ if (!response.has(CACHE_SIZE2)) {
return getCacheSizeDeprecated(response);
}
try {
- final String size = response.getString(CACHE_SIZE2);
+ final String size = response.get(CACHE_SIZE2).asText();
return CacheSize.getById(size);
- } catch (final JSONException e) {
+ } catch (final NullPointerException e) {
Log.e("OkapiClient.getCacheSize", e);
return getCacheSizeDeprecated(response);
}
}
- private static CacheSize getCacheSizeDeprecated(final JSONObject response) {
- if (response.isNull(CACHE_SIZE_DEPRECATED)) {
+ private static CacheSize getCacheSizeDeprecated(final ObjectNode response) {
+ if (!response.has(CACHE_SIZE_DEPRECATED)) {
return CacheSize.NOT_CHOSEN;
}
double size = 0;
try {
- size = response.getDouble(CACHE_SIZE_DEPRECATED);
- } catch (final JSONException e) {
+ size = response.get(CACHE_SIZE_DEPRECATED).asDouble();
+ } catch (final NullPointerException e) {
Log.e("OkapiClient.getCacheSize", e);
}
switch ((int) Math.round(size)) {
@@ -732,19 +728,22 @@ final class OkapiClient {
@NonNull
private static JSONResult request(final OCApiConnector connector, final OkapiService service, final Parameters params) {
if (connector == null) {
- return new JSONResult(null);
+ return new JSONResult("unknown OKAPI connector");
}
final String host = connector.getHost();
if (StringUtils.isBlank(host)) {
- return new JSONResult(null);
+ return new JSONResult("unknown OKAPI connector host");
}
params.add("langpref", getPreferredLanguage());
if (connector.getSupportedAuthLevel() == OAuthLevel.Level3) {
- final ImmutablePair<String, String> tokens = Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId());
- OAuth.signOAuth(host, service.methodName, "GET", false, params, tokens.left, tokens.right, connector.getCK(), connector.getCS());
+ final OAuthTokens tokens = new OAuthTokens(connector);
+ if (!tokens.isValid()) {
+ return new JSONResult("invalid oauth tokens");
+ }
+ OAuth.signOAuth(host, service.methodName, "GET", false, params, tokens, connector.getCK(), connector.getCS());
} else {
connector.addAuthentication(params);
}
@@ -810,16 +809,7 @@ final class OkapiClient {
return null;
}
- final JSONObject data = result.data;
- if (!data.isNull(USER_UUID)) {
- try {
- return data.getString(USER_UUID);
- } catch (final JSONException e) {
- Log.e("OkapiClient.getUserUUID - uuid", e);
- }
- }
-
- return null;
+ return result.data.path(USER_UUID).asText(null);
}
public static UserInfo getUserInfo(final OCApiLiveConnector connector) {
@@ -833,31 +823,11 @@ final class OkapiClient {
return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.getFromOkapiError(error.getResult()));
}
- final JSONObject data = result.data;
-
- String name = StringUtils.EMPTY;
- boolean successUserName = false;
-
- if (!data.isNull(USER_USERNAME)) {
- try {
- name = data.getString(USER_USERNAME);
- successUserName = true;
- } catch (final JSONException e) {
- Log.e("OkapiClient.getUserInfo - name", e);
- }
- }
-
- int finds = 0;
- boolean successFinds = false;
-
- if (!data.isNull(USER_CACHES_FOUND)) {
- try {
- finds = data.getInt(USER_CACHES_FOUND);
- successFinds = true;
- } catch (final JSONException e) {
- Log.e("OkapiClient.getUserInfo - finds", e);
- }
- }
+ final ObjectNode data = result.data;
+ final boolean successUserName = data.has(USER_USERNAME);
+ final String name = data.path(USER_USERNAME).asText();
+ final boolean successFinds = data.has(USER_CACHES_FOUND);
+ final int finds = data.path(USER_CACHES_FOUND).asInt();
return new UserInfo(name, finds, successUserName && successFinds ? UserInfoStatus.SUCCESSFUL : UserInfoStatus.FAILED);
}
@@ -874,7 +844,7 @@ final class OkapiClient {
if (!result.isSuccess) {
return new OkapiError(result.data);
}
- return new OkapiError(new JSONObject());
+ return new OkapiError(new ObjectNode(JsonUtils.factory));
}
/**
@@ -884,21 +854,27 @@ final class OkapiClient {
private static class JSONResult {
public final boolean isSuccess;
- public final JSONObject data;
+ public final ObjectNode data;
public JSONResult(final @Nullable HttpResponse response) {
- final boolean isSuccess = Network.isSuccess(response);
+ final boolean isRequestSuccessful = Network.isSuccess(response);
final String responseData = Network.getResponseDataAlways(response);
- JSONObject data = null;
+ ObjectNode tempData = null;
if (responseData != null) {
try {
- data = new JSONObject(responseData);
- } catch (final JSONException e) {
+ tempData = (ObjectNode) JsonUtils.reader.readTree(responseData);
+ } catch (IOException | ClassCastException e) {
Log.w("JSONResult", e);
}
}
- this.data = data;
- this.isSuccess = isSuccess && data != null;
+ data = tempData;
+ isSuccess = isRequestSuccessful && tempData != null;
+ }
+
+ public JSONResult(final @NonNull String errorMessage) {
+ isSuccess = false;
+ data = new ObjectNode(JsonUtils.factory);
+ data.putObject("error").put("developer_message", errorMessage);
}
}
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiError.java b/main/src/cgeo/geocaching/connector/oc/OkapiError.java
index 7faf2c7..b847207 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiError.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiError.java
@@ -2,11 +2,11 @@ package cgeo.geocaching.connector.oc;
import cgeo.geocaching.utils.Log;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
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
@@ -26,7 +26,7 @@ public class OkapiError {
@NonNull private final OkapiErrors state;
@NonNull private final String message;
- public OkapiError(@Nullable JSONObject data) {
+ public OkapiError(@Nullable ObjectNode data) {
// A null-response is by definition an error (some exception occurred somewhere in the flow)
if (data == null) {
@@ -39,10 +39,10 @@ public class OkapiError {
String localmessage = null;
OkapiErrors localstate = OkapiErrors.UNSPECIFIED;
try {
- JSONObject error = data.getJSONObject("error");
+ final ObjectNode error = (ObjectNode) data.get("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");
+ final String reason = error.get("reason_stack").asText();
if (StringUtils.contains(reason, "invalid_oauth_request")) {
if (StringUtils.contains(reason, "invalid_timestamp")) {
localstate = OkapiErrors.INVALID_TIMESTAMP;
@@ -53,10 +53,10 @@ public class OkapiError {
}
// Check if we can extract a message as well
if (error.has("developer_message")) {
- localmessage = error.getString("developer_message");
+ localmessage = error.get("developer_message").asText();
assert localmessage != null; // by virtue of defaultString
}
- } catch (JSONException ex) {
+ } catch (ClassCastException | NullPointerException ex) {
Log.d("OkapiError: Failed to parse JSON", ex);
localstate = OkapiErrors.UNSPECIFIED;
}
diff --git a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
index b2afff5..21207ec 100644
--- a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
+++ b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
@@ -39,9 +39,9 @@ public class OpenCachingApi {
return null;
}
- private static HttpResponse getRequest(String string, Parameters parameters) {
+ private static HttpResponse getRequest(final String uri, final Parameters parameters) {
parameters.add("Authorization", DEV_KEY);
- return Network.getRequest(string, parameters);
+ return Network.getRequest(uri, parameters);
}
private static Collection<Geocache> importCachesFromResponse(final HttpResponse response, final boolean isDetailed) {
@@ -50,7 +50,7 @@ public class OpenCachingApi {
}
Collection<Geocache> caches;
try {
- caches = new OXGPXParser(StoredList.TEMPORARY_LIST_ID, isDetailed).parse(response.getEntity().getContent(), null);
+ caches = new OXGPXParser(StoredList.TEMPORARY_LIST.id, isDetailed).parse(response.getEntity().getContent(), null);
} catch (Exception e) {
Log.e("Error importing from OpenCaching.com", e);
return Collections.emptyList();