diff options
47 files changed, 1278 insertions, 1476 deletions
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index f07155d..8362662 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -7,6 +7,7 @@ import cgeo.geocaching.apps.cache.GeneralAppsFactory; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; @@ -38,6 +39,8 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; @@ -579,7 +582,7 @@ public class CacheDetailActivity extends AbstractActivity { cache.openInBrowser(this); return true; } else if (menuItem == MENU_CACHES_AROUND) { - cachesAround(); + cgeocaches.startActivityCachesAround(this, cache.getCoords()); return true; } else if (menuItem == MENU_CALENDAR) { addToCalendarWithIntent(); @@ -606,7 +609,7 @@ public class CacheDetailActivity extends AbstractActivity { private class LoadCacheHandler extends CancellableHandler { @Override public void handleRegularMessage(final Message msg) { - if (cgBase.UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { + if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { if (search == null) { @@ -772,25 +775,43 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - search = cgBase.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler); + search = cgCache.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler); handler.sendMessage(Message.obtain()); } } /** - * Starts activity to search for caches near this cache. + * Indicates whether the specified action can be used as an intent. This + * method queries the package manager for installed packages that can + * respond to an intent with the specified action. If no suitable package is + * found, this method returns false. * - * Also finishes this activity. + * @param context + * The application's environment. + * @param action + * The Intent action to check for availability. + * @param uri + * The Intent URI to check for availability. + * + * @return True if an Intent with the specified action can be sent and + * responded to, false otherwise. */ - private void cachesAround() { - cgeocaches.startActivityCachesAround(this, cache.getCoords()); - - finish(); + private static boolean isIntentAvailable(Context context, String action, Uri uri) { + final PackageManager packageManager = context.getPackageManager(); + final Intent intent; + if (uri == null) { + intent = new Intent(action); + } else { + intent = new Intent(action, uri); + } + List<ResolveInfo> list = packageManager.queryIntentActivities(intent, + PackageManager.MATCH_DEFAULT_ONLY); + return list.size() > 0; } private void addToCalendarWithIntent() { - final boolean calendarAddOnAvailable = cgBase.isIntentAvailable(this, ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST)); + final boolean calendarAddOnAvailable = isIntentAvailable(this, ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST)); if (calendarAddOnAvailable) { final Parameters params = new Parameters( @@ -1437,7 +1458,7 @@ public class CacheDetailActivity extends AbstractActivity { if (cache.getHiddenDate() != null) { long time = cache.getHiddenDate().getTime(); if (time > 0) { - String dateString = cgBase.formatFullDate(time); + String dateString = Formatter.formatFullDate(time); if (cache.isEventCache()) { dateString = DateUtils.formatDateTime(cgeoapplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + dateString; } @@ -1536,7 +1557,7 @@ public class CacheDetailActivity extends AbstractActivity { private class StoreCacheHandler extends CancellableHandler { @Override public void handleRegularMessage(Message msg) { - if (cgBase.UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { + if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { storeThread = null; @@ -1554,7 +1575,7 @@ public class CacheDetailActivity extends AbstractActivity { private class RefreshCacheHandler extends CancellableHandler { @Override public void handleRegularMessage(Message msg) { - if (cgBase.UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { + if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { refreshThread = null; @@ -1638,7 +1659,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - cgBase.refreshCache(CacheDetailActivity.this, cache.getGeocode(), cache.getListId(), handler); + cache.refresh(CacheDetailActivity.this, cache.getListId(), handler); handler.sendEmptyMessage(0); } @@ -1668,7 +1689,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - cgBase.dropCache(cache, handler); + cache.drop(handler); } } @@ -1724,7 +1745,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - handler.sendEmptyMessage(cgBase.addToWatchlist(cache)); + handler.sendEmptyMessage(GCParser.addToWatchlist(cache)); } } @@ -1738,7 +1759,7 @@ public class CacheDetailActivity extends AbstractActivity { @Override public void run() { - handler.sendEmptyMessage(cgBase.removeFromWatchlist(cache)); + handler.sendEmptyMessage(GCParser.removeFromWatchlist(cache)); } } @@ -2168,7 +2189,7 @@ public class CacheDetailActivity extends AbstractActivity { } } - view.setAdapter(new ArrayAdapter<cgLog>(CacheDetailActivity.this, R.layout.cacheview_logs_item, cache.getLogs(allLogs)) { + view.setAdapter(new ArrayAdapter<LogEntry>(CacheDetailActivity.this, R.layout.cacheview_logs_item, cache.getLogs(allLogs)) { final UserActionsClickListener userActionsClickListener = new UserActionsClickListener(); final DecryptTextClickListener decryptTextClickListener = new DecryptTextClickListener(); @@ -2184,10 +2205,10 @@ public class CacheDetailActivity extends AbstractActivity { rowView.setTag(holder); } - final cgLog log = getItem(position); + final LogEntry log = getItem(position); if (log.date > 0) { - holder.date.setText(cgBase.formatShortDate(log.date)); + holder.date.setText(Formatter.formatShortDate(log.date)); holder.date.setVisibility(View.VISIBLE); } else { holder.date.setVisibility(View.GONE); @@ -2217,10 +2238,10 @@ public class CacheDetailActivity extends AbstractActivity { } // images - if (CollectionUtils.isNotEmpty(log.logImages)) { + if (log.hasLogImages()) { List<String> titles = new ArrayList<String>(5); - for (cgImage image : log.logImages) { + for (cgImage image : log.getLogImages()) { if (StringUtils.isNotBlank(image.getTitle())) { titles.add(image.getTitle()); } @@ -2234,7 +2255,7 @@ public class CacheDetailActivity extends AbstractActivity { holder.images.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - cgeoimages.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<cgImage>(log.logImages)); + cgeoimages.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<cgImage>(log.getLogImages())); } }); } else { @@ -2491,4 +2512,11 @@ public class CacheDetailActivity extends AbstractActivity { cachesIntent.putExtra("name", cacheName); context.startActivity(cachesIntent); } + + public static void startActivityGuid(final Context context, final String guid, final String cacheName) { + final Intent cacheIntent = new Intent(context, CacheDetailActivity.class); + cacheIntent.putExtra("guid", guid); + cacheIntent.putExtra("name", cacheName); + context.startActivity(cacheIntent); + } } diff --git a/main/src/cgeo/geocaching/cgDestination.java b/main/src/cgeo/geocaching/Destination.java index 1e5253c..441e959 100644 --- a/main/src/cgeo/geocaching/cgDestination.java +++ b/main/src/cgeo/geocaching/Destination.java @@ -2,20 +2,20 @@ package cgeo.geocaching; import cgeo.geocaching.geopoint.Geopoint; -public class cgDestination implements ICoordinates { +public final class Destination implements ICoordinates { final private long id; final private long date; final private Geopoint coords; - public cgDestination(long id, long date, final Geopoint coords) { + public Destination(long id, long date, final Geopoint coords) { this.id = id; this.date = date; this.coords = coords; } - public cgDestination withDate(final long date) { - return new cgDestination(id, date, coords); + public Destination(final Geopoint coords) { + this(0, System.currentTimeMillis(), coords); } public long getDate() { @@ -34,7 +34,7 @@ public class cgDestination implements ICoordinates { @Override public boolean equals(final Object obj) { - return obj != null && obj instanceof cgDestination && ((cgDestination) obj).coords.equals(coords); + return obj != null && obj instanceof Destination && ((Destination) obj).coords.equals(coords); } public long getId() { diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java new file mode 100644 index 0000000..3f6ed74 --- /dev/null +++ b/main/src/cgeo/geocaching/LogEntry.java @@ -0,0 +1,69 @@ +package cgeo.geocaching; + +import cgeo.geocaching.enumerations.LogType; + +import org.apache.commons.collections.CollectionUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class LogEntry { + /** + * avoid creating new empty lists all the time using this constant. We could also return Collections.EMPTY_LIST + * using a cast, but that might trigger static code analysis tools. + */ + private static final List<cgImage> EMPTY_LIST = Collections.emptyList(); + public int id = 0; + public LogType type = LogType.LOG_NOTE; // note + public String author = ""; + public String log = ""; + public long date = 0; + public int found = -1; + /** Friend's log entry */ + public boolean friend = false; + private List<cgImage> logImages = null; + public String cacheName = ""; // used for trackables + public String cacheGuid = ""; // used for trackables + + @Override + public int hashCode() { + return (int) date * type.hashCode() * author.hashCode() * log.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof LogEntry)) { + return false; + } + final LogEntry otherLog = (LogEntry) obj; + return date == otherLog.date && + type == otherLog.type && + author.compareTo(otherLog.author) == 0 && + log.compareTo(otherLog.log) == 0; + } + + public void addLogImage(final cgImage image) { + if (logImages == null) { + logImages = new ArrayList<cgImage>(); + } + logImages.add(image); + } + + /** + * @return the log images or an empty list, never <code>null</code> + */ + public List<cgImage> getLogImages() { + if (logImages == null) { + return EMPTY_LIST; + } + return logImages; + } + + public boolean hasLogImages() { + return CollectionUtils.isNotEmpty(logImages); + } +} diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index 556ef32..2e56c7c 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -1,5 +1,6 @@ package cgeo.geocaching; +import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; @@ -128,7 +129,7 @@ public class SearchResult implements Parcelable { } public void setViewstates(String[] viewstates) { - if (cgBase.isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { return; } diff --git a/main/src/cgeo/geocaching/TrackableLog.java b/main/src/cgeo/geocaching/TrackableLog.java new file mode 100644 index 0000000..8e2ad90 --- /dev/null +++ b/main/src/cgeo/geocaching/TrackableLog.java @@ -0,0 +1,18 @@ +package cgeo.geocaching; + +import cgeo.geocaching.enumerations.LogTypeTrackable; + +public final class TrackableLog { + public TrackableLog(String trackCode, String name, int id, int ctl) { + this.trackCode = trackCode; + this.name = name; + this.id = id; + this.ctl = ctl; + } + + public final int ctl; + public final int id; + public final String trackCode; + public final String name; + public LogTypeTrackable action = LogTypeTrackable.DO_NOTHING; // base.logTrackablesAction - no action +} diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index 5d5d8ba..a2fde26 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -1,6 +1,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; @@ -13,6 +14,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.DateDialog; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; @@ -64,7 +66,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D private List<LogType> possibleLogTypes = new ArrayList<LogType>(); private String[] viewstates = null; private boolean gettingViewstate = true; - private List<cgTrackableLog> trackables = null; + private List<TrackableLog> trackables = null; private Calendar date = Calendar.getInstance(); private LogType typeSelected = LogType.LOG_UNKNOWN; private int attempts = 0; @@ -88,13 +90,13 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D showToast(res.getString(R.string.info_log_type_changed)); } - if (cgBase.isEmpty(viewstates) && attempts < 2) { + if (Login.isEmpty(viewstates) && attempts < 2) { final LoadDataThread thread; thread = new LoadDataThread(); thread.start(); return; - } else if (cgBase.isEmpty(viewstates) && attempts >= 2) { + } else if (Login.isEmpty(viewstates) && attempts >= 2) { showToast(res.getString(R.string.err_log_load_data)); showProgress(false); @@ -114,7 +116,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory); inventoryView.removeAllViews(); - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.visit_trackable, null); ((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode); @@ -382,7 +384,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D } else { final int realViewId = ((LinearLayout) findViewById(viewId)).getId(); - for (final cgTrackableLog tb : trackables) { + for (final TrackableLog tb : trackables) { if (tb.id == realViewId) { menu.setHeaderTitle(tb.name); } @@ -419,7 +421,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D } tbText.setText(res.getString(logType.resourceId) + " ▼"); } - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { tb.action = logType; } tbChanged = true; @@ -442,7 +444,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D return false; } - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { if (tb.id == group) { tbChanged = true; @@ -475,7 +477,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D possibleLogTypes = cache.getPossibleLogTypes(); - final cgLog log = app.loadLogOffline(geocode); + final LogEntry log = app.loadLogOffline(geocode); if (log != null) { typeSelected = log.type; date.setTime(new Date(log.date)); @@ -507,7 +509,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D }); final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); dateButton.setOnClickListener(new DateListener()); final EditText logView = (EditText) findViewById(R.id.log); @@ -522,7 +524,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D lastState.restore(this); } - if (cgBase.isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { enablePostButton(false); new LoadDataThread().start(); } else { @@ -545,7 +547,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D date = dateIn; final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); } public void setType(LogType type) { @@ -609,7 +611,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D setType(typeSelected); final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); dateButton.setOnClickListener(new DateListener()); final EditText logView = (EditText) findViewById(R.id.log); @@ -659,9 +661,9 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/seek/log.aspx", params)); viewstates = Login.getViewstates(page); - trackables = cgBase.parseTrackableLog(page); + trackables = GCParser.parseTrackableLog(page); - final List<LogType> typesPre = cgBase.parseTypes(page); + final List<LogType> typesPre = GCParser.parseTypes(page); if (CollectionUtils.isNotEmpty(typesPre)) { possibleLogTypes.clear(); possibleLogTypes.addAll(typesPre); @@ -695,12 +697,12 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D public StatusCode postLogFn(String log) { try { - final StatusCode status = cgBase.postLog(geocode, cacheid, viewstates, typeSelected, + final StatusCode status = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log, trackables); if (status == StatusCode.NO_ERROR) { - final cgLog logNow = new cgLog(); + final LogEntry logNow = new LogEntry(); logNow.author = Settings.getUsername(); logNow.date = date.getTimeInMillis(); logNow.type = typeSelected; @@ -765,7 +767,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D private class ActivityState { private final String[] viewstates; - private final List<cgTrackableLog> trackables; + private final List<TrackableLog> trackables; private final int attempts; private final List<LogType> possibleLogTypes; private final LogType typeSelected; diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index 8985955..8ddd21a 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -2,7 +2,6 @@ package cgeo.geocaching.activity; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.compatibility.Compatibility; @@ -85,8 +84,6 @@ public abstract class AbstractActivity extends Activity implements IAbstractActi res = this.getResources(); app = (cgeoapplication) this.getApplication(); - cgBase.initialize(app); - // Restore cookie store if needed Cookies.restoreCookieStore(Settings.getCookieStore()); diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java index b3bbb3f..7af75b8 100644 --- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java @@ -1,6 +1,5 @@ package cgeo.geocaching.activity; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.compatibility.Compatibility; @@ -73,7 +72,6 @@ public abstract class AbstractListActivity extends ListActivity implements // init res = this.getResources(); app = (cgeoapplication) this.getApplication(); - cgBase.initialize(app); ActivityMixin.keepScreenOn(this, keepScreenOn); } diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java index 8eeee8d..f95fb2c 100644 --- a/main/src/cgeo/geocaching/cgCache.java +++ b/main/src/cgeo/geocaching/cgCache.java @@ -9,11 +9,14 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; +import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointParser; +import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; @@ -26,6 +29,8 @@ import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.Handler; +import android.os.Message; +import android.text.Html; import android.text.Spannable; import java.util.ArrayList; @@ -87,7 +92,7 @@ public class cgCache implements ICache, IWaypoint { private List<String> attributes = null; private List<cgWaypoint> waypoints = null; private ArrayList<cgImage> spoilers = null; - private List<cgLog> logs = null; + private List<LogEntry> logs = null; private List<cgTrackable> inventory = null; private Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>(); private boolean logOffline = false; @@ -381,7 +386,7 @@ public class cgCache implements ICache, IWaypoint { * * @return true: page contains guid of cache, false: otherwise */ - boolean isGuidContainedInPage(final String page) { + public boolean isGuidContainedInPage(final String page) { if (StringUtils.isBlank(page)) { return false; } @@ -933,7 +938,7 @@ public class cgCache implements ICache, IWaypoint { return false; } - public List<cgLog> getLogs() { + public List<LogEntry> getLogs() { return getLogs(true); } @@ -942,15 +947,15 @@ public class cgCache implements ICache, IWaypoint { * true for all logs, false for friend logs only * @return the logs with all entries or just the entries of the friends, never <code>null</code> */ - public List<cgLog> getLogs(boolean allLogs) { + public List<LogEntry> getLogs(boolean allLogs) { if (logs == null) { return Collections.emptyList(); } if (allLogs) { return logs; } - ArrayList<cgLog> friendLogs = new ArrayList<cgLog>(); - for (cgLog log : logs) { + ArrayList<LogEntry> friendLogs = new ArrayList<LogEntry>(); + for (LogEntry log : logs) { if (log.friend) { friendLogs.add(log); } @@ -962,7 +967,7 @@ public class cgCache implements ICache, IWaypoint { * @param logs * the log entries */ - public void setLogs(List<cgLog> logs) { + public void setLogs(List<LogEntry> logs) { this.logs = logs; } @@ -1353,16 +1358,16 @@ public class cgCache implements ICache, IWaypoint { return attributes != null && attributes.size() > 0; } - public void prependLog(final cgLog log) { + public void prependLog(final LogEntry log) { if (logs == null) { - logs = new ArrayList<cgLog>(); + logs = new ArrayList<LogEntry>(); } logs.add(0, log); } - public void appendLog(final cgLog log) { + public void appendLog(final LogEntry log) { if (logs == null) { - logs = new ArrayList<cgLog>(); + logs = new ArrayList<LogEntry>(); } logs.add(log); } @@ -1397,7 +1402,7 @@ public class cgCache implements ICache, IWaypoint { public void store(Activity activity, CancellableHandler handler) { final int listId = Math.max(getListId(), StoredList.STANDARD_LIST_ID); - cgBase.storeCache(activity, this, null, listId, false, handler); + storeCache(activity, this, null, listId, false, handler); } public void setZoomlevel(int zoomlevel) { @@ -1418,4 +1423,171 @@ public class cgCache implements ICache, IWaypoint { public String getCoordType() { return "cache"; } + + public void drop(Handler handler) { + try { + cgeoapplication.getInstance().markDropped(getGeocode()); + cgeoapplication.getInstance().removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE)); + + handler.sendMessage(Message.obtain()); + } catch (Exception e) { + Log.e("cache.drop: ", e); + } + } + + public void checkFields() { + if (StringUtils.isBlank(getGeocode())) { + Log.e("cgBase.loadLogsFromDetails: geo code not parsed correctly"); + } + if (StringUtils.isBlank(getName())) { + Log.e("name not parsed correctly"); + } + if (StringUtils.isBlank(getGuid())) { + Log.e("guid not parsed correctly"); + } + if (getTerrain() == 0.0) { + Log.e("terrain not parsed correctly"); + } + if (getDifficulty() == 0.0) { + Log.e("difficulty not parsed correctly"); + } + if (StringUtils.isBlank(getOwner())) { + Log.e("owner not parsed correctly"); + } + if (StringUtils.isBlank(getOwnerReal())) { + Log.e("owner real not parsed correctly"); + } + if (getHiddenDate() == null) { + Log.e("hidden not parsed correctly"); + } + if (getFavoritePoints() < 0) { + Log.e("favoriteCount not parsed correctly"); + } + if (getSize() == null) { + Log.e("size not parsed correctly"); + } + if (getType() == null || getType() == CacheType.UNKNOWN) { + Log.e("type not parsed correctly"); + } + if (getCoords() == null) { + Log.e("coordinates not parsed correctly"); + } + if (StringUtils.isBlank(getLocation())) { + Log.e("location not parsed correctly"); + } + } + + public void refresh(Activity activity, int newListId, CancellableHandler handler) { + cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); + storeCache(activity, null, geocode, newListId, true, handler); + } + + public static void storeCache(Activity activity, cgCache origCache, String geocode, int listId, boolean forceRedownload, CancellableHandler handler) { + try { + cgCache cache; + // get cache details, they may not yet be complete + if (origCache != null) { + // only reload the cache if it was already stored or doesn't have full details (by checking the description) + if (origCache.getListId() >= StoredList.STANDARD_LIST_ID || StringUtils.isBlank(origCache.getDescription())) { + final SearchResult search = searchByGeocode(origCache.getGeocode(), null, listId, false, handler); + cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + } else { + cache = origCache; + } + } else if (StringUtils.isNotBlank(geocode)) { + final SearchResult search = searchByGeocode(geocode, null, listId, forceRedownload, handler); + cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + } else { + cache = null; + } + + if (cache == null) { + if (handler != null) { + handler.sendMessage(Message.obtain()); + } + + return; + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + final HtmlImage imgGetter = new HtmlImage(activity, cache.getGeocode(), false, listId, true); + + // store images from description + if (StringUtils.isNotBlank(cache.getDescription())) { + Html.fromHtml(cache.getDescription(), imgGetter, null); + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + // store spoilers + if (CollectionUtils.isNotEmpty(cache.getSpoilers())) { + for (cgImage oneSpoiler : cache.getSpoilers()) { + imgGetter.getDrawable(oneSpoiler.getUrl()); + } + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + // store images from logs + if (Settings.isStoreLogImages()) { + for (LogEntry log : cache.getLogs(true)) { + if (log.hasLogImages()) { + for (cgImage oneLogImg : log.getLogImages()) { + imgGetter.getDrawable(oneLogImg.getUrl()); + } + } + } + } + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + // store map previews + StaticMapsProvider.downloadMaps(cache, activity); + + if (CancellableHandler.isCancelled(handler)) { + return; + } + + cache.setListId(listId); + cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + + if (handler != null) { + handler.sendMessage(Message.obtain()); + } + } catch (Exception e) { + Log.e("cgBase.storeCache"); + } + } + + public static SearchResult searchByGeocode(final String geocode, final String guid, final int listId, final boolean forceReload, final CancellableHandler handler) { + if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) { + Log.e("cgeoBase.searchByGeocode: No geocode nor guid given"); + return null; + } + + cgeoapplication app = cgeoapplication.getInstance(); + if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (app.isOffline(geocode, guid) || app.isThere(geocode, guid, true, true))) { + final SearchResult search = new SearchResult(); + final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : app.getGeocode(guid); + search.addGeocode(realGeocode); + return search; + } + + // if we have no geocode, we can't dynamically select the handler, but must explicitly use GC + if (geocode == null && guid != null) { + return GCConnector.getInstance().searchByGeocode(null, guid, app, handler); + } + + return ConnectorFactory.getConnector(geocode).searchByGeocode(geocode, guid, app, handler); + } + } diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index 8bad165..c437e72 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -472,271 +472,6 @@ public class cgData { if (oldVersion > 0) { db.execSQL("delete from " + dbTableCaches + " where reason = 0"); - if (oldVersion < 34) { // upgrade to 34 - try { - db.execSQL("create index if not exists in_a on " + dbTableCaches + " (geocode)"); - db.execSQL("create index if not exists in_b on " + dbTableCaches + " (guid)"); - db.execSQL("create index if not exists in_c on " + dbTableCaches + " (reason)"); - db.execSQL("create index if not exists in_d on " + dbTableCaches + " (detailed)"); - db.execSQL("create index if not exists in_e on " + dbTableCaches + " (type)"); - db.execSQL("create index if not exists in_a on " + dbTableAttributes + " (geocode)"); - db.execSQL("create index if not exists in_a on " + dbTableWaypoints + " (geocode)"); - db.execSQL("create index if not exists in_b on " + dbTableWaypoints + " (geocode, type)"); - db.execSQL("create index if not exists in_a on " + dbTableSpoilers + " (geocode)"); - db.execSQL("create index if not exists in_a on " + dbTableLogs + " (geocode)"); - db.execSQL("create index if not exists in_a on " + dbTableTrackables + " (geocode)"); - - Log.i("Indexes added."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 34: " + e.toString()); - } - } - - if (oldVersion < 37) { // upgrade to 37 - try { - db.execSQL("alter table " + dbTableCaches + " add column direction text"); - db.execSQL("alter table " + dbTableCaches + " add column distance double"); - - Log.i("Columns direction and distance added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 37: " + e.toString()); - } - } - - if (oldVersion < 38) { // upgrade to 38 - try { - db.execSQL("drop table " + dbTableLogs); - db.execSQL(dbCreateLogs); - - Log.i("Changed type column in " + dbTableLogs + " to integer."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 38: " + e.toString()); - } - } - - if (oldVersion < 39) { // upgrade to 39 - try { - db.execSQL(dbCreateLists); - - Log.i("Created lists table."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 39: " + e.toString()); - } - } - - if (oldVersion < 40) { // upgrade to 40 - try { - db.execSQL("drop table " + dbTableTrackables); - db.execSQL(dbCreateTrackables); - - Log.i("Changed type of geocode column in trackables table."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 40: " + e.toString()); - } - } - - if (oldVersion < 41) { // upgrade to 41 - try { - db.execSQL("alter table " + dbTableCaches + " add column rating float"); - db.execSQL("alter table " + dbTableCaches + " add column votes integer"); - db.execSQL("alter table " + dbTableCaches + " add column vote integer"); - - Log.i("Added columns for GCvote."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 41: " + e.toString()); - } - } - - if (oldVersion < 42) { // upgrade to 42 - try { - db.execSQL(dbCreateLogsOffline); - - Log.i("Added table for offline logs"); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 42: " + e.toString()); - } - } - - if (oldVersion < 43) { // upgrade to 43 - try { - final String dbTableCachesTemp = dbTableCaches + "_temp"; - final String dbCreateCachesTemp = "" - + "create temporary table " + dbTableCachesTemp + " (" - + "_id integer primary key autoincrement, " - + "updated long not null, " - + "detailed integer not null default 0, " - + "detailedupdate long, " - + "geocode text unique not null, " - + "reason integer not null default 0, " // cached, favourite... - + "cacheid text, " - + "guid text, " - + "type text, " - + "name text, " - + "owner text, " - + "hidden long, " - + "hint text, " - + "size text, " - + "difficulty float, " - + "terrain float, " - + "latlon text, " - + "latitude_string text, " - + "longitude_string text, " - + "location text, " - + "distance double, " - + "latitude double, " - + "longitude double, " - + "shortdesc text, " - + "description text, " - + "rating float, " - + "votes integer, " - + "vote integer, " - + "disabled integer not null default 0, " - + "archived integer not null default 0, " - + "members integer not null default 0, " - + "found integer not null default 0, " - + "favourite integer not null default 0, " - + "inventorycoins integer default 0, " - + "inventorytags integer default 0, " - + "inventoryunknown integer default 0 " - + "); "; - final String dbCreateCachesNew = "" - + "create table " + dbTableCaches + " (" - + "_id integer primary key autoincrement, " - + "updated long not null, " - + "detailed integer not null default 0, " - + "detailedupdate long, " - + "geocode text unique not null, " - + "reason integer not null default 0, " // cached, favourite... - + "cacheid text, " - + "guid text, " - + "type text, " - + "name text, " - + "owner text, " - + "hidden long, " - + "hint text, " - + "size text, " - + "difficulty float, " - + "terrain float, " - + "latlon text, " - + "latitude_string text, " - + "longitude_string text, " - + "location text, " - + "direction double, " - + "distance double, " - + "latitude double, " - + "longitude double, " - + "shortdesc text, " - + "description text, " - + "rating float, " - + "votes integer, " - + "vote integer, " - + "disabled integer not null default 0, " - + "archived integer not null default 0, " - + "members integer not null default 0, " - + "found integer not null default 0, " - + "favourite integer not null default 0, " - + "inventorycoins integer default 0, " - + "inventorytags integer default 0, " - + "inventoryunknown integer default 0 " - + "); "; - - db.beginTransaction(); - db.execSQL(dbCreateCachesTemp); - db.execSQL("insert into " + dbTableCachesTemp + " select _id, updated, detailed, detailedupdate, geocode, reason, cacheid, guid, type, name, owner, hidden, hint, size, difficulty, terrain, latlon, latitude_string, longitude_string, location, distance, latitude, longitude, shortdesc, description, rating, votes, vote, disabled, archived, members, found, favourite, inventorycoins, inventorytags, inventoryunknown from " + dbTableCaches); - db.execSQL("drop table " + dbTableCaches); - db.execSQL(dbCreateCachesNew); - db.execSQL("insert into " + dbTableCaches + " select _id, updated, detailed, detailedupdate, geocode, reason, cacheid, guid, type, name, owner, hidden, hint, size, difficulty, terrain, latlon, latitude_string, longitude_string, location, null, distance, latitude, longitude, shortdesc, description, rating, votes, vote, disabled, archived, members, found, favourite, inventorycoins, inventorytags, inventoryunknown from " + dbTableCachesTemp); - db.execSQL("drop table " + dbTableCachesTemp); - db.setTransactionSuccessful(); - - Log.i("Changed direction column"); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 43: " + e.toString()); - } finally { - db.endTransaction(); - } - } - - if (oldVersion < 44) { // upgrade to 44 - try { - db.execSQL("alter table " + dbTableCaches + " add column favourite_cnt integer"); - - Log.i("Column favourite_cnt added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 44: " + e.toString()); - } - } - - if (oldVersion < 45) { // upgrade to 45 - try { - db.execSQL("alter table " + dbTableCaches + " add column owner_real text"); - - Log.i("Column owner_real added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 45: " + e.toString()); - } - } - - if (oldVersion < 46) { // upgrade to 46 - try { - db.execSQL("alter table " + dbTableCaches + " add column visiteddate long"); - db.execSQL("create index if not exists in_f on " + dbTableCaches + " (visiteddate, detailedupdate)"); - - Log.i("Added column for date of visit."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 46: " + e.toString()); - } - } - if (oldVersion < 47) { // upgrade to 47 - try { - db.execSQL("alter table " + dbTableCaches + " add column own integer not null default 0"); - - Log.i("Added column own."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 47: " + e.toString()); - } - } - - if (oldVersion < 48) { // upgrade to 48 - try { - db.execSQL("alter table " + dbTableCaches + " add column elevation double"); - - Log.i("Column elevation added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 48: " + e.toString()); - } - } - - if (oldVersion < 49) { // upgrade to 49 - try { - db.execSQL(dbCreateLogCount); - - Log.i("Created table " + dbTableLogCount + "."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 49: " + e.toString()); - } - } - - if (oldVersion < 50) { // upgrade to 50 - try { - db.execSQL("alter table " + dbTableCaches + " add column myvote float"); - - Log.i("Added float column for votes to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 50: " + e.toString()); - } - } - - if (oldVersion < 51) { // upgrade to 51 - try { - db.execSQL("alter table " + dbTableCaches + " add column reliable_latlon integer"); - - Log.i("Column reliable_latlon added to " + dbTableCaches + "."); - } catch (Exception e) { - Log.e("Failed to upgrade to ver. 51: " + e.toString()); - } - } - if (oldVersion < 52) { // upgrade to 52 try { db.execSQL(dbCreateSearchDestinationHistory); @@ -1417,7 +1152,7 @@ public class cgData { * @param destination * a destination to save */ - public void saveSearchedDestination(final cgDestination destination) { + public void saveSearchedDestination(final Destination destination) { init(); databaseRW.beginTransaction(); @@ -1608,11 +1343,11 @@ public class cgData { return true; } - public boolean saveLogs(String geocode, List<cgLog> logs) { + public boolean saveLogs(String geocode, List<LogEntry> logs) { return saveLogs(geocode, logs, true); } - public boolean saveLogs(String geocode, List<cgLog> logs, boolean drop) { + public boolean saveLogs(String geocode, List<LogEntry> logs, boolean drop) { if (StringUtils.isBlank(geocode) || logs == null) { return false; } @@ -1629,7 +1364,7 @@ public class cgData { if (!logs.isEmpty()) { InsertHelper helper = new InsertHelper(databaseRW, dbTableLogs); long timeStamp = System.currentTimeMillis(); - for (cgLog log : logs) { + for (LogEntry log : logs) { helper.prepareForInsert(); helper.bind(LOGS_GEOCODE, geocode); @@ -1643,9 +1378,9 @@ public class cgData { long log_id = helper.execute(); - if (CollectionUtils.isNotEmpty(log.logImages)) { + if (log.hasLogImages()) { ContentValues values = new ContentValues(); - for (cgImage img : log.logImages) { + for (cgImage img : log.getLogImages()) { values.clear(); values.put("log_id", log_id); values.put("title", img.getTitle()); @@ -2287,7 +2022,7 @@ public class cgData { * * @return A list of previously entered destinations or an empty list. */ - public List<cgDestination> loadHistoryOfSearchedLocations() { + public List<Destination> loadHistoryOfSearchedLocations() { init(); Cursor cursor = databaseRO.query(dbTableSearchDestionationHistory, @@ -2299,7 +2034,7 @@ public class cgData { "date desc", "100"); - final List<cgDestination> destinations = new LinkedList<cgDestination>(); + final List<Destination> destinations = new LinkedList<Destination>(); if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); @@ -2309,7 +2044,7 @@ public class cgData { int indexLongitude = cursor.getColumnIndex("longitude"); do { - final cgDestination dest = new cgDestination(cursor.getLong(indexId), cursor.getLong(indexDate), getCoords(cursor, indexLatitude, indexLongitude)); + final Destination dest = new Destination(cursor.getLong(indexId), cursor.getLong(indexDate), getCoords(cursor, indexLatitude, indexLongitude)); // If coordinates are non-existent or invalid, do not consider // this point. @@ -2344,14 +2079,14 @@ public class cgData { return success; } - public List<cgLog> loadLogs(String geocode) { + public List<LogEntry> loadLogs(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - List<cgLog> logs = new ArrayList<cgLog>(); + List<LogEntry> logs = new ArrayList<LogEntry>(); Cursor cursor = databaseRO.rawQuery( "SELECT cg_logs._id as cg_logs_id, type, author, log, date, found, friend, " + dbTableLogImages + "._id as cg_logImages_id, log_id, title, url FROM " @@ -2359,7 +2094,7 @@ public class cgData { + " ON ( cg_logs._id = log_id ) WHERE geocode = ? ORDER BY date desc, cg_logs._id asc", new String[] { geocode }); if (cursor != null && cursor.getCount() > 0) { - cgLog log = null; + LogEntry log = null; int indexLogsId = cursor.getColumnIndex("cg_logs_id"); int indexType = cursor.getColumnIndex("type"); int indexAuthor = cursor.getColumnIndex("author"); @@ -2372,7 +2107,7 @@ public class cgData { int indexUrl = cursor.getColumnIndex("url"); while (cursor.moveToNext() && logs.size() < 100) { if (log == null || log.id != cursor.getInt(indexLogsId)) { - log = new cgLog(); + log = new LogEntry(); log.id = cursor.getInt(indexLogsId); log.type = LogType.getById(cursor.getInt(indexType)); log.author = cursor.getString(indexAuthor); @@ -2385,11 +2120,7 @@ public class cgData { if (!cursor.isNull(indexLogImagesId)) { String title = cursor.getString(indexTitle); String url = cursor.getString(indexUrl); - if (log.logImages == null) { - log.logImages = new ArrayList<cgImage>(); - } - final cgImage log_img = new cgImage(url, title); - log.logImages.add(log_img); + log.addLogImage(new cgImage(url, title)); } } } @@ -3012,14 +2743,14 @@ public class cgData { return status; } - public cgLog loadLogOffline(String geocode) { + public LogEntry loadLogOffline(String geocode) { if (StringUtils.isBlank(geocode)) { return null; } init(); - cgLog log = null; + LogEntry log = null; Cursor cursor = databaseRO.query( dbTableLogsOffline, @@ -3034,7 +2765,7 @@ public class cgData { if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); - log = new cgLog(); + log = new LogEntry(); log.id = cursor.getInt(cursor.getColumnIndex("_id")); log.type = LogType.getById(cursor.getInt(cursor.getColumnIndex("type"))); log.log = cursor.getString(cursor.getColumnIndex("log")); @@ -3308,7 +3039,7 @@ public class cgData { return true; } - public boolean removeSearchedDestination(cgDestination destination) { + public boolean removeSearchedDestination(Destination destination) { boolean success = true; if (destination == null) { success = false; diff --git a/main/src/cgeo/geocaching/cgLog.java b/main/src/cgeo/geocaching/cgLog.java deleted file mode 100644 index 2b3568d..0000000 --- a/main/src/cgeo/geocaching/cgLog.java +++ /dev/null @@ -1,39 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.enumerations.LogType; - -import java.util.List; - -public class cgLog { - public int id = 0; - public LogType type = LogType.LOG_NOTE; // note - public String author = ""; - public String log = ""; - public long date = 0; - public int found = -1; - /** Friend's logentry */ - public boolean friend = false; - public List<cgImage> logImages = null; - public String cacheName = ""; // used for trackables - public String cacheGuid = ""; // used for trackables - - @Override - public int hashCode() { - return (int) date * type.hashCode() * author.hashCode() * log.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof cgLog)) { - return false; - } - final cgLog otherLog = (cgLog) obj; - return date == otherLog.date && - type == otherLog.type && - author.compareTo(otherLog.author) == 0 && - log.compareTo(otherLog.log) == 0 ? true : false; - } -} diff --git a/main/src/cgeo/geocaching/cgTrackable.java b/main/src/cgeo/geocaching/cgTrackable.java index c4a3464..f46e39b 100644 --- a/main/src/cgeo/geocaching/cgTrackable.java +++ b/main/src/cgeo/geocaching/cgTrackable.java @@ -34,7 +34,7 @@ public class cgTrackable implements ILogable { private String goal = null; private String details = null; private String image = null; - private List<cgLog> logs = new ArrayList<cgLog>(); + private List<LogEntry> logs = new ArrayList<LogEntry>(); private String trackingcode = null; public String getUrl() { @@ -188,11 +188,11 @@ public class cgTrackable implements ILogable { this.image = image; } - public List<cgLog> getLogs() { + public List<LogEntry> getLogs() { return logs; } - public void setLogs(List<cgLog> logs) { + public void setLogs(List<LogEntry> logs) { this.logs = logs; } diff --git a/main/src/cgeo/geocaching/cgTrackableLog.java b/main/src/cgeo/geocaching/cgTrackableLog.java deleted file mode 100644 index ee134da..0000000 --- a/main/src/cgeo/geocaching/cgTrackableLog.java +++ /dev/null @@ -1,11 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.enumerations.LogTypeTrackable; - -public class cgTrackableLog { - public int ctl = -1; - public int id = -1; - public String trackCode = null; - public String name = null; - public LogTypeTrackable action = LogTypeTrackable.DO_NOTHING; // base.logTrackablesAction - no action -} diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java index abead59..a8a62c3 100644 --- a/main/src/cgeo/geocaching/cgeoapplication.java +++ b/main/src/cgeo/geocaching/cgeoapplication.java @@ -297,7 +297,7 @@ public class cgeoapplication extends Application { } /** {@link cgData#loadHistoryOfSearchedLocations()} */ - public List<cgDestination> getHistoryOfSearchedLocations() { + public List<Destination> getHistoryOfSearchedLocations() { return storage.loadHistoryOfSearchedLocations(); } @@ -348,8 +348,8 @@ public class cgeoapplication extends Application { return storage.clearSearchedDestinations(); } - /** {@link cgData#saveSearchedDestination(cgDestination)} */ - public void saveSearchedDestination(cgDestination destination) { + /** {@link cgData#saveSearchedDestination(Destination)} */ + public void saveSearchedDestination(Destination destination) { storage.saveSearchedDestination(destination); } @@ -412,7 +412,7 @@ public class cgeoapplication extends Application { return StringUtils.defaultString(action); } - public boolean addLog(String geocode, cgLog log) { + public boolean addLog(String geocode, LogEntry log) { if (StringUtils.isBlank(geocode)) { return false; } @@ -420,7 +420,7 @@ public class cgeoapplication extends Application { return false; } - List<cgLog> list = new ArrayList<cgLog>(); + List<LogEntry> list = new ArrayList<LogEntry>(); list.add(log); return storage.saveLogs(geocode, list, false); @@ -440,7 +440,7 @@ public class cgeoapplication extends Application { } /** {@link cgData#loadLogOffline(String)} */ - public cgLog loadLogOffline(String geocode) { + public LogEntry loadLogOffline(String geocode) { return storage.loadLogOffline(geocode); } @@ -484,8 +484,8 @@ public class cgeoapplication extends Application { return storage.removeList(id); } - /** {@link cgData#removeSearchedDestination(cgDestination)} */ - public boolean removeSearchedDestinations(cgDestination destination) { + /** {@link cgData#removeSearchedDestination(Destination)} */ + public boolean removeSearchedDestinations(Destination destination) { return storage.removeSearchedDestination(destination); } diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 184d254..70bf892 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -6,6 +6,7 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cachelist.CacheListAppFactory; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; @@ -674,7 +675,7 @@ public class cgeocaches extends AbstractListActivity { // refresh standard list if it has changed (new caches downloaded) if (type == CacheListType.OFFLINE && listId >= StoredList.STANDARD_LIST_ID && search != null) { - SearchResult newSearch = cgBase.searchByStored(coords, cacheType, listId); + SearchResult newSearch = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, cacheType, listId); if (newSearch != null && newSearch.getTotal() != search.getTotal()) { refreshCurrentList(); } @@ -1097,7 +1098,7 @@ public class cgeocaches extends AbstractListActivity { return true; } else if (id == MENU_DROP_CACHE) { - cgBase.dropCache(getCacheFromAdapter(adapterInfo), new Handler() { + getCacheFromAdapter(adapterInfo).drop(new Handler() { @Override public void handleMessage(Message msg) { refreshCurrentList(); @@ -1505,7 +1506,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByStored(coords, Settings.getCacheType(), listId); + search = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId); handler.sendMessage(Message.obtain()); } } @@ -1535,7 +1536,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByNextPage(this, search, Settings.isShowCaptcha()); + search = GCParser.searchByNextPage(this, search, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } @@ -1562,7 +1563,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByCoords(this, coords, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByCoords(this, coords, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } @@ -1589,7 +1590,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByKeyword(this, keyword, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByKeyword(this, keyword, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } } @@ -1615,7 +1616,7 @@ public class cgeocaches extends AbstractListActivity { @Override public void run() { - search = cgBase.searchByUsername(this, username, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByUsername(this, username, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } } @@ -1647,7 +1648,7 @@ public class cgeocaches extends AbstractListActivity { params.put("cacheType", cacheType.id); } - search = cgBase.searchByOwner(this, username, cacheType, Settings.isShowCaptcha()); + search = GCParser.searchByOwner(this, username, cacheType, Settings.isShowCaptcha()); handler.sendMessage(Message.obtain()); } @@ -1717,7 +1718,7 @@ public class cgeocaches extends AbstractListActivity { } detailProgress++; - cgBase.refreshCache(cgeocaches.this, cache.getGeocode(), listIdLD, null); + cache.refresh(cgeocaches.this, listIdLD, null); handler.sendEmptyMessage(cacheList.indexOf(cache)); @@ -1780,7 +1781,7 @@ public class cgeocaches extends AbstractListActivity { handler.sendMessage(handler.obtainMessage(1, GCcode)); yield(); - cgBase.storeCache(cgeocaches.this, null, GCcode, listIdLFW, false, null); + cgCache.storeCache(cgeocaches.this, null, GCcode, listIdLFW, false, null); handler.sendMessage(handler.obtainMessage(2, GCcode)); yield(); diff --git a/main/src/cgeo/geocaching/cgeoinit.java b/main/src/cgeo/geocaching/cgeoinit.java index 3344c3c..2269ad7 100644 --- a/main/src/cgeo/geocaching/cgeoinit.java +++ b/main/src/cgeo/geocaching/cgeoinit.java @@ -12,6 +12,7 @@ import cgeo.geocaching.network.Cookies; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.TwitterAuthorizationActivity; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; @@ -733,7 +734,7 @@ public class cgeoinit extends AbstractActivity { TextView lastBackup = (TextView) findViewById(R.id.backup_last); File lastBackupFile = cgeoapplication.isRestoreFile(); if (lastBackupFile != null) { - lastBackup.setText(res.getString(R.string.init_backup_last) + " " + cgBase.formatTime(lastBackupFile.lastModified()) + ", " + cgBase.formatDate(lastBackupFile.lastModified())); + lastBackup.setText(res.getString(R.string.init_backup_last) + " " + Formatter.formatTime(lastBackupFile.lastModified()) + ", " + Formatter.formatDate(lastBackupFile.lastModified())); } else { lastBackup.setText(res.getString(R.string.init_backup_last_no)); } diff --git a/main/src/cgeo/geocaching/cgeopoint.java b/main/src/cgeo/geocaching/cgeopoint.java index 73c0b18..0335453 100644 --- a/main/src/cgeo/geocaching/cgeopoint.java +++ b/main/src/cgeo/geocaching/cgeopoint.java @@ -6,6 +6,7 @@ import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.GeopointParser; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -40,18 +41,18 @@ public class cgeopoint extends AbstractActivity { private static final int MENU_CACHES_AROUND = 5; private static final int MENU_CLEAR_HISTORY = 6; - private static class DestinationHistoryAdapter extends ArrayAdapter<cgDestination> { + private static class DestinationHistoryAdapter extends ArrayAdapter<Destination> { private LayoutInflater inflater = null; public DestinationHistoryAdapter(Context context, - List<cgDestination> objects) { + List<Destination> objects) { super(context, 0, objects); } @Override public View getView(final int position, final View convertView, final ViewGroup parent) { - cgDestination loc = getItem(position); + Destination loc = getItem(position); View v = convertView; @@ -70,7 +71,7 @@ public class cgeopoint extends AbstractActivity { longitude.setText(lonString); latitude.setText(latString); - date.setText(cgBase.formatShortDateTime(getContext(), loc.getDate())); + date.setText(Formatter.formatShortDateTime(getContext(), loc.getDate())); return v; } @@ -89,7 +90,7 @@ public class cgeopoint extends AbstractActivity { private Button latButton = null; private Button lonButton = null; private boolean changed = false; - private List<cgDestination> historyOfSearchedLocations; + private List<Destination> historyOfSearchedLocations; private DestinationHistoryAdapter destionationHistoryAdapter; private ListView historyListView; private TextView historyFooter; @@ -137,8 +138,8 @@ public class cgeopoint extends AbstractActivity { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { final Object selection = arg0.getItemAtPosition(arg2); - if (selection instanceof cgDestination) { - navigateTo(((cgDestination) selection).getCoords()); + if (selection instanceof Destination) { + navigateTo(((Destination) selection).getCoords()); } } }); @@ -163,21 +164,21 @@ public class cgeopoint extends AbstractActivity { switch (item.getItemId()) { case CONTEXT_MENU_NAVIGATE: contextMenuItemPosition = position; - if (destination instanceof cgDestination) { - NavigationAppFactory.showNavigationMenu(geo, this, null, null, ((cgDestination) destination).getCoords()); + if (destination instanceof Destination) { + NavigationAppFactory.showNavigationMenu(geo, this, null, null, ((Destination) destination).getCoords()); return true; } break; case CONTEXT_MENU_DELETE_WAYPOINT: - if (destination instanceof cgDestination) { - removeFromHistory((cgDestination) destination); + if (destination instanceof Destination) { + removeFromHistory((Destination) destination); } return true; case CONTEXT_MENU_EDIT_WAYPOINT: - if (destination instanceof cgDestination) { - final Geopoint gp = ((cgDestination) destination).getCoords(); + if (destination instanceof Destination) { + final Geopoint gp = ((Destination) destination).getCoords(); latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); } @@ -205,7 +206,7 @@ public class cgeopoint extends AbstractActivity { return destionationHistoryAdapter; } - private List<cgDestination> getHistoryOfSearchedLocations() { + private List<Destination> getHistoryOfSearchedLocations() { if (historyOfSearchedLocations == null) { // Load from database historyOfSearchedLocations = app.getHistoryOfSearchedLocations(); @@ -382,8 +383,7 @@ public class cgeopoint extends AbstractActivity { final Geopoint coords = getDestination(); - if (coords != null) - { + if (coords != null) { addToHistory(coords); } @@ -410,21 +410,20 @@ public class cgeopoint extends AbstractActivity { private void addToHistory(final Geopoint coords) { // Add locations to history - final cgDestination loc = new cgDestination(0, 0, coords); + final Destination loc = new Destination(coords); if (!getHistoryOfSearchedLocations().contains(loc)) { - final cgDestination updatedLoc = loc.withDate(System.currentTimeMillis()); - getHistoryOfSearchedLocations().add(0, updatedLoc); + getHistoryOfSearchedLocations().add(0, loc); // Save location - app.saveSearchedDestination(updatedLoc); + app.saveSearchedDestination(loc); // Ensure to remove the footer historyListView.removeFooterView(getEmptyHistoryFooter()); } } - private void removeFromHistory(cgDestination destination) { + private void removeFromHistory(Destination destination) { if (getHistoryOfSearchedLocations().contains(destination)) { getHistoryOfSearchedLocations().remove(destination); diff --git a/main/src/cgeo/geocaching/cgeopopup.java b/main/src/cgeo/geocaching/cgeopopup.java index c1a5b01..99e75d8 100644 --- a/main/src/cgeo/geocaching/cgeopopup.java +++ b/main/src/cgeo/geocaching/cgeopopup.java @@ -596,7 +596,7 @@ public class cgeopopup extends AbstractActivity { @Override public void run() { - cgBase.dropCache(cache, handler); + cache.drop(handler); } } diff --git a/main/src/cgeo/geocaching/cgeotouch.java b/main/src/cgeo/geocaching/cgeotouch.java index 570df1c..56b5ba1 100644 --- a/main/src/cgeo/geocaching/cgeotouch.java +++ b/main/src/cgeo/geocaching/cgeotouch.java @@ -1,6 +1,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; @@ -8,6 +9,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.DateDialog; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -63,7 +65,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog setType((LogType) msg.obj); showToast(res.getString(R.string.info_log_type_changed)); } else { - if (cgBase.isEmpty(viewstates) && attempts < 2) { + if (Login.isEmpty(viewstates) && attempts < 2) { showToast(res.getString(R.string.err_log_load_data_again)); loadData thread; @@ -71,7 +73,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog thread.start(); return; - } else if (cgBase.isEmpty(viewstates) && attempts >= 2) { + } else if (Login.isEmpty(viewstates) && attempts >= 2) { showToast(res.getString(R.string.err_log_load_data)); showProgress(false); @@ -203,8 +205,8 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog textContent = text.getText().toString(); final long now = System.currentTimeMillis(); - dateString = cgBase.formatDate(now); - timeString = cgBase.formatTime(now); + dateString = Formatter.formatDate(now); + timeString = Formatter.formatTime(now); if ((id & 0x4) == 0x4) { addText += dateString; @@ -287,7 +289,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog }); Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); dateButton.setOnClickListener(new cgeotouchDateListener()); if (tweetBox == null) { @@ -299,7 +301,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog tweetCheck.setChecked(true); Button buttonPost = (Button) findViewById(R.id.post); - if (cgBase.isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { buttonPost.setEnabled(false); buttonPost.setOnTouchListener(null); buttonPost.setOnClickListener(null); @@ -319,7 +321,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog date = dateIn; final Button dateButton = (Button) findViewById(R.id.date); - dateButton.setText(cgBase.formatShortDate(date.getTime().getTime())); + dateButton.setText(Formatter.formatShortDate(date.getTime().getTime())); } public void setType(LogType type) { @@ -396,7 +398,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog viewstates = Login.getViewstates(page); - final List<LogType> typesPre = cgBase.parseTypes(page); + final List<LogType> typesPre = GCParser.parseTypes(page); if (typesPre.size() > 0) { logTypes.clear(); logTypes.addAll(typesPre); @@ -442,7 +444,7 @@ public class cgeotouch extends AbstractActivity implements DateDialog.DateDialog tweetCheck = (CheckBox) findViewById(R.id.tweet); } - final StatusCode status = cgBase.postLogTrackable(guid, tracking, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log); + final StatusCode status = GCParser.postLogTrackable(guid, tracking, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log); if (status == StatusCode.NO_ERROR && Settings.isUseTwitter() && Settings.isTwitterLoginValid() && diff --git a/main/src/cgeo/geocaching/cgeotrackable.java b/main/src/cgeo/geocaching/cgeotrackable.java index 8306217..923e420 100644 --- a/main/src/cgeo/geocaching/cgeotrackable.java +++ b/main/src/cgeo/geocaching/cgeotrackable.java @@ -1,11 +1,12 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.geopoint.HumanDistance; import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.utils.Log; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import android.app.ProgressDialog; @@ -155,7 +156,7 @@ public class cgeotrackable extends AbstractActivity { // trackable released if (trackable.getReleased() != null) { - addDetail(R.string.trackable_released, cgBase.formatDate(trackable.getReleased().getTime())); + addDetail(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime())); } // trackable distance @@ -428,7 +429,7 @@ public class cgeotrackable extends AbstractActivity { trackable = cgeoapplication.getInstance().getTrackableByGeocode(geocode); if ((trackable == null || trackable.isLoggable()) && !StringUtils.startsWithIgnoreCase(geocode, "GK")) { - trackable = cgBase.searchTrackable(geocode, guid, id); + trackable = GCParser.searchTrackable(geocode, guid, id); } handler.sendMessage(Message.obtain()); } @@ -442,11 +443,11 @@ public class cgeotrackable extends AbstractActivity { RelativeLayout rowView; if (trackable != null && trackable.getLogs() != null) { - for (cgLog log : trackable.getLogs()) { + for (LogEntry log : trackable.getLogs()) { rowView = (RelativeLayout) inflater.inflate(R.layout.trackable_logs_item, null); if (log.date > 0) { - ((TextView) rowView.findViewById(R.id.added)).setText(cgBase.formatShortDate(log.date)); + ((TextView) rowView.findViewById(R.id.added)).setText(Formatter.formatShortDate(log.date)); } ((TextView) rowView.findViewById(R.id.type)).setText(log.type.getL10n()); @@ -460,10 +461,7 @@ public class cgeotrackable extends AbstractActivity { final String cacheName = log.cacheName; ((TextView) rowView.findViewById(R.id.location)).setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { - Intent cacheIntent = new Intent(cgeotrackable.this, CacheDetailActivity.class); - cacheIntent.putExtra("guid", cacheGuid); - cacheIntent.putExtra("name", Html.fromHtml(cacheName).toString()); - startActivity(cacheIntent); + CacheDetailActivity.startActivityGuid(cgeotrackable.this, cacheGuid, Html.fromHtml(cacheName).toString()); } }); } @@ -475,9 +473,9 @@ public class cgeotrackable extends AbstractActivity { // add LogImages LinearLayout logLayout = (LinearLayout) rowView.findViewById(R.id.log_layout); - if (CollectionUtils.isNotEmpty(log.logImages)) { + if (log.hasLogImages()) { - final ArrayList<cgImage> logImages = new ArrayList<cgImage>(log.logImages); + final ArrayList<cgImage> logImages = new ArrayList<cgImage>(log.getLogImages()); final View.OnClickListener listener = new View.OnClickListener() { @Override @@ -487,8 +485,8 @@ public class cgeotrackable extends AbstractActivity { }; ArrayList<String> titles = new ArrayList<String>(); - for (int i_img_cnt = 0; i_img_cnt < log.logImages.size(); i_img_cnt++) { - String img_title = log.logImages.get(i_img_cnt).getTitle(); + for (cgImage image : log.getLogImages()) { + String img_title = image.getTitle(); if (!StringUtils.isBlank(img_title)) { titles.add(img_title); } diff --git a/main/src/cgeo/geocaching/connector/gc/GCBase.java b/main/src/cgeo/geocaching/connector/gc/GCBase.java index e038573..2f22c52 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCBase.java +++ b/main/src/cgeo/geocaching/connector/gc/GCBase.java @@ -2,7 +2,6 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; @@ -185,7 +184,7 @@ public class GCBase { if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY)) { Geopoint center = viewport.getCenter(); if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) { - SearchResult search = cgBase.searchByCoords(null, center, Settings.getCacheType(), false); + SearchResult search = GCParser.searchByCoords(null, center, Settings.getCacheType(), false); if (search != null && !search.isEmpty()) { final Set<String> geocodes = search.getGeocodes(); if (Settings.isPremiumMember()) { diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index f539d58..a431359 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -3,7 +3,6 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.AbstractConnector; @@ -101,7 +100,7 @@ public class GCConnector extends AbstractConnector { params.put("log", "y"); params.put("numlogs", String.valueOf(GCConstants.NUMBER_OF_LOGS)); - cgBase.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_loadpage); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_loadpage); final String page = Login.getRequestLogged("http://www.geocaching.com/seek/cache_details.aspx", params); @@ -124,7 +123,7 @@ public class GCConnector extends AbstractConnector { return search; } - final SearchResult searchResult = cgBase.parseCache(page, handler); + final SearchResult searchResult = GCParser.parseCache(page, handler); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { Log.e("cgeoBase.searchByGeocode: No cache parsed"); diff --git a/main/src/cgeo/geocaching/cgBase.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index eda6d81..cf7c762 100644 --- a/main/src/cgeo/geocaching/cgBase.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -1,14 +1,19 @@ -// $codepro.audit.disable logExceptions -package cgeo.geocaching; - -import cgeo.geocaching.connector.ConnectorFactory; -import cgeo.geocaching.connector.gc.GCConnector; -import cgeo.geocaching.connector.gc.GCConstants; -import cgeo.geocaching.connector.gc.Login; +package cgeo.geocaching.connector.gc; + +import cgeo.geocaching.LogEntry; +import cgeo.geocaching.R; +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.TrackableLog; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgImage; +import cgeo.geocaching.cgSearchThread; +import cgeo.geocaching.cgTrackable; +import cgeo.geocaching.cgWaypoint; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.LogTypeTrackable; @@ -19,7 +24,6 @@ import cgeo.geocaching.gcvote.GCVote; import cgeo.geocaching.gcvote.GCVoteRating; import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.DirectionImage; @@ -35,20 +39,10 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; import android.net.Uri; -import android.os.Handler; -import android.os.Message; import android.text.Html; import android.text.Spannable; import android.text.Spanned; -import android.text.format.DateUtils; import android.text.style.StrikethroughSpan; import java.net.URLDecoder; @@ -56,70 +50,16 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.regex.Matcher; -public class cgBase { - +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 - public static String version = null; - - private static Context context; - public static Resources res; - - public static final int UPDATE_LOAD_PROGRESS_DETAIL = 42186; - - private cgBase() { - //initialize(app); - throw new UnsupportedOperationException(); // static class, not to be instantiated - } - - /** - * Called from AbstractActivity.onCreate() and AbstractListActivity.onCreate() - * - * @param app - */ - public static void initialize(final cgeoapplication app) { - context = app.getBaseContext(); - res = app.getBaseContext().getResources(); - - try { - final PackageManager manager = app.getPackageManager(); - final PackageInfo info = manager.getPackageInfo(app.getPackageName(), 0); - version = info.versionName; - } catch (PackageManager.NameNotFoundException e) { - Log.e("unable to get version information", e); - version = null; - } - } - - public static void sendLoadProgressDetail(final Handler handler, final int str) { - if (null != handler) { - handler.obtainMessage(UPDATE_LOAD_PROGRESS_DETAIL, cgeoapplication.getInstance().getString(str)).sendToTarget(); - } - } - - /** - * checks if an Array of Strings is empty or not. Empty means: - * - Array is null - * - or all elements are null or empty strings - */ - public static boolean isEmpty(String[] a) { - if (a == null) { - return true; - } - - for (String s : a) { - if (StringUtils.isNotEmpty(s)) { - return false; - } - } - return true; - } private static SearchResult parseSearch(final cgSearchThread thread, final String url, final String pageContent, final boolean showCaptcha) { if (StringUtils.isBlank(pageContent)) { @@ -275,7 +215,7 @@ public class cgBase { cids.add(cache.getCacheId()); } - // favourite count + // favorite count try { result = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_FAVORITE, false, 1, null, true); if (null != result) { @@ -385,7 +325,7 @@ public class cgBase { } // update progress message so user knows we're still working. Otherwise it will remain on whatever was set // in getExtraOnlineInfo (which could be logs, gcvote, or elevation) - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_render); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_render); // save full detailed caches cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); } @@ -393,7 +333,7 @@ public class cgBase { } static SearchResult parseCacheFromText(final String page, final CancellableHandler handler) { - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); if (StringUtils.isBlank(page)) { Log.e("cgeoBase.parseCache: No page given"); @@ -544,7 +484,7 @@ public class cgBase { } } - checkFields(cache); + cache.checkFields(); // cache personal note cache.setPersonalNote(BaseUtils.getMatch(page, GCConstants.PATTERN_PERSONALNOTE, true, cache.getPersonalNote())); @@ -591,7 +531,7 @@ public class cgBase { if (CancellableHandler.isCancelled(handler)) { return null; } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILERSINSIDE.matcher(spoilers); @@ -685,8 +625,7 @@ public class cgBase { final String originalCoords = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null); if (null != originalCoords) { - // res is null during the unit tests - final cgWaypoint waypoint = new cgWaypoint(res != null ? res.getString(R.string.cache_coordinates_original) : "res = null", WaypointType.WAYPOINT, false); + final cgWaypoint waypoint = new cgWaypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.WAYPOINT, false); waypoint.setCoords(new Geopoint(originalCoords)); cache.addWaypoint(waypoint, false); cache.setUserModifiedCoords(true); @@ -703,8 +642,7 @@ public class cgBase { if (CancellableHandler.isCancelled(handler)) { return null; } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_waypoints); - + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_waypoints); String wpList = page.substring(wpBegin); @@ -731,7 +669,7 @@ public class cgBase { // waypoint name // res is null during the unit tests - final String name = BaseUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, res != null ? res.getString(R.string.waypoint) : "res = null", true); + final String name = BaseUtils.getMatch(wp[6], GCConstants.PATTERN_WPNAME, true, 1, cgeoapplication.getInstance().getString(R.string.waypoint), true); // waypoint type final String resulttype = BaseUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null); @@ -779,485 +717,6 @@ public class cgBase { return searchResult; } - private static void getExtraOnlineInfo(final cgCache cache, final String page, final CancellableHandler handler) { - if (CancellableHandler.isCancelled(handler)) { - return; - } - - //cache.setLogs(loadLogsFromDetails(page, cache, false)); - if (Settings.isFriendLogsWanted()) { - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); - List<cgLog> allLogs = cache.getLogs(); - List<cgLog> friendLogs = loadLogsFromDetails(page, cache, true, false); - if (friendLogs != null) { - for (cgLog log : friendLogs) { - if (allLogs.contains(log)) { - allLogs.get(allLogs.indexOf(log)).friend = true; - } else { - allLogs.add(log); - } - } - } - } - - if (Settings.isElevationWanted()) { - if (CancellableHandler.isCancelled(handler)) { - return; - } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_elevation); - if (cache.getCoords() != null) { - cache.setElevation(cache.getCoords().getElevation()); - } - } - - if (Settings.isRatingWanted()) { - if (CancellableHandler.isCancelled(handler)) { - return; - } - sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote); - final GCVoteRating rating = GCVote.getRating(cache.getGuid(), cache.getGeocode()); - if (rating != null) { - cache.setRating(rating.getRating()); - cache.setVotes(rating.getVotes()); - cache.setMyVote(rating.getMyVote()); - } - } - } - - /** - * Load logs from a cache details page. - * - * @param page - * the text of the details page - * @param cache - * the cache object to put the logs in - * @param friends - * retrieve friend logs - */ - private static List<cgLog> loadLogsFromDetails(final String page, final cgCache cache, final boolean friends, final boolean getDataFromPage) { - String rawResponse = null; - - if (!getDataFromPage) { - final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN2.matcher(page); - if (!userTokenMatcher.find()) { - Log.e("cgBase.loadLogsFromDetails: unable to extract userToken"); - return null; - } - - final String userToken = userTokenMatcher.group(1); - final Parameters params = new Parameters( - "tkn", userToken, - "idx", "1", - "num", String.valueOf(GCConstants.NUMBER_OF_LOGS), - "decrypt", "true", - // "sp", Boolean.toString(personal), // personal logs - "sf", Boolean.toString(friends)); - - final HttpResponse response = Network.getRequest("http://www.geocaching.com/seek/geocache.logbook", params); - if (response == null) { - Log.e("cgBase.loadLogsFromDetails: cannot log logs, response is null"); - return null; - } - final int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != 200) { - Log.e("cgBase.loadLogsFromDetails: error " + statusCode + " when requesting log information"); - return null; - } - rawResponse = Network.getResponseData(response); - if (rawResponse == null) { - Log.e("cgBase.loadLogsFromDetails: unable to read whole response"); - return null; - } - } else { - // extract embedded JSON data from page - rawResponse = BaseUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, ""); - } - - List<cgLog> logs = new ArrayList<cgLog>(); - - try { - final JSONObject resp = new JSONObject(rawResponse); - if (!resp.getString("status").equals("success")) { - Log.e("cgBase.loadLogsFromDetails: status is " + resp.getString("status")); - return null; - } - - final JSONArray data = resp.getJSONArray("data"); - - for (int index = 0; index < data.length(); index++) { - final JSONObject entry = data.getJSONObject(index); - final cgLog logDone = new cgLog(); - logDone.friend = friends; - - // FIXME: use the "LogType" field instead of the "LogTypeImage" one. - final String logIconNameExt = entry.optString("LogTypeImage", ".gif"); - final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4); - logDone.type = LogType.getByIconName(logIconName); - - try { - logDone.date = Login.parseGcCustomDate(entry.getString("Visited")).getTime(); - } catch (ParseException e) { - Log.e("cgBase.loadLogsFromDetails: failed to parse log date."); - } - - logDone.author = entry.getString("UserName"); - logDone.found = entry.getInt("GeocacheFindCount"); - logDone.log = entry.getString("LogText"); - - final JSONArray images = entry.getJSONArray("Images"); - for (int i = 0; i < images.length(); i++) { - final JSONObject image = images.getJSONObject(i); - String url = "http://img.geocaching.com/cache/log/" + image.getString("FileName"); - String title = image.getString("Name"); - final cgImage logImage = new cgImage(url, title); - if (logDone.logImages == null) { - logDone.logImages = new ArrayList<cgImage>(); - } - logDone.logImages.add(logImage); - } - - logs.add(logDone); - } - } catch (JSONException e) { - // failed to parse logs - Log.w("cgBase.loadLogsFromDetails: Failed to parse cache logs", e); - } - - return logs; - } - - private static void checkFields(cgCache cache) { - if (StringUtils.isBlank(cache.getGeocode())) { - Log.e("cgBase.loadLogsFromDetails: geo code not parsed correctly"); - } - if (StringUtils.isBlank(cache.getName())) { - Log.e("name not parsed correctly"); - } - if (StringUtils.isBlank(cache.getGuid())) { - Log.e("guid not parsed correctly"); - } - if (cache.getTerrain() == 0.0) { - Log.e("terrain not parsed correctly"); - } - if (cache.getDifficulty() == 0.0) { - Log.e("difficulty not parsed correctly"); - } - if (StringUtils.isBlank(cache.getOwner())) { - Log.e("owner not parsed correctly"); - } - if (StringUtils.isBlank(cache.getOwnerReal())) { - Log.e("owner real not parsed correctly"); - } - if (cache.getHiddenDate() == null) { - Log.e("hidden not parsed correctly"); - } - if (cache.getFavoritePoints() < 0) { - Log.e("favoriteCount not parsed correctly"); - } - if (cache.getSize() == null) { - Log.e("size not parsed correctly"); - } - if (cache.getType() == null || cache.getType() == CacheType.UNKNOWN) { - Log.e("type not parsed correctly"); - } - if (cache.getCoords() == null) { - Log.e("coordinates not parsed correctly"); - } - if (StringUtils.isBlank(cache.getLocation())) { - Log.e("location not parsed correctly"); - } - } - - /** - * Parse a trackable HTML description into a cgTrackable object - * - * @param page - * the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace} - * @param app - * if not null, the application to use to save the trackable - * @return the parsed trackable, or null if none could be parsed - */ - public static cgTrackable parseTrackable(final String page, final cgeoapplication app, final String possibleTrackingcode) { - if (StringUtils.isBlank(page)) { - Log.e("cgeoBase.parseTrackable: No page given"); - return null; - } - - final cgTrackable trackable = new cgTrackable(); - - // trackable geocode - trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()).toUpperCase()); - - // trackable id - trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid())); - - // trackable icon - trackable.setIconUrl(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ICON, true, trackable.getIconUrl())); - - // trackable name - trackable.setName(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_NAME, true, trackable.getName())); - - // trackable type - if (StringUtils.isNotBlank(trackable.getName())) { - trackable.setType(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_TYPE, true, trackable.getType())); - } - - // trackable owner name - try { - final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page); - if (matcherOwner.find() && matcherOwner.groupCount() > 0) { - trackable.setOwnerGuid(matcherOwner.group(1)); - trackable.setOwner(matcherOwner.group(2).trim()); - } - } catch (Exception e) { - // failed to parse trackable owner name - Log.w("cgeoBase.parseTrackable: Failed to parse trackable owner name"); - } - - // trackable origin - trackable.setOrigin(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ORIGIN, true, trackable.getOrigin())); - - // trackable spotted - try { - final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page); - if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) { - trackable.setSpottedGuid(matcherSpottedCache.group(1)); - trackable.setSpottedName(matcherSpottedCache.group(2).trim()); - trackable.setSpottedType(cgTrackable.SPOTTED_CACHE); - } - - final Matcher matcherSpottedUser = GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER.matcher(page); - if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) { - trackable.setSpottedGuid(matcherSpottedUser.group(1)); - trackable.setSpottedName(matcherSpottedUser.group(2).trim()); - trackable.setSpottedType(cgTrackable.SPOTTED_USER); - } - - if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) { - trackable.setSpottedType(cgTrackable.SPOTTED_UNKNOWN); - } - - if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) { - trackable.setSpottedType(cgTrackable.SPOTTED_OWNER); - } - } catch (Exception e) { - // failed to parse trackable last known place - Log.w("cgeoBase.parseTrackable: Failed to parse trackable last known place"); - } - - // released date - can be missing on the page - try { - String releaseString = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null); - if (releaseString != null) { - trackable.setReleased(dateTbIn1.parse(releaseString)); - if (trackable.getReleased() == null) { - trackable.setReleased(dateTbIn2.parse(releaseString)); - } - } - } catch (ParseException e1) { - trackable.setReleased(null); - } - - - // trackable distance - try { - final String distance = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null); - if (null != distance) { - trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits())); - } - } catch (NumberFormatException e) { - throw e; - } - - // trackable goal - trackable.setGoal(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())); - - // trackable details & image - try { - final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page); - if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) { - final String image = StringUtils.trim(matcherDetailsImage.group(3)); - final String details = StringUtils.trim(matcherDetailsImage.group(4)); - - if (StringUtils.isNotEmpty(image)) { - trackable.setImage(image); - } - if (StringUtils.isNotEmpty(details) && !StringUtils.equals(details, "No additional details available.")) { - trackable.setDetails(details); - } - } - } catch (Exception e) { - // failed to parse trackable details & image - Log.w("cgeoBase.parseTrackable: Failed to parse trackable details & image"); - } - - // trackable logs - try - { - final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page); - /* - * 1. Type (img) - * 2. Date - * 3. Author - * 4. Cache-GUID - * 5. <ignored> (strike-through property for ancien caches) - * 6. Cache-name - * 7. Logtext - */ - while (matcherLogs.find()) - { - final cgLog logDone = new cgLog(); - - logDone.type = LogType.getByIconName(matcherLogs.group(1)); - logDone.author = Html.fromHtml(matcherLogs.group(3)).toString().trim(); - - try - { - logDone.date = Login.parseGcCustomDate(matcherLogs.group(2)).getTime(); - } catch (ParseException e) { - } - - logDone.log = matcherLogs.group(7).trim(); - - if (matcherLogs.group(4) != null && matcherLogs.group(6) != null) - { - logDone.cacheGuid = matcherLogs.group(4); - logDone.cacheName = matcherLogs.group(6); - } - - // Apply the pattern for images in a trackable log entry against each full log (group(0)) - final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(matcherLogs.group(0)); - /* - * 1. Image URL - * 2. Image title - */ - while (matcherLogImages.find()) - { - final cgImage logImage = new cgImage(matcherLogImages.group(1), matcherLogImages.group(2)); - if (logDone.logImages == null) { - logDone.logImages = new ArrayList<cgImage>(); - } - logDone.logImages.add(logImage); - } - - trackable.getLogs().add(logDone); - } - } catch (Exception e) { - // failed to parse logs - Log.w("cgeoBase.parseCache: Failed to parse cache logs" + e.toString()); - } - - // trackingcode - if (!StringUtils.equalsIgnoreCase(trackable.getGeocode(), possibleTrackingcode)) { - trackable.setTrackingcode(possibleTrackingcode); - } - - if (app != null) { - app.saveTrackable(trackable); - } - - return trackable; - } - - public static List<LogType> parseTypes(String page) { - if (StringUtils.isEmpty(page)) { - return null; - } - - final List<LogType> types = new ArrayList<LogType>(); - - final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page); - String typesText = null; - if (typeBoxMatcher.find()) { - if (typeBoxMatcher.groupCount() > 0) { - typesText = typeBoxMatcher.group(1); - } - } - - if (typesText != null) { - - final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText); - while (typeMatcher.find()) { - if (typeMatcher.groupCount() > 1) { - final int type = Integer.parseInt(typeMatcher.group(2)); - - if (type > 0) { - types.add(LogType.getById(type)); - } - } - } - } - - return types; - } - - public static List<cgTrackableLog> parseTrackableLog(final String page) { - if (StringUtils.isEmpty(page)) { - return null; - } - - final List<cgTrackableLog> trackables = new ArrayList<cgTrackableLog>(); - - String table = StringUtils.substringBetween(page, "<table id=\"tblTravelBugs\"", "</table>"); - - // if no trackables are currently in the account, the table is not available, so return an empty list instead of null - if (StringUtils.isBlank(table)) { - return trackables; - } - - table = StringUtils.substringBetween(table, "<tbody>", "</tbody>"); - if (StringUtils.isBlank(table)) { - Log.e("cgeoBase.parseTrackableLog: tbody not found on page"); - return null; - } - - final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page); - while (trackableMatcher.find()) { - if (trackableMatcher.groupCount() > 0) { - final cgTrackableLog trackableLog = new cgTrackableLog(); - - if (trackableMatcher.group(1) != null) { - trackableLog.trackCode = trackableMatcher.group(1); - } else { - continue; - } - if (trackableMatcher.group(2) != null) { - trackableLog.name = Html.fromHtml(trackableMatcher.group(2)).toString(); - } else { - continue; - } - if (trackableMatcher.group(3) != null) { - trackableLog.ctl = Integer.valueOf(trackableMatcher.group(3)); - } else { - continue; - } - if (trackableMatcher.group(5) != null) { - trackableLog.id = Integer.valueOf(trackableMatcher.group(5)); - } else { - continue; - } - - Log.i("Trackable in inventory (#" + trackableLog.ctl + "/" + trackableLog.id + "): " + trackableLog.trackCode + " - " + trackableLog.name); - - trackables.add(trackableLog); - } - } - - return trackables; - } - - /** - * Insert the right cache type restriction in parameters - * - * @param params - * the parameters to insert the restriction into - * @param cacheType - * the type of cache, or null to include everything - */ - static private void insertCacheType(final Parameters params, final CacheType cacheType) { - params.put("tx", cacheType.guid); - } - public static SearchResult searchByNextPage(cgSearchThread thread, final SearchResult search, boolean showCaptcha) { if (search == null) { return search; @@ -1271,7 +730,7 @@ public class cgBase { return search; } - if (isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { Log.e("cgeoBase.searchByNextPage: No viewstate given"); return search; } @@ -1318,30 +777,25 @@ public class cgBase { return search; } - public static SearchResult searchByGeocode(final String geocode, final String guid, final int listId, final boolean forceReload, final CancellableHandler handler) { - if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) { - Log.e("cgeoBase.searchByGeocode: No geocode nor guid given"); - return null; - } - - cgeoapplication app = cgeoapplication.getInstance(); - if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (app.isOffline(geocode, guid) || app.isThere(geocode, guid, true, true))) { - final SearchResult search = new SearchResult(); - final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : app.getGeocode(guid); - search.addGeocode(realGeocode); - return search; - } - - // if we have no geocode, we can't dynamically select the handler, but must explicitly use GC - if (geocode == null && guid != null) { - return GCConnector.getInstance().searchByGeocode(null, guid, app, handler); + /** + * Possibly hide caches found or hidden by user. This mutates its params argument when possible. + * + * @param params + * the parameters to mutate, or null to create a new Parameters if needed + * @param my + * @param addF + * @return the original params if not null, maybe augmented with f=1, or a new Parameters with f=1 or null otherwise + */ + public static Parameters addFToParams(final Parameters params, final boolean my, final boolean addF) { + if (!my && Settings.isExcludeMyCaches() && addF) { + if (params == null) { + return new Parameters("f", "1"); + } + params.put("f", "1"); + Log.i("Skipping caches found or hidden by user."); } - return ConnectorFactory.getConnector(geocode).searchByGeocode(geocode, guid, app, handler); - } - - public static SearchResult searchByStored(final Geopoint coords, final CacheType cacheType, final int list) { - return cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, cacheType, list); + return params; } /** @@ -1457,8 +911,8 @@ public class cgBase { public static StatusCode postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, - final String log, final List<cgTrackableLog> trackables) { - if (isEmpty(viewstates)) { + final String log, final List<TrackableLog> trackables) { + if (Login.isEmpty(viewstates)) { Log.e("cgeoBase.postLog: No viewstate given"); return StatusCode.LOG_POST_ERROR; } @@ -1508,7 +962,7 @@ public class cgBase { if (trackables != null && !trackables.isEmpty()) { // we have some trackables to proceed final StringBuilder hdnSelected = new StringBuilder(); - for (final cgTrackableLog tb : trackables) { + for (final TrackableLog tb : trackables) { if (tb.action != LogTypeTrackable.DO_NOTHING) { hdnSelected.append(Integer.toString(tb.id)); hdnSelected.append(tb.action.action); @@ -1545,7 +999,7 @@ public class cgBase { if (matcher.find() && matcher.groupCount() > 0) { final String[] viewstatesConfirm = Login.getViewstates(page); - if (isEmpty(viewstatesConfirm)) { + if (Login.isEmpty(viewstatesConfirm)) { Log.e("cgeoBase.postLog: No viewstate for confirm log"); return StatusCode.LOG_POST_ERROR; } @@ -1561,7 +1015,7 @@ public class cgBase { if (trackables != null && !trackables.isEmpty()) { // we have some trackables to proceed final StringBuilder hdnSelected = new StringBuilder(); - for (cgTrackableLog tb : trackables) { + for (TrackableLog tb : trackables) { String ctl = null; final String action = Integer.toString(tb.id) + tb.action.action; @@ -1615,7 +1069,7 @@ public class cgBase { public static StatusCode postLogTrackable(final String tbid, final String trackingCode, final String[] viewstates, final LogType logType, final int year, final int month, final int day, final String log) { - if (isEmpty(viewstates)) { + if (Login.isEmpty(viewstates)) { Log.e("cgeoBase.postLogTrackable: No viewstate given"); return StatusCode.LOG_POST_ERROR; } @@ -1743,221 +1197,422 @@ public class cgBase { } /** - * Possibly hide caches found or hidden by user. This mutates its params argument when possible. + * Parse a trackable HTML description into a cgTrackable object * - * @param params - * the parameters to mutate, or null to create a new Parameters if needed - * @param my - * @param addF - * @return the original params if not null, maybe augmented with f=1, or a new Parameters with f=1 or null otherwise + * @param page + * the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace} + * @param app + * if not null, the application to use to save the trackable + * @return the parsed trackable, or null if none could be parsed */ - public static Parameters addFToParams(final Parameters params, final boolean my, final boolean addF) { - if (!my && Settings.isExcludeMyCaches() && addF) { - if (params == null) { - return new Parameters("f", "1"); - } - params.put("f", "1"); - Log.i("Skipping caches found or hidden by user."); + public static cgTrackable parseTrackable(final String page, final cgeoapplication app, final String possibleTrackingcode) { + if (StringUtils.isBlank(page)) { + Log.e("cgeoBase.parseTrackable: No page given"); + return null; } - return params; - } + final cgTrackable trackable = new cgTrackable(); + + // trackable geocode + trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()).toUpperCase()); + + // trackable id + trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid())); - public static void storeCache(Activity activity, cgCache origCache, String geocode, int listId, boolean forceRedownload, CancellableHandler handler) { + // trackable icon + trackable.setIconUrl(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ICON, true, trackable.getIconUrl())); + + // trackable name + trackable.setName(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_NAME, true, trackable.getName())); + + // trackable type + if (StringUtils.isNotBlank(trackable.getName())) { + trackable.setType(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_TYPE, true, trackable.getType())); + } + + // trackable owner name try { - cgCache cache; - // get cache details, they may not yet be complete - if (origCache != null) { - // only reload the cache if it was already stored or doesn't have full details (by checking the description) - if (origCache.getListId() >= StoredList.STANDARD_LIST_ID || StringUtils.isBlank(origCache.getDescription())) { - final SearchResult search = searchByGeocode(origCache.getGeocode(), null, listId, false, handler); - cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); - } else { - cache = origCache; - } - } else if (StringUtils.isNotBlank(geocode)) { - final SearchResult search = searchByGeocode(geocode, null, listId, forceRedownload, handler); - cache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); - } else { - cache = null; + final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page); + if (matcherOwner.find() && matcherOwner.groupCount() > 0) { + trackable.setOwnerGuid(matcherOwner.group(1)); + trackable.setOwner(matcherOwner.group(2).trim()); } + } catch (Exception e) { + // failed to parse trackable owner name + Log.w("cgeoBase.parseTrackable: Failed to parse trackable owner name"); + } - if (cache == null) { - if (handler != null) { - handler.sendMessage(Message.obtain()); - } + // trackable origin + trackable.setOrigin(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ORIGIN, true, trackable.getOrigin())); - return; + // trackable spotted + try { + final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page); + if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) { + trackable.setSpottedGuid(matcherSpottedCache.group(1)); + trackable.setSpottedName(matcherSpottedCache.group(2).trim()); + trackable.setSpottedType(cgTrackable.SPOTTED_CACHE); } - if (CancellableHandler.isCancelled(handler)) { - return; + final Matcher matcherSpottedUser = GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER.matcher(page); + if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) { + trackable.setSpottedGuid(matcherSpottedUser.group(1)); + trackable.setSpottedName(matcherSpottedUser.group(2).trim()); + trackable.setSpottedType(cgTrackable.SPOTTED_USER); } - final HtmlImage imgGetter = new HtmlImage(activity, cache.getGeocode(), false, listId, true); - - // store images from description - if (StringUtils.isNotBlank(cache.getDescription())) { - Html.fromHtml(cache.getDescription(), imgGetter, null); + if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) { + trackable.setSpottedType(cgTrackable.SPOTTED_UNKNOWN); } - if (CancellableHandler.isCancelled(handler)) { - return; + if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) { + trackable.setSpottedType(cgTrackable.SPOTTED_OWNER); } + } catch (Exception e) { + // failed to parse trackable last known place + Log.w("cgeoBase.parseTrackable: Failed to parse trackable last known place"); + } - // store spoilers - if (CollectionUtils.isNotEmpty(cache.getSpoilers())) { - for (cgImage oneSpoiler : cache.getSpoilers()) { - imgGetter.getDrawable(oneSpoiler.getUrl()); + // released date - can be missing on the page + try { + String releaseString = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null); + if (releaseString != null) { + trackable.setReleased(dateTbIn1.parse(releaseString)); + if (trackable.getReleased() == null) { + trackable.setReleased(dateTbIn2.parse(releaseString)); } } + } catch (ParseException e1) { + trackable.setReleased(null); + } - if (CancellableHandler.isCancelled(handler)) { - return; + // trackable distance + try { + final String distance = BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null); + if (null != distance) { + trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits())); } + } catch (NumberFormatException e) { + throw e; + } - // store images from logs - if (Settings.isStoreLogImages()) { - for (cgLog log : cache.getLogs(true)) { - if (CollectionUtils.isNotEmpty(log.logImages)) { - for (cgImage oneLogImg : log.logImages) { - imgGetter.getDrawable(oneLogImg.getUrl()); - } - } + // trackable goal + trackable.setGoal(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())); + + // trackable details & image + try { + final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page); + if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) { + final String image = StringUtils.trim(matcherDetailsImage.group(3)); + final String details = StringUtils.trim(matcherDetailsImage.group(4)); + + if (StringUtils.isNotEmpty(image)) { + trackable.setImage(image); + } + if (StringUtils.isNotEmpty(details) && !StringUtils.equals(details, "No additional details available.")) { + trackable.setDetails(details); } } + } catch (Exception e) { + // failed to parse trackable details & image + Log.w("cgeoBase.parseTrackable: Failed to parse trackable details & image"); + } - if (CancellableHandler.isCancelled(handler)) { - return; - } + // trackable logs + try + { + final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page); + /* + * 1. Type (img) + * 2. Date + * 3. Author + * 4. Cache-GUID + * 5. <ignored> (strike-through property for ancien caches) + * 6. Cache-name + * 7. Logtext + */ + while (matcherLogs.find()) + { + final LogEntry logDone = new LogEntry(); - // store map previews - StaticMapsProvider.downloadMaps(cache, activity); + logDone.type = LogType.getByIconName(matcherLogs.group(1)); + logDone.author = Html.fromHtml(matcherLogs.group(3)).toString().trim(); - if (CancellableHandler.isCancelled(handler)) { - return; - } + try + { + logDone.date = Login.parseGcCustomDate(matcherLogs.group(2)).getTime(); + } catch (ParseException e) { + } - cache.setListId(listId); - cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); + logDone.log = matcherLogs.group(7).trim(); + + if (matcherLogs.group(4) != null && matcherLogs.group(6) != null) + { + logDone.cacheGuid = matcherLogs.group(4); + logDone.cacheName = matcherLogs.group(6); + } + + // Apply the pattern for images in a trackable log entry against each full log (group(0)) + final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(matcherLogs.group(0)); + /* + * 1. Image URL + * 2. Image title + */ + while (matcherLogImages.find()) + { + final cgImage logImage = new cgImage(matcherLogImages.group(1), matcherLogImages.group(2)); + logDone.addLogImage(logImage); + } - if (handler != null) { - handler.sendMessage(Message.obtain()); + trackable.getLogs().add(logDone); } } catch (Exception e) { - Log.e("cgBase.storeCache"); + // failed to parse logs + Log.w("cgeoBase.parseCache: Failed to parse cache logs" + e.toString()); } - } - - public static void refreshCache(Activity activity, String geocode, int listId, CancellableHandler handler) { - cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE)); - storeCache(activity, null, geocode, listId, true, handler); - } - public static void dropCache(final cgCache cache, final Handler handler) { - try { - cgeoapplication.getInstance().markDropped(cache.getGeocode()); - cgeoapplication.getInstance().removeCache(cache.getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE)); + // trackingcode + if (!StringUtils.equalsIgnoreCase(trackable.getGeocode(), possibleTrackingcode)) { + trackable.setTrackingcode(possibleTrackingcode); + } - handler.sendMessage(Message.obtain()); - } catch (Exception e) { - Log.e("cgBase.dropCache: " + e.toString()); + if (app != null) { + app.saveTrackable(trackable); } - } - /** - * Generate a time string according to system-wide settings (locale, 12/24 hour) - * such as "13:24". - * - * @param date - * milliseconds since the epoch - * @return the formatted string - */ - public static String formatTime(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_TIME); + return trackable; } /** - * Generate a date string according to system-wide settings (locale, date format) - * such as "20 December" or "20 December 2010". The year will only be included when necessary. + * Load logs from a cache details page. * - * @param date - * milliseconds since the epoch - * @return the formatted string + * @param page + * the text of the details page + * @param cache + * the cache object to put the logs in + * @param friends + * retrieve friend logs */ - public static String formatDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE); + private static List<LogEntry> loadLogsFromDetails(final String page, final cgCache cache, final boolean friends, final boolean getDataFromPage) { + String rawResponse = null; + + if (!getDataFromPage) { + final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN2.matcher(page); + if (!userTokenMatcher.find()) { + Log.e("cgBase.loadLogsFromDetails: unable to extract userToken"); + return null; + } + + final String userToken = userTokenMatcher.group(1); + final Parameters params = new Parameters( + "tkn", userToken, + "idx", "1", + "num", String.valueOf(GCConstants.NUMBER_OF_LOGS), + "decrypt", "true", + // "sp", Boolean.toString(personal), // personal logs + "sf", Boolean.toString(friends)); + + final HttpResponse response = Network.getRequest("http://www.geocaching.com/seek/geocache.logbook", params); + if (response == null) { + Log.e("cgBase.loadLogsFromDetails: cannot log logs, response is null"); + return null; + } + final int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != 200) { + Log.e("cgBase.loadLogsFromDetails: error " + statusCode + " when requesting log information"); + return null; + } + rawResponse = Network.getResponseData(response); + if (rawResponse == null) { + Log.e("cgBase.loadLogsFromDetails: unable to read whole response"); + return null; + } + } else { + // extract embedded JSON data from page + rawResponse = BaseUtils.getMatch(page, GCConstants.PATTERN_LOGBOOK, ""); + } + + List<LogEntry> logs = new ArrayList<LogEntry>(); + + try { + final JSONObject resp = new JSONObject(rawResponse); + if (!resp.getString("status").equals("success")) { + Log.e("cgBase.loadLogsFromDetails: status is " + resp.getString("status")); + return null; + } + + final JSONArray data = resp.getJSONArray("data"); + + for (int index = 0; index < data.length(); index++) { + final JSONObject entry = data.getJSONObject(index); + final LogEntry logDone = new LogEntry(); + logDone.friend = friends; + + // FIXME: use the "LogType" field instead of the "LogTypeImage" one. + final String logIconNameExt = entry.optString("LogTypeImage", ".gif"); + final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4); + logDone.type = LogType.getByIconName(logIconName); + + try { + logDone.date = Login.parseGcCustomDate(entry.getString("Visited")).getTime(); + } catch (ParseException e) { + Log.e("cgBase.loadLogsFromDetails: failed to parse log date."); + } + + logDone.author = entry.getString("UserName"); + logDone.found = entry.getInt("GeocacheFindCount"); + logDone.log = entry.getString("LogText"); + + final JSONArray images = entry.getJSONArray("Images"); + for (int i = 0; i < images.length(); i++) { + final JSONObject image = images.getJSONObject(i); + String url = "http://img.geocaching.com/cache/log/" + image.getString("FileName"); + String title = image.getString("Name"); + final cgImage logImage = new cgImage(url, title); + logDone.addLogImage(logImage); + } + + logs.add(logDone); + } + } catch (JSONException e) { + // failed to parse logs + Log.w("cgBase.loadLogsFromDetails: Failed to parse cache logs", e); + } + + return logs; } - /** - * Generate a date string according to system-wide settings (locale, date format) - * such as "20 December 2010". The year will always be included, making it suitable - * to generate long-lived log entries. - * - * @param date - * milliseconds since the epoch - * @return the formatted string - */ - public static String formatFullDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_SHOW_YEAR); + public static List<LogType> parseTypes(String page) { + if (StringUtils.isEmpty(page)) { + return null; + } + + final List<LogType> types = new ArrayList<LogType>(); + + final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page); + String typesText = null; + if (typeBoxMatcher.find()) { + if (typeBoxMatcher.groupCount() > 0) { + typesText = typeBoxMatcher.group(1); + } + } + + if (typesText != null) { + + final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText); + while (typeMatcher.find()) { + if (typeMatcher.groupCount() > 1) { + final int type = Integer.parseInt(typeMatcher.group(2)); + + if (type > 0) { + types.add(LogType.getById(type)); + } + } + } + } + + return types; } - /** - * Generate a numeric date string according to system-wide settings (locale, date format) - * such as "10/20/2010". - * - * @param date - * milliseconds since the epoch - * @return the formatted string - */ - public static String formatShortDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_NUMERIC_DATE); + public static List<TrackableLog> parseTrackableLog(final String page) { + if (StringUtils.isEmpty(page)) { + return null; + } + + String table = StringUtils.substringBetween(page, "<table id=\"tblTravelBugs\"", "</table>"); + + // if no trackables are currently in the account, the table is not available, so return an empty list instead of null + if (StringUtils.isBlank(table)) { + return Collections.emptyList(); + } + + table = StringUtils.substringBetween(table, "<tbody>", "</tbody>"); + if (StringUtils.isBlank(table)) { + Log.e("cgeoBase.parseTrackableLog: tbody not found on page"); + return null; + } + + final List<TrackableLog> trackableLogs = new ArrayList<TrackableLog>(); + + final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page); + while (trackableMatcher.find()) { + if (trackableMatcher.groupCount() > 0) { + + final String trackCode = trackableMatcher.group(1); + final String name = Html.fromHtml(trackableMatcher.group(2)).toString(); + try { + final Integer ctl = Integer.valueOf(trackableMatcher.group(3)); + final Integer id = Integer.valueOf(trackableMatcher.group(5)); + if (trackCode != null && name != null && ctl != null && id != null) { + final TrackableLog entry = new TrackableLog(trackCode, name, id.intValue(), ctl.intValue()); + + Log.i("Trackable in inventory (#" + entry.ctl + "/" + entry.id + "): " + entry.trackCode + " - " + entry.name); + trackableLogs.add(entry); + } + } catch (NumberFormatException e) { + Log.e("GCParser.parseTrackableLog", e); + } + } + } + + return trackableLogs; } /** - * Generate a numeric date and time string according to system-wide settings (locale, - * date format) such as "7 sept. at 12:35". + * Insert the right cache type restriction in parameters * - * @param context - * a Context - * @param date - * milliseconds since the epoch - * @return the formatted string + * @param params + * the parameters to insert the restriction into + * @param cacheType + * the type of cache, or null to include everything */ - public static String formatShortDateTime(Context context, long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL); + static private void insertCacheType(final Parameters params, final CacheType cacheType) { + params.put("tx", cacheType.guid); } - /** - * Indicates whether the specified action can be used as an intent. This - * method queries the package manager for installed packages that can - * respond to an intent with the specified action. If no suitable package is - * found, this method returns false. - * - * @param context - * The application's environment. - * @param action - * The Intent action to check for availability. - * @param uri - * The Intent URI to check for availability. - * - * @return True if an Intent with the specified action can be sent and - * responded to, false otherwise. - */ - public static boolean isIntentAvailable(Context context, String action, Uri uri) { - final PackageManager packageManager = context.getPackageManager(); - final Intent intent; - if (uri == null) { - intent = new Intent(action); - } else { - intent = new Intent(action, uri); + private static void getExtraOnlineInfo(final cgCache cache, final String page, final CancellableHandler handler) { + if (CancellableHandler.isCancelled(handler)) { + return; + } + + //cache.setLogs(loadLogsFromDetails(page, cache, false)); + if (Settings.isFriendLogsWanted()) { + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); + List<LogEntry> allLogs = cache.getLogs(); + List<LogEntry> friendLogs = loadLogsFromDetails(page, cache, true, false); + if (friendLogs != null) { + for (LogEntry log : friendLogs) { + if (allLogs.contains(log)) { + allLogs.get(allLogs.indexOf(log)).friend = true; + } else { + allLogs.add(log); + } + } + } + } + + if (Settings.isElevationWanted()) { + if (CancellableHandler.isCancelled(handler)) { + return; + } + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_elevation); + if (cache.getCoords() != null) { + cache.setElevation(cache.getCoords().getElevation()); + } + } + + if (Settings.isRatingWanted()) { + if (CancellableHandler.isCancelled(handler)) { + return; + } + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote); + final GCVoteRating rating = GCVote.getRating(cache.getGuid(), cache.getGeocode()); + if (rating != null) { + cache.setRating(rating.getRating()); + cache.setVotes(rating.getVotes()); + cache.setMyVote(rating.getMyVote()); + } } - List<ResolveInfo> list = packageManager.queryIntentActivities(intent, - PackageManager.MATCH_DEFAULT_ONLY); - return list.size() > 0; } } - diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java index 4605bc9..1e614df 100644 --- a/main/src/cgeo/geocaching/connector/gc/Login.java +++ b/main/src/cgeo/geocaching/connector/gc/Login.java @@ -2,7 +2,7 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Cookies; import cgeo.geocaching.network.HtmlImage; @@ -63,15 +63,12 @@ public abstract class Login { final ImmutablePair<String, String> login = Settings.getLogin(); if (login == null || StringUtils.isEmpty(login.left) || StringUtils.isEmpty(login.right)) { - Login.setActualStatus(cgBase.res.getString(R.string.err_login)); + Login.setActualStatus(cgeoapplication.getInstance().getString(R.string.err_login)); Log.e("cgeoBase.login: No login information stored"); return StatusCode.NO_LOGIN_INFO_STORED; } - // res is null during the unit tests - if (cgBase.res != null) { - Login.setActualStatus(cgBase.res.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 && BaseUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) { @@ -100,7 +97,7 @@ public abstract class Login { "ctl00$ContentBody$cbRememberMe", "on", "ctl00$ContentBody$btnSignIn", "Login"); final String[] viewstates = Login.getViewstates(loginData); - if (cgBase.isEmpty(viewstates)) { + if (isEmpty(viewstates)) { Log.e("cgeoBase.login: Failed to find viewstates"); return StatusCode.LOGIN_PARSE_ERROR; // no viewstates } @@ -189,10 +186,7 @@ public abstract class Login { return false; } - // res is null during the unit tests - if (cgBase.res != null) { - setActualStatus(cgBase.res.getString(R.string.init_login_popup_ok)); - } + setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_ok)); // on every page except login page setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME)); @@ -210,10 +204,7 @@ public abstract class Login { return true; } - // res is null during the unit tests - if (cgBase.res != null) { - setActualStatus(cgBase.res.getString(R.string.init_login_popup_failed)); - } + setActualStatus(cgeoapplication.getInstance().getString(R.string.init_login_popup_failed)); return false; } @@ -307,6 +298,24 @@ public abstract class Login { } /** + * checks if an Array of Strings is empty or not. Empty means: + * - Array is null + * - or all elements are null or empty strings + */ + public static boolean isEmpty(String[] a) { + if (a == null) { + return true; + } + + for (String s : a) { + if (StringUtils.isNotEmpty(s)) { + return false; + } + } + return true; + } + + /** * read all viewstates from page * * @return String[] with all view states diff --git a/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java b/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java index 80786f9..4e4d9f7 100644 --- a/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/opencaching/OkapiClient.java @@ -2,7 +2,7 @@ package cgeo.geocaching.connector.opencaching; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgImage; -import cgeo.geocaching.cgLog; +import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; @@ -202,18 +202,18 @@ final public class OkapiClient { return user.getString(USER_USERNAME); } - private static List<cgLog> parseLogs(JSONArray logsJSON) { - List<cgLog> result = null; + private static List<LogEntry> parseLogs(JSONArray logsJSON) { + List<LogEntry> result = null; for (int i = 0; i < logsJSON.length(); i++) { try { JSONObject logResponse = logsJSON.getJSONObject(i); - cgLog log = new cgLog(); + LogEntry log = new LogEntry(); log.date = parseDate(logResponse.getString(LOG_DATE)).getTime(); log.log = logResponse.getString(LOG_COMMENT).trim(); log.type = parseLogType(logResponse.getString(LOG_TYPE)); log.author = parseUser(logResponse.getJSONObject(LOG_USER)); if (result == null) { - result = new ArrayList<cgLog>(); + result = new ArrayList<LogEntry>(); } result.add(log); } catch (JSONException e) { diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java index f9f13e3..32c9943 100644 --- a/main/src/cgeo/geocaching/export/FieldnoteExport.java +++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java @@ -2,7 +2,7 @@ package cgeo.geocaching.export; import cgeo.geocaching.R; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgLog; +import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.Progress; @@ -144,7 +144,7 @@ class FieldnoteExport extends AbstractExport { try { final cgCache cache = caches.get(i); if (cache.isLogOffline()) { - cgLog log = cgeoapplication.getInstance().loadLogOffline(cache.getGeocode()); + LogEntry log = cgeoapplication.getInstance().loadLogOffline(cache.getGeocode()); if (null != logTypes.get(log.type)) { fieldNoteBuffer.append(cache.getGeocode()) .append(',') diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index bebbed8..2c833a2 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -2,7 +2,7 @@ package cgeo.geocaching.export; import cgeo.geocaching.R; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgLog; +import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.Progress; @@ -209,7 +209,7 @@ class GpxExport extends AbstractExport { if (cache.getLogs().size() > 0) { gpx.append("<groundspeak:logs>"); - for (cgLog log : cache.getLogs()) { + for (LogEntry log : cache.getLogs()) { gpx.append("<groundspeak:log id=\""); gpx.append(log.id); gpx.append("\">"); diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java index 1706964..051a49b 100644 --- a/main/src/cgeo/geocaching/files/GPXParser.java +++ b/main/src/cgeo/geocaching/files/GPXParser.java @@ -3,7 +3,7 @@ package cgeo.geocaching.files; import cgeo.geocaching.R; import cgeo.geocaching.StoredList; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgLog; +import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgTrackable; import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.cgeoapplication; @@ -76,7 +76,7 @@ public abstract class GPXParser extends FileParser { private cgCache cache; private cgTrackable trackable = new cgTrackable(); - private cgLog log = new cgLog(); + private LogEntry log = new LogEntry(); private String type = null; private String sym = null; @@ -674,7 +674,7 @@ public abstract class GPXParser extends FileParser { @Override public void start(Attributes attrs) { - log = new cgLog(); + log = new LogEntry(); try { if (attrs.getIndex("id") > -1) { diff --git a/main/src/cgeo/geocaching/go4cache/Go4Cache.java b/main/src/cgeo/geocaching/go4cache/Go4Cache.java index 782919c..b0a7b35 100644 --- a/main/src/cgeo/geocaching/go4cache/Go4Cache.java +++ b/main/src/cgeo/geocaching/go4cache/Go4Cache.java @@ -1,7 +1,6 @@ package cgeo.geocaching.go4cache; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter.Format; @@ -16,6 +15,8 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -41,6 +42,7 @@ public final class Go4Cache extends Thread { private final static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 2010-07-25 14:44:01 final private ArrayBlockingQueue<Geopoint> queue = new ArrayBlockingQueue<Geopoint>(1); + private String packageVersion; public static Go4Cache getInstance() { // no need to be synchronized return InstanceHolder.INSTANCE; @@ -48,10 +50,22 @@ public final class Go4Cache extends Thread { private Go4Cache() { // private singleton constructor super("Go4Cache"); + initializeVersion(); setPriority(Thread.MIN_PRIORITY); start(); } + private void initializeVersion() { + try { + final PackageManager manager = cgeoapplication.getInstance().getPackageManager(); + final PackageInfo info = manager.getPackageInfo(cgeoapplication.getInstance().getPackageName(), 0); + packageVersion = info.versionName; + } catch (PackageManager.NameNotFoundException e) { + Log.e("unable to get version information", e); + packageVersion = null; + } + } + /** * Send the coordinates to go4cache.com if the user opted in to do so. * @@ -96,8 +110,8 @@ public final class Go4Cache extends Thread { "ln", lonStr, "a", currentAction, "s", (CryptUtils.sha1(username + "|" + latStr + "|" + lonStr + "|" + currentAction + "|" + CryptUtils.md5("carnero: developing your dreams"))).toLowerCase()); - if (null != cgBase.version) { - params.put("v", cgBase.version); + if (null != packageVersion) { + params.put("v", packageVersion); } Network.postRequest("http://api.go4cache.com/", params); diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index d163a8a..e5f8701 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -8,7 +8,6 @@ import cgeo.geocaching.Settings; import cgeo.geocaching.StoredList; import cgeo.geocaching.UpdateDirectionCallback; import cgeo.geocaching.UpdateLocationCallback; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgDirection; import cgeo.geocaching.cgGeo; @@ -1540,7 +1539,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto break; } - cgBase.storeCache(activity, null, geocode, StoredList.STANDARD_LIST_ID, false, handler); + cgCache.storeCache(activity, null, geocode, StoredList.STANDARD_LIST_ID, false, handler); } } catch (Exception e) { Log.e("cgeocaches.LoadDetails.run: " + e.toString()); diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index 8b7ef3c..8aed160 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -36,6 +36,7 @@ import android.net.Uri; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.zip.GZIPInputStream; @@ -128,41 +129,92 @@ public abstract class Network { * @return */ public static HttpResponse postRequest(final String uri, final Parameters params) { - try { - final HttpPost request = new HttpPost(uri); - if (params != null) { - request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); - } - return Network.request(request); - } catch (final Exception e) { - // Can be UnsupportedEncodingException, ClientProtocolException or IOException - Log.e("postRequest", e); - return null; - } + return request("POST", uri, params, null, null); } /** - * GET HTTP request + * Make an HTTP request * + * @param method + * the HTTP method to use ("GET" or "POST") * @param uri * the URI to request * @param params * the parameters to add the the GET request * @param headers * the headers to add to the GET request - * @return the HTTP response + * @param cacheFile + * the cache file used to cache this query + * @return the HTTP response, or null in case of an encoding error in a POST request arguments */ - public static HttpResponse getRequest(final String uri, final Parameters params, final Parameters headers) { - final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString(); - final HttpRequestBase request = new HttpGet(fullUri); + private static HttpResponse request(final String method, final String uri, final Parameters params, final Parameters headers, final File cacheFile) { + HttpRequestBase request; + if (method.equals("GET")) { + final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString(); + request = new HttpGet(fullUri); + } else { + request = new HttpPost(uri); + if (params != null) { + try { + ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); + } catch (final UnsupportedEncodingException e) { + Log.e("request", e); + return null; + } + } + } - if (headers != null) { - for (final NameValuePair header : headers) { - request.setHeader(header.getName(), header.getValue()); + for (final NameValuePair header : Parameters.extend(Parameters.merge(headers, cacheHeaders(cacheFile)), + "Accept-Charset", "utf-8,iso-8859-1;q=0.8,utf-16;q=0.8,*;q=0.7", + "Accept-Language", "en-US,*;q=0.9", + "X-Requested-With", "XMLHttpRequest")) { + request.setHeader(header.getName(), header.getValue()); + } + + request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Network.USER_AGENT); + + final String reqLogStr = request.getMethod() + " " + Network.hidePassword(request.getURI().toString()); + Log.d(reqLogStr); + + final HttpClient client = Network.getHttpClient(); + for (int i = 0; i <= Network.NB_DOWNLOAD_RETRIES; i++) { + final long before = System.currentTimeMillis(); + try { + final HttpResponse response = client.execute(request); + int status = response.getStatusLine().getStatusCode(); + if (status == 200) { + Log.d(status + Network.formatTimeSpan(before) + reqLogStr); + } else { + Log.w(status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr); + } + return response; + } catch (IOException e) { + final String timeSpan = Network.formatTimeSpan(before); + final String tries = (i + 1) + "/" + (Network.NB_DOWNLOAD_RETRIES + 1); + if (i == Network.NB_DOWNLOAD_RETRIES) { + Log.e("Failure " + tries + timeSpan + reqLogStr, e); + } else { + Log.e("Failure " + tries + " (" + e.toString() + ")" + timeSpan + "- retrying " + reqLogStr); + } } } - return Network.request(request); + return null; + } + + private static Parameters cacheHeaders(final File cacheFile) { + if (cacheFile != null && cacheFile.exists()) { + final String etag = LocalStorage.getSavedHeader(cacheFile, "etag"); + if (etag != null) { + return new Parameters("If-None-Match", etag); + } else { + final String lastModified = LocalStorage.getSavedHeader(cacheFile, "last-modified"); + if (lastModified != null) { + return new Parameters("If-Modified-Since", lastModified); + } + } + } + return null; } /** @@ -177,21 +229,10 @@ public abstract class Network { * @return the HTTP response */ public static HttpResponse getRequest(final String uri, final Parameters params, final File cacheFile) { - if (cacheFile != null && cacheFile.exists()) { - final String etag = LocalStorage.getSavedHeader(cacheFile, "etag"); - if (etag != null) { - return getRequest(uri, params, new Parameters("If-None-Match", etag)); - } else { - final String lastModified = LocalStorage.getSavedHeader(cacheFile, "last-modified"); - if (lastModified != null) { - return getRequest(uri, params, new Parameters("If-Modified-Since", lastModified)); - } - } - } - - return getRequest(uri, params, (Parameters) null); + return request("GET", uri, params, null, cacheFile); } + /** * GET HTTP request * @@ -202,7 +243,7 @@ public abstract class Network { * @return the HTTP response */ public static HttpResponse getRequest(final String uri, final Parameters params) { - return getRequest(uri, params, (Parameters) null); + return request("GET", uri, params, null, null); } /** @@ -210,45 +251,25 @@ public abstract class Network { * * @param uri * the URI to request + * @param params + * the parameters to add the the GET request + * @param headers + * the headers to add to the GET request * @return the HTTP response */ - public static HttpResponse getRequest(final String uri) { - return getRequest(uri, null, (Parameters) null); + public static HttpResponse getRequest(final String uri, final Parameters params, final Parameters headers) { + return request("GET", uri, params, headers, null); } - public static HttpResponse request(final HttpRequestBase request) { - request.setHeader("Accept-Charset", "utf-8,iso-8859-1;q=0.8,utf-16;q=0.8,*;q=0.7"); - request.setHeader("Accept-Language", "en-US,*;q=0.9"); - request.setHeader("X-Requested-With", "XMLHttpRequest"); - request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, USER_AGENT); - - final String reqLogStr = request.getMethod() + " " + Network.hidePassword(request.getURI().toString()); - Log.d(reqLogStr); - - final HttpClient client = Network.getHttpClient(); - for (int i = 0; i <= Network.NB_DOWNLOAD_RETRIES; i++) { - final long before = System.currentTimeMillis(); - try { - final HttpResponse response = client.execute(request); - int status = response.getStatusLine().getStatusCode(); - if (status == 200) { - Log.d(status + Network.formatTimeSpan(before) + reqLogStr); - } else { - Log.w(status + " [" + response.getStatusLine().getReasonPhrase() + "]" + Network.formatTimeSpan(before) + reqLogStr); - } - return response; - } catch (IOException e) { - final String timeSpan = Network.formatTimeSpan(before); - final String tries = (i + 1) + "/" + (Network.NB_DOWNLOAD_RETRIES + 1); - if (i == Network.NB_DOWNLOAD_RETRIES) { - Log.e("Failure " + tries + timeSpan + reqLogStr, e); - } else { - Log.e("Failure " + tries + " (" + e.toString() + ")" + timeSpan + "- retrying " + reqLogStr); - } - } - } - - return null; + /** + * GET HTTP request + * + * @param uri + * the URI to request + * @return the HTTP response + */ + public static HttpResponse getRequest(final String uri) { + return request("GET", uri, null, null, null); } private static String formatTimeSpan(final long before) { @@ -261,7 +282,7 @@ public abstract class Network { } public static JSONObject requestJSON(final String uri, final Parameters params) { - final HttpResponse response = getRequest(uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01")); + final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null); if (isSuccess(response)) { try { return new JSONObject(Network.getResponseData(response)); diff --git a/main/src/cgeo/geocaching/network/Parameters.java b/main/src/cgeo/geocaching/network/Parameters.java index e65bec2..5c0328a 100644 --- a/main/src/cgeo/geocaching/network/Parameters.java +++ b/main/src/cgeo/geocaching/network/Parameters.java @@ -12,7 +12,7 @@ import java.util.Comparator; /** * List of key/values pairs to be used in a GET or POST request. - * + * */ public class Parameters extends ArrayList<NameValuePair> { @@ -44,14 +44,16 @@ public class Parameters extends ArrayList<NameValuePair> { * list of key/value pairs * @throws InvalidParameterException * if the number of key/values is unbalanced + * @return the object itself to facilitate chaining */ - public void put(final String... keyValues) { + public Parameters put(final String... keyValues) { if (keyValues.length % 2 == 1) { throw new InvalidParameterException("odd number of parameters"); } for (int i = 0; i < keyValues.length; i += 2) { add(new BasicNameValuePair(keyValues[i], keyValues[i + 1])); } + return this; } /** @@ -63,12 +65,46 @@ public class Parameters extends ArrayList<NameValuePair> { Collections.sort(this, comparator); } - /** - * @return the URL encoded string corresponding to those parameters - */ @Override public String toString() { return URLEncodedUtils.format(this, HTTP.UTF_8); } + /** + * Extend or create a Parameters object with new key/value pairs. + * + * @param params + * an existing object or null to create a new one + * @param keyValues + * list of key/value pair + * @throws InvalidParameterException + * if the number of key/values is unbalanced + * @return the object itself if it is non-null, a new one otherwise + */ + public static Parameters extend(final Parameters params, final String... keyValues) { + if (params == null) { + return new Parameters(keyValues); + } else { + return params.put(keyValues); + } + } + + /** + * Merge two (possibly null) Parameters object. + * + * @param params + * the object to merge into if non-null + * @param extra + * the object to merge from if non-null + * @return params with extra data if params was non-null, extra otherwise + */ + public static Parameters merge(final Parameters params, final Parameters extra) { + if (params == null) { + return extra; + } else if (extra != null) { + params.addAll(extra); + } + return params; + } + } diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java index ee7a8b1..54f4505 100644 --- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -3,7 +3,6 @@ package cgeo.geocaching.ui; import cgeo.geocaching.CacheDetailActivity; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheSize; @@ -578,8 +577,8 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { if (cacheListType == CacheListType.HISTORY && cache.getVisitedDate() > 0) { ArrayList<String> infos = new ArrayList<String>(); infos.add(StringUtils.upperCase(cache.getGeocode())); - infos.add(cgBase.formatDate(cache.getVisitedDate())); - infos.add(cgBase.formatTime(cache.getVisitedDate())); + infos.add(Formatter.formatDate(cache.getVisitedDate())); + infos.add(Formatter.formatTime(cache.getVisitedDate())); holder.info.setText(StringUtils.join(infos, Formatter.SEPARATOR)); } else { ArrayList<String> infos = new ArrayList<String>(); @@ -597,7 +596,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { if (cache.getSize() != CacheSize.UNKNOWN && cache.showSize()) { infos.add(cache.getSize().getL10n()); } else if (cache.isEventCache() && cache.getHiddenDate() != null) { - infos.add(cgBase.formatShortDate(cache.getHiddenDate().getTime())); + infos.add(Formatter.formatShortDate(cache.getHiddenDate().getTime())); } if (cache.isPremiumMembersOnly()) { diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java index 661a9a0..6ee1a65 100644 --- a/main/src/cgeo/geocaching/ui/Formatter.java +++ b/main/src/cgeo/geocaching/ui/Formatter.java @@ -1,8 +1,80 @@ package cgeo.geocaching.ui; -public interface Formatter { +import cgeo.geocaching.cgeoapplication; + +import android.content.Context; +import android.text.format.DateUtils; + +public abstract class Formatter { /** Text separator used for formatting texts */ public static final String SEPARATOR = " · "; + private static final Context context = cgeoapplication.getInstance().getBaseContext(); + + /** + * Generate a time string according to system-wide settings (locale, 12/24 hour) + * such as "13:24". + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatTime(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_TIME); + } + + /** + * Generate a date string according to system-wide settings (locale, date format) + * such as "20 December" or "20 December 2010". The year will only be included when necessary. + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatDate(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE); + } + + /** + * Generate a date string according to system-wide settings (locale, date format) + * such as "20 December 2010". The year will always be included, making it suitable + * to generate long-lived log entries. + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatFullDate(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_YEAR); + } + + /** + * Generate a numeric date string according to system-wide settings (locale, date format) + * such as "10/20/2010". + * + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatShortDate(long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_NUMERIC_DATE); + } + + /** + * Generate a numeric date and time string according to system-wide settings (locale, + * date format) such as "7 sept. at 12:35". + * + * @param context + * a Context + * @param date + * milliseconds since the epoch + * @return the formatted string + */ + public static String formatShortDateTime(Context context, long date) { + return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL); + } + } diff --git a/main/src/cgeo/geocaching/utils/CancellableHandler.java b/main/src/cgeo/geocaching/utils/CancellableHandler.java index d4915eb..8cf8f28 100644 --- a/main/src/cgeo/geocaching/utils/CancellableHandler.java +++ b/main/src/cgeo/geocaching/utils/CancellableHandler.java @@ -1,5 +1,7 @@ package cgeo.geocaching.utils; +import cgeo.geocaching.cgeoapplication; + import android.os.Handler; import android.os.Message; @@ -9,6 +11,7 @@ import android.os.Message; */ public abstract class CancellableHandler extends Handler { + protected static final int UPDATE_LOAD_PROGRESS_DETAIL = 42186; private volatile boolean cancelled = false; private static class CancelHolder { @@ -109,4 +112,9 @@ public abstract class CancellableHandler extends Handler { return handler != null && handler.isCancelled(); } + public static void sendLoadProgressDetail(final Handler handler, final int resourceId) { + if (null != handler) { + handler.obtainMessage(UPDATE_LOAD_PROGRESS_DETAIL, cgeoapplication.getInstance().getString(resourceId)).sendToTarget(); + } + } } diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index b8c4a25..60866e0 100644 --- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java +++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java @@ -2,10 +2,10 @@ package cgeo.geocaching.utils; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgBase; import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.network.Network; +import cgeo.geocaching.ui.Formatter; import org.apache.commons.lang3.StringUtils; @@ -55,14 +55,14 @@ public class LogTemplateProvider { @Override public String getValue(final boolean offline) { - return cgBase.formatFullDate(System.currentTimeMillis()); + return Formatter.formatFullDate(System.currentTimeMillis()); } }, new LogTemplate("TIME", R.string.init_signature_template_time) { @Override public String getValue(final boolean offline) { - return cgBase.formatTime(System.currentTimeMillis()); + return Formatter.formatTime(System.currentTimeMillis()); } }, new LogTemplate("DATETIME", R.string.init_signature_template_datetime) { @@ -70,7 +70,7 @@ public class LogTemplateProvider { @Override public String getValue(final boolean offline) { final long currentTime = System.currentTimeMillis(); - return cgBase.formatFullDate(currentTime) + " " + cgBase.formatTime(currentTime); + return Formatter.formatFullDate(currentTime) + " " + Formatter.formatTime(currentTime); } }, new LogTemplate("USER", R.string.init_signature_template_user) { diff --git a/tests/src/cgeo/geocaching/cgDestinationTest.java b/tests/src/cgeo/geocaching/DestinationTest.java index cb5fe45..26caacd 100644 --- a/tests/src/cgeo/geocaching/cgDestinationTest.java +++ b/tests/src/cgeo/geocaching/DestinationTest.java @@ -6,14 +6,14 @@ import android.test.AndroidTestCase; import junit.framework.Assert; -public class cgDestinationTest extends AndroidTestCase { +public class DestinationTest extends AndroidTestCase { - private cgDestination dest = null; + private Destination dest = null; @Override protected void setUp() throws Exception { super.setUp(); - dest = new cgDestination(1, 10000, new Geopoint(52.5, 9.33)); + dest = new Destination(1, 10000, new Geopoint(52.5, 9.33)); } public void testSomething() { diff --git a/tests/src/cgeo/geocaching/TrackablesTest.java b/tests/src/cgeo/geocaching/TrackablesTest.java index 1d3d165..3cb34a6 100644 --- a/tests/src/cgeo/geocaching/TrackablesTest.java +++ b/tests/src/cgeo/geocaching/TrackablesTest.java @@ -1,5 +1,6 @@ package cgeo.geocaching; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; import cgeo.geocaching.test.R; import cgeo.geocaching.utils.BaseUtils; @@ -9,16 +10,16 @@ import java.util.List; public class TrackablesTest extends AbstractResourceInstrumentationTestCase { public void testLogPageWithTrackables() { - List<cgTrackableLog> tbLogs = cgBase.parseTrackableLog(getFileContent(R.raw.log_with_2tb)); + List<TrackableLog> tbLogs = GCParser.parseTrackableLog(getFileContent(R.raw.log_with_2tb)); assertNotNull(tbLogs); assertEquals(2, tbLogs.size()); - cgTrackableLog log = tbLogs.get(0); + TrackableLog log = tbLogs.get(0); assertEquals("Steffen's Kaiserwagen", log.name); assertEquals("1QG1EE", log.trackCode); } public void testLogPageWithoutTrackables() { - List<cgTrackableLog> tbLogs = cgBase.parseTrackableLog(getFileContent(R.raw.log_without_tb)); + List<TrackableLog> tbLogs = GCParser.parseTrackableLog(getFileContent(R.raw.log_without_tb)); assertNotNull(tbLogs); assertEquals(0, tbLogs.size()); } @@ -40,20 +41,20 @@ public class TrackablesTest extends AbstractResourceInstrumentationTestCase { final cgTrackable trackable = getTBXATG(); assertEquals("TBXATG", trackable.getGeocode()); - List<cgLog> log = trackable.getLogs(); + List<LogEntry> log = trackable.getLogs(); // second log entry has several images; just check first two - assertEquals("http://img.geocaching.com/track/log/large/f2e24c50-394c-4d74-8fb4-87298d8bff1d.jpg", log.get(1).logImages.get(0).getUrl()); - assertEquals("7b Welcome to Geowoodstock", log.get(1).logImages.get(0).getTitle()); - assertEquals("http://img.geocaching.com/track/log/large/b57c29c3-134e-4202-a2a1-69ce8920b055.jpg", log.get(1).logImages.get(1).getUrl()); - assertEquals("8 Crater Lake Natl Park Oregon", log.get(1).logImages.get(1).getTitle()); + assertEquals("http://img.geocaching.com/track/log/large/f2e24c50-394c-4d74-8fb4-87298d8bff1d.jpg", log.get(1).getLogImages().get(0).getUrl()); + assertEquals("7b Welcome to Geowoodstock", log.get(1).getLogImages().get(0).getTitle()); + assertEquals("http://img.geocaching.com/track/log/large/b57c29c3-134e-4202-a2a1-69ce8920b055.jpg", log.get(1).getLogImages().get(1).getUrl()); + assertEquals("8 Crater Lake Natl Park Oregon", log.get(1).getLogImages().get(1).getTitle()); // third log entry has one image - assertEquals("http://img.geocaching.com/track/log/large/0096b42d-4d10-45fa-9be2-2d08c0d5cc61.jpg", log.get(2).logImages.get(0).getUrl()); - assertEquals("Traverski's GC Univ coin on tour", log.get(2).logImages.get(0).getTitle()); + assertEquals("http://img.geocaching.com/track/log/large/0096b42d-4d10-45fa-9be2-2d08c0d5cc61.jpg", log.get(2).getLogImages().get(0).getUrl()); + assertEquals("Traverski's GC Univ coin on tour", log.get(2).getLogImages().get(0).getTitle()); } public void testParseTrackableWithoutReleaseDate() { - cgTrackable trackable = cgBase.parseTrackable(getFileContent(R.raw.tb14wfv), null, null); + cgTrackable trackable = GCParser.parseTrackable(getFileContent(R.raw.tb14wfv), null, null); assertNotNull(trackable); assertEquals("The Brickster", trackable.getName()); assertEquals("Adrian C", trackable.getOwner()); @@ -66,11 +67,11 @@ public class TrackablesTest extends AbstractResourceInstrumentationTestCase { } private cgTrackable getTB2R124() { - return cgBase.parseTrackable(BaseUtils.replaceWhitespace(getFileContent(R.raw.trackable_tb2r124)), null, null); + return GCParser.parseTrackable(BaseUtils.replaceWhitespace(getFileContent(R.raw.trackable_tb2r124)), null, null); } private cgTrackable getTBXATG() { - return cgBase.parseTrackable(BaseUtils.replaceWhitespace(getFileContent(R.raw.trackable_tbxatg)), null, null); + return GCParser.parseTrackable(BaseUtils.replaceWhitespace(getFileContent(R.raw.trackable_tbxatg)), null, null); } } diff --git a/tests/src/cgeo/geocaching/cgDataTest.java b/tests/src/cgeo/geocaching/cgDataTest.java index 0625585..a1c6b1b 100644 --- a/tests/src/cgeo/geocaching/cgDataTest.java +++ b/tests/src/cgeo/geocaching/cgDataTest.java @@ -29,9 +29,10 @@ public class cgDataTest extends ApplicationTestCase<cgeoapplication> { int listId2 = StoredList.STANDARD_LIST_ID; // create caches - final cgCache cache1 = cgBaseTest.createCache(0); - assertNotNull(cache1); - final cgCache cache2 = cgBaseTest.createCache(1); + final cgCache cache1 = new cgCache(); + cache1.setGeocode("Cache 1"); + final cgCache cache2 = new cgCache(); + cache2.setGeocode("Cache 2"); assertNotNull(cache2); try { diff --git a/tests/src/cgeo/geocaching/cgeoApplicationTest.java b/tests/src/cgeo/geocaching/cgeoApplicationTest.java index 4f952fd..4a1fcb0 100644 --- a/tests/src/cgeo/geocaching/cgeoApplicationTest.java +++ b/tests/src/cgeo/geocaching/cgeoApplicationTest.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.gc.GCBase; +import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; @@ -16,6 +17,7 @@ import cgeo.geocaching.test.mock.GC2JVEH; import cgeo.geocaching.test.mock.MockedCache; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; +import cgeo.test.Compare; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -44,7 +46,6 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { // init environment createApplication(); - cgBase.initialize(getApplication()); } /** @@ -64,7 +65,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { */ @MediumTest public static void testSearchTrackableNotExisting() { - cgTrackable tb = cgBase.searchTrackable("123456", null, null); + cgTrackable tb = GCParser.searchTrackable("123456", null, null); assertNotNull(tb); } @@ -73,7 +74,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { */ @MediumTest public static void testSearchTrackable() { - cgTrackable tb = cgBase.searchTrackable("TB2J1VZ", null, null); + cgTrackable tb = GCParser.searchTrackable("TB2J1VZ", null, null); // fix data assertEquals("aefffb86-099f-444f-b132-605436163aa8", tb.getGuid()); assertEquals("TB2J1VZ", tb.getGeocode()); @@ -100,7 +101,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { */ @MediumTest public static cgCache testSearchByGeocode(final String geocode) { - final SearchResult search = cgBase.searchByGeocode(geocode, null, 0, true, null); + final SearchResult search = cgCache.searchByGeocode(geocode, null, 0, true, null); assertNotNull(search); if (Settings.isPremiumMember() || search.getError() == null) { assertEquals(1, search.getGeocodes().size()); @@ -116,7 +117,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { */ @MediumTest public static void testSearchByGeocodeNotExisting() { - final SearchResult search = cgBase.searchByGeocode("GC123456", null, 0, true, null); + final SearchResult search = cgCache.searchByGeocode("GC123456", null, 0, true, null); assertNotNull(search); assertEquals(StatusCode.UNPUBLISHED_CACHE, search.getError()); } @@ -135,7 +136,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { deleteCacheFromDBAndLogout(cache.getGeocode()); - SearchResult search = cgBase.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); + SearchResult search = cgCache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); assertNotNull(search); assertEquals(1, search.getGeocodes().size()); assertTrue(search.getGeocodes().contains(cache.getGeocode())); @@ -148,7 +149,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { deleteCacheFromDBAndLogout(cache.getGeocode()); - search = cgBase.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); + search = cgCache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); assertNotNull(search); assertEquals(0, search.getGeocodes().size()); @@ -174,7 +175,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { deleteCacheFromDBAndLogout(cache.getGeocode()); - SearchResult search = cgBase.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); + SearchResult search = cgCache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); assertNotNull(search); assertEquals(0, search.getGeocodes().size()); @@ -191,7 +192,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { */ @MediumTest public static void testSearchByCoords() { - final SearchResult search = cgBase.searchByCoords(null, new Geopoint("N 52° 24.972 E 009° 35.647"), CacheType.MYSTERY, false); + final SearchResult search = GCParser.searchByCoords(null, new Geopoint("N 52° 24.972 E 009° 35.647"), CacheType.MYSTERY, false); assertNotNull(search); assertTrue(18 <= search.getGeocodes().size()); assertTrue(search.getGeocodes().contains("GC1RMM2")); @@ -202,7 +203,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { */ @MediumTest public static void testSearchByOwner() { - final SearchResult search = cgBase.searchByOwner(null, "blafoo", CacheType.MYSTERY, false); + final SearchResult search = GCParser.searchByOwner(null, "blafoo", CacheType.MYSTERY, false); assertNotNull(search); assertEquals(3, search.getGeocodes().size()); assertTrue(search.getGeocodes().contains("GC36RT6")); @@ -213,7 +214,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { */ @MediumTest public static void testSearchByUsername() { - final SearchResult search = cgBase.searchByUsername(null, "blafoo", CacheType.WEBCAM, false); + final SearchResult search = GCParser.searchByUsername(null, "blafoo", CacheType.WEBCAM, false); assertNotNull(search); assertEquals(3, search.getTotal()); assertTrue(search.getGeocodes().contains("GCP0A9")); @@ -325,7 +326,7 @@ public class cgeoApplicationTest extends ApplicationTestCase<cgeoapplication> { mockedCache.setMockedDataUser(Settings.getUsername()); cgCache parsedCache = cgeoApplicationTest.testSearchByGeocode(mockedCache.getGeocode()); if (null != parsedCache) { - cgBaseTest.testCompareCaches(mockedCache, parsedCache, true); + Compare.assertCompareCaches(mockedCache, parsedCache, true); } } } diff --git a/tests/src/cgeo/geocaching/connector/gc/GCBaseTest.java b/tests/src/cgeo/geocaching/connector/gc/GCBaseTest.java index e6a2474..88873a1 100644 --- a/tests/src/cgeo/geocaching/connector/gc/GCBaseTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/GCBaseTest.java @@ -1,11 +1,11 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.cgBaseTest; import cgeo.geocaching.cgCache; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.test.mock.GC2CJPF; import cgeo.geocaching.test.mock.MockedCache; +import cgeo.test.Compare; import java.util.HashSet; import java.util.Set; @@ -37,7 +37,7 @@ public class GCBaseTest extends TestCase { SearchResult result = GCBase.searchByGeocodes(geocodes); cgCache parsedCache = result.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY); - cgBaseTest.testCompareCaches(mockedCache, parsedCache, false); + Compare.assertCompareCaches(mockedCache, parsedCache, false); } } diff --git a/tests/src/cgeo/geocaching/cgBaseTest.java b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java index 1f80ac6..54f69ce 100644 --- a/tests/src/cgeo/geocaching/cgBaseTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java @@ -1,16 +1,18 @@ -package cgeo.geocaching; +package cgeo.geocaching.connector.gc; -import cgeo.geocaching.connector.gc.GCConstants; +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; import cgeo.geocaching.test.R; import cgeo.geocaching.test.RegExPerformanceTest; import cgeo.geocaching.test.mock.MockedCache; -import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.CancellableHandler; +import cgeo.test.Compare; import org.apache.commons.lang3.StringUtils; @@ -18,72 +20,34 @@ import android.test.suitebuilder.annotation.MediumTest; import java.util.ArrayList; -public class cgBaseTest extends AbstractResourceInstrumentationTestCase { - - public static void testRegEx() { - String page = MockedCache.readCachePage("GC2CJPF"); - assertEquals("blafoo", BaseUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); - assertTrue(page.contains("id=\"ctl00_hlRenew\"") || "Premium Member".equals(BaseUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, "???"))); - int cachesFound = 0; - try { - cachesFound = Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", "")); - } catch (NumberFormatException e) { - fail(); - } - assertTrue(cachesFound >= 491); - } - - public static void testReplaceWhitespaces() { - assertEquals("foo bar baz ", BaseUtils.replaceWhitespace(" foo\n\tbar \r baz ")); - } - - public static void testElevation() { - assertEquals(125.663703918457, (new Geopoint(48.0, 2.0)).getElevation(), 0.1); +public class GCParserTest extends AbstractResourceInstrumentationTestCase { + public void testUnpublishedCache() { + final String page = getFileContent(R.raw.cache_unpublished); + SearchResult result = GCParser.parseCacheFromText(page, null); + assertNotNull(result); + assertTrue(result.isEmpty()); + assertEquals(StatusCode.UNPUBLISHED_CACHE, result.getError()); } - public static void testCompareCaches(ICache expected, cgCache actual, boolean all) { - assertEquals(expected.getGeocode(), actual.getGeocode()); - assertTrue(expected.getType() == actual.getType()); - assertEquals(expected.getOwner(), actual.getOwner()); - assertEquals(expected.getDifficulty(), actual.getDifficulty()); - assertEquals(expected.getTerrain(), actual.getTerrain()); - assertEquals(expected.isDisabled(), actual.isDisabled()); - assertEquals(expected.isArchived(), actual.isArchived()); - assertEquals(expected.getSize(), actual.getSize()); - assertEquals(expected.getName(), actual.getName()); - assertEquals(expected.getGuid(), actual.getGuid()); - assertTrue(expected.getFavoritePoints() <= actual.getFavoritePoints()); - assertEquals(expected.getHiddenDate().toString(), actual.getHiddenDate().toString()); - assertEquals(expected.isPremiumMembersOnly(), actual.isPremiumMembersOnly()); - - if (all) { - assertEquals(expected.getCoords(), actual.getCoords()); - assertTrue(actual.isReliableLatLon()); - assertEquals(expected.isOwn(), actual.isOwn()); - assertEquals(expected.getOwnerReal(), actual.getOwnerReal()); - assertEquals(expected.getHint(), actual.getHint()); - assertTrue(actual.getDescription().startsWith(expected.getDescription())); - assertEquals(expected.getShortDescription(), actual.getShortDescription()); - assertEquals(expected.getCacheId(), actual.getCacheId()); - assertEquals(expected.getLocation(), actual.getLocation()); - assertEquals(expected.getPersonalNote(), actual.getPersonalNote()); - assertEquals(expected.isFound(), actual.isFound()); - assertEquals(expected.isFavorite(), actual.isFavorite()); - assertEquals(expected.isWatchlist(), actual.isWatchlist()); + private static cgCache createCache(int index) { + final MockedCache mockedCache = RegExPerformanceTest.MOCKED_CACHES[index]; + // to get the same results we have to use the date format used when the mocked data was created + String oldCustomDate = Settings.getGcCustomDate(); - for (String attribute : expected.getAttributes()) { - assertTrue(actual.getAttributes().contains(attribute)); - } - for (LogType logType : expected.getLogCounts().keySet()) { - assertTrue(actual.getLogCounts().get(logType) >= expected.getLogCounts().get(logType)); - } + SearchResult searchResult; + try { + Settings.setGcCustomDate(MockedCache.getDateFormat()); + searchResult = GCParser.parseCacheFromText(mockedCache.getData(), null); + } finally { + Settings.setGcCustomDate(oldCustomDate); + } - // the inventory can differ to often, therefore we don't compare them + assertNotNull(searchResult); + assertEquals(1, searchResult.getCount()); - int actualSpoilersSize = null != actual.getSpoilers() ? actual.getSpoilers().size() : 0; - int expectedSpoilersSize = null != expected.getSpoilers() ? expected.getSpoilers().size() : 0; - assertEquals(expectedSpoilersSize, actualSpoilersSize); - } + final cgCache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + assertNotNull(cache); + return cache; } /** @@ -97,10 +61,10 @@ public class cgBaseTest extends AbstractResourceInstrumentationTestCase { for (MockedCache mockedCache : RegExPerformanceTest.MOCKED_CACHES) { // to get the same results we have to use the date format used when the mocked data was created Settings.setGcCustomDate(MockedCache.getDateFormat()); - SearchResult searchResult = cgBase.parseCacheFromText(mockedCache.getData(), null); + SearchResult searchResult = GCParser.parseCacheFromText(mockedCache.getData(), null); cgCache parsedCache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); assertTrue(StringUtils.isNotBlank(mockedCache.getMockedDataUser())); - cgBaseTest.testCompareCaches(mockedCache, parsedCache, true); + Compare.assertCompareCaches(mockedCache, parsedCache, true); } } finally { Settings.setGcCustomDate(gcCustomDate); @@ -108,7 +72,7 @@ public class cgBaseTest extends AbstractResourceInstrumentationTestCase { } public static void testWaypointsFromNote() { - final cgCache cache = cgBaseTest.createCache(0); + final cgCache cache = createCache(0); final Geopoint[] empty = new Geopoint[] {}; final Geopoint[] one = new Geopoint[] { new Geopoint("N51 21.523", "E7 2.680") }; @@ -154,32 +118,4 @@ public class cgBaseTest extends AbstractResourceInstrumentationTestCase { } } - public static cgCache createCache(int index) { - final MockedCache mockedCache = RegExPerformanceTest.MOCKED_CACHES[index]; - // to get the same results we have to use the date format used when the mocked data was created - String oldCustomDate = Settings.getGcCustomDate(); - - SearchResult searchResult; - try { - Settings.setGcCustomDate(MockedCache.getDateFormat()); - searchResult = cgBase.parseCacheFromText(mockedCache.getData(), null); - } finally { - Settings.setGcCustomDate(oldCustomDate); - } - - assertNotNull(searchResult); - assertEquals(1, searchResult.getCount()); - - final cgCache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); - assertNotNull(cache); - return cache; - } - - public void testUnpublishedCache() { - final String page = getFileContent(R.raw.cache_unpublished); - SearchResult result = cgBase.parseCacheFromText(page, null); - assertNotNull(result); - assertTrue(result.isEmpty()); - assertEquals(StatusCode.UNPUBLISHED_CACHE, result.getError()); - } -}
\ No newline at end of file +} diff --git a/tests/src/cgeo/geocaching/files/GPXParserTest.java b/tests/src/cgeo/geocaching/files/GPXParserTest.java index 0b7f396..634c551 100644 --- a/tests/src/cgeo/geocaching/files/GPXParserTest.java +++ b/tests/src/cgeo/geocaching/files/GPXParserTest.java @@ -1,7 +1,7 @@ package cgeo.geocaching.files; import cgeo.geocaching.cgCache; -import cgeo.geocaching.cgLog; +import cgeo.geocaching.LogEntry; import cgeo.geocaching.cgWaypoint; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; @@ -129,7 +129,7 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { assertEquals("Station3: Der zerbrochene Stein zählt doppelt.\nFinal: Oben neben dem Tor", cache.getHint()); // logs assertEquals(6, cache.getLogs().size()); - final cgLog log = cache.getLogs().get(5); + final LogEntry log = cache.getLogs().get(5); assertEquals("Geoteufel", log.author); assertEquals(parseTime("2011-09-11T07:00:00Z"), log.date); assertEquals(-1, log.found); diff --git a/tests/src/cgeo/geocaching/filter/AbstractFilterTestCase.java b/tests/src/cgeo/geocaching/filter/AbstractFilterTestCase.java index d2aad26..f16d326 100644 --- a/tests/src/cgeo/geocaching/filter/AbstractFilterTestCase.java +++ b/tests/src/cgeo/geocaching/filter/AbstractFilterTestCase.java @@ -1,6 +1,5 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.cgBase; import cgeo.geocaching.cgeoapplication; import android.test.ApplicationTestCase; @@ -17,6 +16,5 @@ public abstract class AbstractFilterTestCase extends ApplicationTestCase<cgeoapp // init environment createApplication(); - cgBase.initialize(getApplication()); } } diff --git a/tests/src/cgeo/geocaching/geopoint/GeopointTest.java b/tests/src/cgeo/geocaching/geopoint/GeopointTest.java index 8bb0956..7990489 100644 --- a/tests/src/cgeo/geocaching/geopoint/GeopointTest.java +++ b/tests/src/cgeo/geocaching/geopoint/GeopointTest.java @@ -246,4 +246,8 @@ public class GeopointTest extends AndroidTestCase { Assert.assertEquals(lonSecFrac, dms.lonSecFrac); } + public static void testElevation() { + assertEquals(125.663703918457, (new Geopoint(48.0, 2.0)).getElevation(), 0.1); + } + } diff --git a/tests/src/cgeo/geocaching/utils/BaseUtilsTest.java b/tests/src/cgeo/geocaching/utils/BaseUtilsTest.java new file mode 100644 index 0000000..e174d1f --- /dev/null +++ b/tests/src/cgeo/geocaching/utils/BaseUtilsTest.java @@ -0,0 +1,26 @@ +package cgeo.geocaching.utils; + +import cgeo.geocaching.connector.gc.GCConstants; +import cgeo.geocaching.test.mock.MockedCache; + +import android.test.AndroidTestCase; + +public class BaseUtilsTest extends AndroidTestCase { + public static void testRegEx() { + String page = MockedCache.readCachePage("GC2CJPF"); + assertEquals("blafoo", BaseUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); + assertTrue(page.contains("id=\"ctl00_hlRenew\"") || "Premium Member".equals(BaseUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, "???"))); + int cachesFound = 0; + try { + cachesFound = Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", "")); + } catch (NumberFormatException e) { + fail(); + } + assertTrue(cachesFound >= 491); + } + + public static void testReplaceWhitespaces() { + assertEquals("foo bar baz ", BaseUtils.replaceWhitespace(" foo\n\tbar \r baz ")); + } + +} diff --git a/tests/src/cgeo/test/Compare.java b/tests/src/cgeo/test/Compare.java new file mode 100644 index 0000000..432f4e4 --- /dev/null +++ b/tests/src/cgeo/test/Compare.java @@ -0,0 +1,57 @@ +package cgeo.test; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import cgeo.geocaching.ICache; +import cgeo.geocaching.cgCache; +import cgeo.geocaching.enumerations.LogType; + +public abstract class Compare { + + public static void assertCompareCaches(ICache expected, cgCache actual, boolean all) { + assertEquals(expected.getGeocode(), actual.getGeocode()); + assertTrue(expected.getType() == actual.getType()); + assertEquals(expected.getOwner(), actual.getOwner()); + assertEquals(expected.getDifficulty(), actual.getDifficulty()); + assertEquals(expected.getTerrain(), actual.getTerrain()); + assertEquals(expected.isDisabled(), actual.isDisabled()); + assertEquals(expected.isArchived(), actual.isArchived()); + assertEquals(expected.getSize(), actual.getSize()); + assertEquals(expected.getName(), actual.getName()); + assertEquals(expected.getGuid(), actual.getGuid()); + assertTrue(expected.getFavoritePoints() <= actual.getFavoritePoints()); + assertEquals(expected.getHiddenDate().toString(), actual.getHiddenDate().toString()); + assertEquals(expected.isPremiumMembersOnly(), actual.isPremiumMembersOnly()); + + if (all) { + assertEquals(expected.getCoords(), actual.getCoords()); + assertTrue(actual.isReliableLatLon()); + assertEquals(expected.isOwn(), actual.isOwn()); + assertEquals(expected.getOwnerReal(), actual.getOwnerReal()); + assertEquals(expected.getHint(), actual.getHint()); + assertTrue(actual.getDescription().startsWith(expected.getDescription())); + assertEquals(expected.getShortDescription(), actual.getShortDescription()); + assertEquals(expected.getCacheId(), actual.getCacheId()); + assertEquals(expected.getLocation(), actual.getLocation()); + assertEquals(expected.getPersonalNote(), actual.getPersonalNote()); + assertEquals(expected.isFound(), actual.isFound()); + assertEquals(expected.isFavorite(), actual.isFavorite()); + assertEquals(expected.isWatchlist(), actual.isWatchlist()); + + for (String attribute : expected.getAttributes()) { + assertTrue(actual.getAttributes().contains(attribute)); + } + for (LogType logType : expected.getLogCounts().keySet()) { + assertTrue(actual.getLogCounts().get(logType) >= expected.getLogCounts().get(logType)); + } + + // the inventory can differ to often, therefore we don't compare them + + int actualSpoilersSize = null != actual.getSpoilers() ? actual.getSpoilers().size() : 0; + int expectedSpoilersSize = null != expected.getSpoilers() ? expected.getSpoilers().size() : 0; + assertEquals(expectedSpoilersSize, actualSpoilersSize); + } + } + +} |
