diff options
Diffstat (limited to 'main/src')
22 files changed, 337 insertions, 202 deletions
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 4307886..73675de 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -34,6 +34,7 @@ import cgeo.geocaching.utils.GeoDirHandler; import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.ImageHelper; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import cgeo.geocaching.utils.TranslationUtils; import cgeo.geocaching.utils.UnknownTagsHandler; @@ -102,7 +103,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -1139,8 +1139,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc details.addTerrain(cache); details.addRating(cache); - // favourite count - details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×"); + // favorite count + if (cache.getFavoritePoints() > 0) { + details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×"); + } // own rating if (cache.getMyVote() > 0) { @@ -1216,21 +1218,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // favorite points Button buttonFavPointAdd = (Button) view.findViewById(R.id.add_to_favpoint); Button buttonFavPointRemove = (Button) view.findViewById(R.id.remove_from_favpoint); - buttonFavPointAdd.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - GCConnector.addToFavorites(cache); - updateFavPointBox(); - } - }); - buttonFavPointRemove.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - GCConnector.removeFromFavorites(cache); - updateFavPointBox(); - } - }); - + buttonFavPointAdd.setOnClickListener(new FavoriteAddClickListener()); + buttonFavPointRemove.setOnClickListener(new FavoriteRemoveClickListener()); updateFavPointBox(); // data license @@ -1465,6 +1454,70 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } } + /** Thread to add this cache to the favourite list of the user */ + private class FavoriteAddThread extends Thread { + private final Handler handler; + + public FavoriteAddThread(Handler handler) { + this.handler = handler; + } + + @Override + public void run() { + handler.sendEmptyMessage(GCConnector.addToFavorites(cache) ? 1 : -1); + } + } + + /** Thread to remove this cache to the favourite list of the user */ + private class FavoriteRemoveThread extends Thread { + private final Handler handler; + + public FavoriteRemoveThread(Handler handler) { + this.handler = handler; + } + + @Override + public void run() { + handler.sendEmptyMessage(GCConnector.removeFromFavorites(cache) ? 1 : -1); + } + } + + private class FavoriteUpdateHandler extends Handler { + @Override + public void handleMessage(Message msg) { + progress.dismiss(); + if (msg.what == -1) { + showToast(res.getString(R.string.err_favorite_failed)); + } else { + updateFavPointBox(); + } + } + } + + /** + * Listener for "add to favourites" button + */ + private class FavoriteAddClickListener extends AbstractWatchlistClickListener { + @Override + public void onClick(View arg0) { + doExecute(R.string.cache_dialog_favourite_add_title, + R.string.cache_dialog_favourite_add_message, + new FavoriteAddThread(new FavoriteUpdateHandler())); + } + } + + /** + * Listener for "remove from favourites" button + */ + private class FavoriteRemoveClickListener extends AbstractWatchlistClickListener { + @Override + public void onClick(View arg0) { + doExecute(R.string.cache_dialog_favourite_remove_title, + R.string.cache_dialog_favourite_remove_message, + new FavoriteRemoveThread(new FavoriteUpdateHandler())); + } + } + /** * shows/hides buttons, sets text in watchlist box */ @@ -1873,7 +1926,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc backcolor = color.darker_gray; } else { - Matcher matcher = DARK_COLOR_PATTERN.matcher(text); + MatcherWrapper matcher = new MatcherWrapper(DARK_COLOR_PATTERN, text); if (matcher.find()) { backcolor = color.darker_gray; } diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java index b625bb5..1cb3de3 100644 --- a/main/src/cgeo/geocaching/LogEntry.java +++ b/main/src/cgeo/geocaching/LogEntry.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -10,7 +11,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.List; -import java.util.regex.Matcher; import java.util.regex.Pattern; public final class LogEntry { @@ -107,7 +107,7 @@ public final class LogEntry { */ public String getDisplayText() { if (Settings.getPlainLogs()) { - Matcher matcher = PATTERN_REMOVE_COLORS.matcher(log); + MatcherWrapper matcher = new MatcherWrapper(PATTERN_REMOVE_COLORS, log); return matcher.replaceAll(""); } return log; diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java index 5898bf7..96aab88 100644 --- a/main/src/cgeo/geocaching/Settings.java +++ b/main/src/cgeo/geocaching/Settings.java @@ -1382,8 +1382,9 @@ public final class Settings { } public static String getPreferencesName() { - // there is currently no Android API to get the file name of the shared preferences - return cgeoapplication.getInstance().getPackageName() + "_preferences"; + // There is currently no Android API to get the file name of the shared preferences. Let's hardcode + // it without needing a cgeoapplication instance. + return "cgeo.geocaching_preferences"; } public static boolean getPlainLogs() { diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java index b486142..8f867b5 100644 --- a/main/src/cgeo/geocaching/cgCache.java +++ b/main/src/cgeo/geocaching/cgCache.java @@ -28,6 +28,7 @@ import cgeo.geocaching.utils.LazyInitializedList; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -48,7 +49,6 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -274,6 +274,8 @@ public class cgCache implements ICache, IWaypoint { if (StringUtils.isBlank(description)) { description = other.description; } + // FIXME: this makes no sense to favor this over the other. 0 should not be a special case here as it is + // in the range of acceptable values. This is probably the case at other places (rating, votes, etc.) too. if (favoritePoints == 0) { favoritePoints = other.favoritePoints; } @@ -760,7 +762,7 @@ public class cgCache implements ICache, IWaypoint { @Override public String getNameForSorting() { if (null == nameForSorting) { - final Matcher matcher = NUMBER_PATTERN.matcher(name); + final MatcherWrapper matcher = new MatcherWrapper(NUMBER_PATTERN, name); if (matcher.find()) { nameForSorting = name.replace(matcher.group(), StringUtils.leftPad(matcher.group(), 6, '0')); } @@ -1318,7 +1320,7 @@ public class cgCache implements ICache, IWaypoint { final Pattern coordPattern = Pattern.compile("\\b[nNsS]{1}\\s*\\d"); // begin of coordinates int count = 1; String note = getPersonalNote(); - Matcher matcher = coordPattern.matcher(note); + MatcherWrapper matcher = new MatcherWrapper(coordPattern, note); while (matcher.find()) { try { final Geopoint point = new Geopoint(note.substring(matcher.start())); @@ -1335,7 +1337,7 @@ public class cgCache implements ICache, IWaypoint { } note = note.substring(matcher.start() + 1); - matcher = coordPattern.matcher(note); + matcher = new MatcherWrapper(coordPattern, note); } } catch (Exception e) { Log.e("cgCache.parseWaypointsFromNote: " + e.toString()); @@ -1577,7 +1579,7 @@ public class cgCache implements ICache, IWaypoint { } // 12:34 final Pattern time = Pattern.compile("\\b(\\d{1,2})\\:(\\d\\d)\\b"); - final Matcher matcher = time.matcher(getDescription()); + final MatcherWrapper matcher = new MatcherWrapper(time, getDescription()); while (matcher.find()) { try { final int hours = Integer.valueOf(matcher.group(1)); @@ -1593,7 +1595,7 @@ public class cgCache implements ICache, IWaypoint { final String hourLocalized = cgeoapplication.getInstance().getString(R.string.cache_time_full_hours); if (StringUtils.isNotBlank(hourLocalized)) { final Pattern fullHours = Pattern.compile("\\b(\\d{1,2})\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE); - final Matcher matcherHours = fullHours.matcher(getDescription()); + final MatcherWrapper matcherHours = new MatcherWrapper(fullHours, getDescription()); if (matcherHours.find()) { try { final int hours = Integer.valueOf(matcherHours.group(1)); diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index 78611b8..e8865c7 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -372,6 +372,8 @@ public class cgData { private static class DbHelper extends SQLiteOpenHelper { + private static boolean firstRun = true; + DbHelper(Context context) { super(context, databasePath().getPath(), null, dbVersion); } @@ -665,6 +667,29 @@ public class cgData { Log.i("Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": completed"); } + @Override + public void onOpen(final SQLiteDatabase db) { + if (firstRun) { + sanityChecks(db); + firstRun = false; + } + } + + /** + * Execute sanity checks that should be performed once per application after the database has been + * opened. + * + * @param db the database to perform sanity checks against + */ + private static void sanityChecks(final SQLiteDatabase db) { + // Check that the history of searches is well formed as some dates seem to be missing according + // to NPE traces. + final int staleHistorySearches = db.delete(dbTableSearchDestionationHistory, "date is null", null); + if (staleHistorySearches > 0) { + Log.w(String.format("cgData.dbHelper.onOpen: removed %d bad search history entries", staleHistorySearches)); + } + } + /** * Method to remove static map files with double underscore due to issue#1670 * introduced with release on 2012-05-24. diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 1210dd4..e4fcc2b 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -131,11 +131,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity @Override public void updateGeoData(final IGeoData geo) { - if (adapter == null) { - return; - } - - if (geo.getCoords() != null) { + if (geo.getCoords() != null) { adapter.setActualCoordinates(geo.getCoords()); } if (!Settings.isUseCompass() || geo.getSpeed() > 5) { // use GPS when speed is higher than 18 km/h @@ -145,7 +141,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity @Override public void updateDirection(final float direction) { - if (adapter == null || !Settings.isLiveList()) { + if (!Settings.isLiveList()) { return; } @@ -226,9 +222,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity Log.e("cgeocaches.loadCachesHandler.2: " + e2.toString()); } - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); } private Handler loadCachesHandler = new LoadCachesHandler(this); @@ -254,12 +248,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity @Override public void handleMessage(Message msg) { try { - if (search != null) { - replaceCacheListFromSearch(); - if (adapter != null) { - adapter.reFilter(); - } - } + replaceCacheListFromSearch(); setAdapter(); updateTitle(); @@ -286,22 +275,30 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity hideLoading(); showProgress(false); - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); } }; - private Set<cgCache> cachesFromSearchResult; /** - * Loads the caches and fills the cachelist + * Loads the caches and fills the cachelist according to {@link #search} content. + * + * If {@link #search} is <code>null</code>, this does nothing. */ private void replaceCacheListFromSearch() { - if (search!=null) { - cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); + if (search != null) { + final Set<cgCache> cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); + runOnUiThread(new Runnable() { + @Override + public void run() { + cacheList.clear(); + cacheList.addAll((Set<cgCache>) cachesFromSearchResult); + adapter.reFilter(); + updateTitle(); + showFooterMoreCaches(); + } + }); } - refreshCacheListHandler.sendEmptyMessage(0); } protected void updateTitle() { @@ -329,9 +326,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity if (msg.what > -1) { cacheList.get(msg.what).setStatusChecked(false); - if (adapter != null) { - adapter.notifyDataSetChanged(); - } + adapter.notifyDataSetChanged(); int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000); int minutesRemaining = ((detailTotal - detailProgress) * secondsElapsed / ((detailProgress > 0) ? detailProgress : 1) / 60); @@ -375,9 +370,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity public void handleMessage(Message msg) { setAdapter(); - if (adapter != null) { - adapter.notifyDataSetChanged(); - } + adapter.notifyDataSetChanged(); if (msg.what == 0) { //no caches progress.setMessage(res.getString(R.string.web_import_waiting)); @@ -399,9 +392,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity threadWeb.kill(); } } else { - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); replaceCacheListFromSearch(); @@ -414,9 +405,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity @Override public void handleMessage(Message msg) { if (msg.what != MSG_CANCEL) { - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); refreshCurrentList(); @@ -435,9 +424,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity if (msg.what > -1) { progress.setProgress(detailProgress); } else { - if (adapter != null) { - adapter.setSelectMode(false); - } + adapter.setSelectMode(false); // reload history list (new LoadByHistoryThread()).start(); @@ -652,10 +639,8 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity startGeoAndDir(); - if (adapter != null) { - adapter.setSelectMode(false); - setAdapterCurrentCoordinates(true); - } + adapter.setSelectMode(false); + setAdapterCurrentCoordinates(true); if (loadCachesHandler != null && search != null) { replaceCacheListFromSearch(); @@ -683,9 +668,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity @Override public void onDestroy() { - if (adapter != null) { - adapter = null; - } + adapter = null; super.onDestroy(); } @@ -756,7 +739,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity super.onPrepareOptionsMenu(menu); try { - if (adapter != null && adapter.isSelectMode()) { + if (adapter.isSelectMode()) { menu.findItem(MENU_SWITCH_SELECT_MODE).setTitle(res.getString(R.string.caches_select_mode_exit)) .setIcon(R.drawable.ic_menu_clear_playlist); menu.findItem(MENU_INVERT_SELECTION).setVisible(true); @@ -854,9 +837,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity int itemId = item.getItemId(); switch (itemId) { case MENU_SWITCH_SELECT_MODE: - if (adapter != null) { - adapter.switchSelectMode(); - } + adapter.switchSelectMode(); invalidateOptionsMenuCompatible(); return true; case MENU_REFRESH_STORED: @@ -887,9 +868,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity renameList(); return false; case MENU_INVERT_SELECTION: - if (adapter != null) { - adapter.invertSelection(); - } + adapter.invertSelection(); invalidateOptionsMenuCompatible(); return false; case MENU_SWITCH_LIST: @@ -957,28 +936,20 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } else { // clear filter - if (adapter != null) { - setFilter(null); - } + setFilter(null); } } }); } private void setComparator(final CacheComparator comparator) { - if (adapter != null) { - adapter.setComparator(comparator); - } + adapter.setComparator(comparator); } @Override public void onCreateContextMenu(final ContextMenu menu, final View view, final ContextMenu.ContextMenuInfo info) { super.onCreateContextMenu(menu, view, info); - if (adapter == null) { - return; - } - AdapterContextMenuInfo adapterInfo = null; try { adapterInfo = (AdapterContextMenuInfo) info; @@ -1121,24 +1092,19 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } private boolean setFilter(IFilter filter) { - if (adapter != null) { - adapter.setFilter(filter); - prepareFilterBar(); - updateTitle(); - invalidateOptionsMenuCompatible(); - return true; - } - return false; + adapter.setFilter(filter); + prepareFilterBar(); + updateTitle(); + invalidateOptionsMenuCompatible(); + return true; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { - if (adapter != null) { - if (adapter.isSelectMode()) { - adapter.setSelectMode(false); - return true; - } + if (adapter.isSelectMode()) { + adapter.setSelectMode(false); + return true; } } return super.onKeyDown(keyCode, event); @@ -1298,7 +1264,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity dialog.setCancelable(true); dialog.setTitle(res.getString(R.string.caches_drop_stored)); - if (adapter != null && adapter.getCheckedCount() > 0) { + if (adapter.getCheckedCount() > 0) { dialog.setMessage(res.getString(R.string.caches_drop_selected_ask)); } else { dialog.setMessage(res.getString(R.string.caches_drop_all_ask)); @@ -1767,22 +1733,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } - /** - * Handler to refresh the current list of caches. This list is shared with the Adapter and therefore must be updated - * in the UI-Thread - */ - - private Handler refreshCacheListHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - cacheList.clear(); - if (cachesFromSearchResult != null) { - cacheList.addAll(cachesFromSearchResult); - } - } - }; - - private void renameList() { new StoredList.UserInterface(this).promptForListRename(listId, new Runnable() { @@ -1850,13 +1800,11 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity SearchResult searchToUse = search; // apply filter settings (if there's a filter) - if (adapter != null) { - Set<String> geocodes = new HashSet<String>(); - for (cgCache cache : adapter.getFilteredList()) { - geocodes.add(cache.getGeocode()); - } - searchToUse = new SearchResult(geocodes); + Set<String> geocodes = new HashSet<String>(); + for (cgCache cache : adapter.getFilteredList()) { + geocodes.add(cache.getGeocode()); } + searchToUse = new SearchResult(geocodes); int count = searchToUse.getCount(); String mapTitle = title; diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java index a474e70..282c88c 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java @@ -57,7 +57,7 @@ public final class GCConstants { public final static Pattern PATTERN_ATTRIBUTES = Pattern.compile("<h3 class=\"WidgetHeader\">.+?Attributes</h3>[^<]*<div class=\"WidgetBody\">((?:[^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+?)[^<]*<p"); /** Two groups ! */ public final static Pattern PATTERN_ATTRIBUTESINSIDE = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+?)\""); - public final static Pattern PATTERN_SPOILER_IMAGE = Pattern.compile("<a href=\"(http://img\\.geocaching\\.com/cache/[^.]+\\.jpe?g)\"[^>]+><img[^>]+><span>([^<]+)</span></a>(?:<br />([^<]+)<br /><br />)?"); + public final static Pattern PATTERN_SPOILER_IMAGE = Pattern.compile("<a href=\"(http://img\\.geocaching\\.com/cache/[^.]+\\.(jpg|jpeg|png|gif))\"[^>]+><img[^>]+><span>([^<]+)</span></a>(?:<br />([^<]+)<br /><br />)?"); public final static Pattern PATTERN_INVENTORY = Pattern.compile("<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">\\W*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?"); public final static Pattern PATTERN_INVENTORYINSIDE = Pattern.compile("[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>"); public final static Pattern PATTERN_WATCHLIST = Pattern.compile(Pattern.quote("watchlist.aspx") + ".{1,50}" + Pattern.quote("action=rem")); diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index fd4e3fa..91b0ddd 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -31,6 +31,7 @@ import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.LazyInitializedList; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import ch.boye.httpclientandroidlib.HttpResponse; @@ -54,7 +55,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Set; -import java.util.regex.Matcher; public abstract class GCParser { private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009 @@ -128,7 +128,7 @@ public abstract class GCParser { } try { - final Matcher matcherGuidAndDisabled = GCConstants.PATTERN_SEARCH_GUIDANDDISABLED.matcher(row); + final MatcherWrapper matcherGuidAndDisabled = new MatcherWrapper(GCConstants.PATTERN_SEARCH_GUIDANDDISABLED, row); while (matcherGuidAndDisabled.find()) { if (matcherGuidAndDisabled.groupCount() > 0) { @@ -169,7 +169,7 @@ public abstract class GCParser { } // cache inventory - final Matcher matcherTbs = GCConstants.PATTERN_SEARCH_TRACKABLES.matcher(row); + final MatcherWrapper matcherTbs = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLES, row); String inventoryPre = null; while (matcherTbs.find()) { if (matcherTbs.groupCount() > 0) { @@ -183,7 +183,7 @@ public abstract class GCParser { } if (StringUtils.isNotBlank(inventoryPre)) { - final Matcher matcherTbsInside = GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE.matcher(inventoryPre); + final MatcherWrapper matcherTbsInside = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE, inventoryPre); while (matcherTbsInside.find()) { if (matcherTbsInside.groupCount() == 2 && matcherTbsInside.group(2) != null && @@ -500,7 +500,7 @@ public abstract class GCParser { try { final String attributesPre = BaseUtils.getMatch(page, GCConstants.PATTERN_ATTRIBUTES, true, null); if (null != attributesPre) { - final Matcher matcherAttributesInside = GCConstants.PATTERN_ATTRIBUTESINSIDE.matcher(attributesPre); + final MatcherWrapper matcherAttributesInside = new MatcherWrapper(GCConstants.PATTERN_ATTRIBUTESINSIDE, attributesPre); final ArrayList<String> attributes = new ArrayList<String>(); while (matcherAttributesInside.find()) { @@ -534,7 +534,7 @@ public abstract class GCParser { } CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); - final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILER_IMAGE.matcher(page); + final MatcherWrapper matcherSpoilersInside = new MatcherWrapper(GCConstants.PATTERN_SPOILER_IMAGE, page); while (matcherSpoilersInside.find()) { // the original spoiler URL (include .../display/... contains a low-resolution image @@ -542,12 +542,12 @@ public abstract class GCParser { String url = matcherSpoilersInside.group(1).replace("/display", ""); String title = null; - if (matcherSpoilersInside.group(2) != null) { - title = matcherSpoilersInside.group(2); + if (matcherSpoilersInside.group(3) != null) { + title = matcherSpoilersInside.group(3); } String description = null; - if (matcherSpoilersInside.group(3) != null) { - description = matcherSpoilersInside.group(3); + if (matcherSpoilersInside.group(4) != null) { + description = matcherSpoilersInside.group(4); } cache.addSpoiler(new cgImage(url, title, description)); } @@ -560,7 +560,7 @@ public abstract class GCParser { try { cache.setInventoryItems(0); - final Matcher matcherInventory = GCConstants.PATTERN_INVENTORY.matcher(page); + final MatcherWrapper matcherInventory = new MatcherWrapper(GCConstants.PATTERN_INVENTORY, page); if (matcherInventory.find()) { if (cache.getInventory() == null) { cache.setInventory(new ArrayList<cgTrackable>()); @@ -570,7 +570,7 @@ public abstract class GCParser { final String inventoryPre = matcherInventory.group(2); if (StringUtils.isNotBlank(inventoryPre)) { - final Matcher matcherInventoryInside = GCConstants.PATTERN_INVENTORYINSIDE.matcher(inventoryPre); + final MatcherWrapper matcherInventoryInside = new MatcherWrapper(GCConstants.PATTERN_INVENTORYINSIDE, inventoryPre); while (matcherInventoryInside.find()) { if (matcherInventoryInside.groupCount() > 0) { @@ -591,14 +591,12 @@ public abstract class GCParser { } // cache logs counts - try - { + try { final String countlogs = BaseUtils.getMatch(page, GCConstants.PATTERN_COUNTLOGS, true, null); if (null != countlogs) { - final Matcher matcherLog = GCConstants.PATTERN_COUNTLOG.matcher(countlogs); + final MatcherWrapper matcherLog = new MatcherWrapper(GCConstants.PATTERN_COUNTLOG, countlogs); - while (matcherLog.find()) - { + while (matcherLog.find()) { String typeStr = matcherLog.group(1); String countStr = matcherLog.group(2).replaceAll("[.,]", ""); @@ -609,8 +607,7 @@ public abstract class GCParser { } } } - } catch (Exception e) - { + } catch (Exception e) { // failed to parse logs Log.w("GCParser.parseCache: Failed to parse cache log count"); } @@ -997,7 +994,7 @@ public abstract class GCParser { // maintenance, archived needs to be confirmed - final Matcher matcher = GCConstants.PATTERN_MAINTENANCE.matcher(page); + final MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_MAINTENANCE, page); try { if (matcher.find() && matcher.groupCount() > 0) { @@ -1046,7 +1043,7 @@ public abstract class GCParser { try { - final Matcher matcherOk = GCConstants.PATTERN_OK1.matcher(page); + final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK1, page); if (matcherOk.find()) { Log.i("Log successfully posted to cache #" + cacheid); @@ -1115,7 +1112,7 @@ public abstract class GCParser { try { - final Matcher matcherOk = GCConstants.PATTERN_OK2.matcher(page); + final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK2, page); if (matcherOk.find()) { Log.i("Log successfully posted to trackable #" + trackingCode); return StatusCode.NO_ERROR; @@ -1286,7 +1283,7 @@ public abstract class GCParser { // trackable owner name try { - final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page); + final MatcherWrapper matcherOwner = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_OWNER, page); if (matcherOwner.find() && matcherOwner.groupCount() > 0) { trackable.setOwnerGuid(matcherOwner.group(1)); trackable.setOwner(matcherOwner.group(2).trim()); @@ -1301,14 +1298,14 @@ public abstract class GCParser { // trackable spotted try { - final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page); + final MatcherWrapper matcherSpottedCache = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE, 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); + final MatcherWrapper matcherSpottedUser = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER, page); if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) { trackable.setSpottedGuid(matcherSpottedUser.group(1)); trackable.setSpottedName(matcherSpottedUser.group(2).trim()); @@ -1351,7 +1348,7 @@ public abstract class GCParser { // trackable details & image try { - final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page); + final MatcherWrapper matcherDetailsImage = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE, page); if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) { final String image = StringUtils.trim(matcherDetailsImage.group(3)); final String details = StringUtils.trim(matcherDetailsImage.group(4)); @@ -1370,7 +1367,7 @@ public abstract class GCParser { // trackable logs try { - final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page); + final MatcherWrapper matcherLogs = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG, page); /* * 1. Type (image) * 2. Date @@ -1400,7 +1397,7 @@ public abstract class GCParser { // Apply the pattern for images in a trackable log entry against each full log (group(0)) final String logEntry = matcherLogs.group(0); - final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(logEntry); + final MatcherWrapper matcherLogImages = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG_IMAGES, logEntry); /* * 1. Image URL * 2. Image title @@ -1450,7 +1447,7 @@ public abstract class GCParser { String rawResponse; if (!getDataFromPage) { - final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN.matcher(page); + final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page); if (!userTokenMatcher.find()) { Log.e("GCParser.loadLogsFromDetails: unable to extract userToken"); return null; @@ -1549,7 +1546,7 @@ public abstract class GCParser { final List<LogType> types = new ArrayList<LogType>(); - final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page); + final MatcherWrapper typeBoxMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPEBOX, page); String typesText = null; if (typeBoxMatcher.find()) { if (typeBoxMatcher.groupCount() > 0) { @@ -1559,7 +1556,7 @@ public abstract class GCParser { if (typesText != null) { - final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText); + final MatcherWrapper typeMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPE2, typesText); while (typeMatcher.find()) { if (typeMatcher.groupCount() > 1) { try { @@ -1597,7 +1594,7 @@ public abstract class GCParser { final List<TrackableLog> trackableLogs = new ArrayList<TrackableLog>(); - final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page); + final MatcherWrapper trackableMatcher = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE, page); while (trackableMatcher.find()) { if (trackableMatcher.groupCount() > 0) { diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java index 494bcee..9a60f65 100644 --- a/main/src/cgeo/geocaching/connector/gc/Login.java +++ b/main/src/cgeo/geocaching/connector/gc/Login.java @@ -10,6 +10,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import ch.boye.httpclientandroidlib.HttpResponse; @@ -26,7 +27,6 @@ import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.regex.Matcher; public abstract class Login { @@ -349,7 +349,7 @@ public abstract class Login { } int count = 1; - final Matcher matcherViewstateCount = GCConstants.PATTERN_VIEWSTATEFIELDCOUNT.matcher(page); + final MatcherWrapper matcherViewstateCount = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATEFIELDCOUNT, page); if (matcherViewstateCount.find()) { try { count = Integer.parseInt(matcherViewstateCount.group(1)); @@ -361,7 +361,7 @@ public abstract class Login { String[] viewstates = new String[count]; // Get the viewstates - final Matcher matcherViewstates = GCConstants.PATTERN_VIEWSTATES.matcher(page); + final MatcherWrapper matcherViewstates = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATES, page); while (matcherViewstates.find()) { String sno = matcherViewstates.group(1); // number of viewstate int no; diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java index e34d277..5965fff 100644 --- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java +++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java @@ -1,6 +1,7 @@ package cgeo.geocaching.connector.gc; -import java.util.regex.Matcher; +import cgeo.geocaching.utils.MatcherWrapper; + import java.util.regex.Pattern; @@ -35,7 +36,7 @@ public final class UTFGridPosition { * @return */ static UTFGridPosition fromString(String key) { - final Matcher matcher = UTFGridPosition.PATTERN_JSON_KEY.matcher(key); + final MatcherWrapper matcher = new MatcherWrapper(UTFGridPosition.PATTERN_JSON_KEY, key); try { if (matcher.matches()) { final int x = Integer.parseInt(matcher.group(1)); diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java index 5918fe1..71a5146 100644 --- a/main/src/cgeo/geocaching/enumerations/LogType.java +++ b/main/src/cgeo/geocaching/enumerations/LogType.java @@ -26,9 +26,9 @@ public enum LogType { NEEDS_ARCHIVE(7, "7", "needs archived", R.string.log_needs_archived, R.drawable.mark_red), WILL_ATTEND(9, "9", "will attend", R.string.log_attend), ATTENDED(10, "10", "attended", R.string.log_attended, R.drawable.mark_green), - RETRIEVED_IT(13, "13", "retrieved it", R.string.log_retrieved, R.drawable.mark_green), - PLACED_IT(14, "14", "placed it", R.string.log_placed), - GRABBED_IT(19, "19", "grabbed it", R.string.log_grabbed, R.drawable.mark_green), + RETRIEVED_IT(13, "13", "retrieved it", R.string.log_retrieved, R.drawable.mark_green_more), + PLACED_IT(14, "14", "placed it", R.string.log_placed, R.drawable.mark_green_more), + GRABBED_IT(19, "19", "grabbed it", R.string.log_grabbed, R.drawable.mark_green_more), NEEDS_MAINTENANCE(45, "45", "needs maintenance", R.string.log_maintenance_needed, R.drawable.mark_red), OWNER_MAINTENANCE(46, "46", "owner maintenance", R.string.log_maintained, R.drawable.mark_green_more), UPDATE_COORDINATES(47, "47", "update coordinates", R.string.log_update), diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java index 2ac19bb..e2d7205 100644 --- a/main/src/cgeo/geocaching/files/GPXParser.java +++ b/main/src/cgeo/geocaching/files/GPXParser.java @@ -19,6 +19,7 @@ import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.lang3.StringUtils; import org.xml.sax.Attributes; @@ -42,7 +43,6 @@ import java.util.EnumSet; import java.util.HashSet; import java.util.Locale; import java.util.Set; -import java.util.regex.Matcher; import java.util.regex.Pattern; public abstract class GPXParser extends FileParser { @@ -209,7 +209,7 @@ public abstract class GPXParser extends FileParser { return null; } // cut out baseName - final Matcher m = BASENAME_PATTERN.matcher(stringName); + final MatcherWrapper m = new MatcherWrapper(BASENAME_PATTERN, stringName); if (!m.matches()) { return null; } @@ -235,7 +235,7 @@ public abstract class GPXParser extends FileParser { static Date parseDate(String inputUntrimmed) throws ParseException { String input = inputUntrimmed.trim(); // remove milliseconds to reduce number of needed patterns - final Matcher matcher = PATTERN_MILLISECONDS.matcher(input); + final MatcherWrapper matcher = new MatcherWrapper(PATTERN_MILLISECONDS, input); input = matcher.replaceFirst(""); if (input.contains("Z")) { return formatSimpleZ.parse(input); @@ -432,14 +432,14 @@ public abstract class GPXParser extends FileParser { @Override public void end(String url) { - final Matcher matcher = patternGuid.matcher(url); + final MatcherWrapper matcher = new MatcherWrapper(patternGuid, url); if (matcher.matches()) { final String guid = matcher.group(1); if (StringUtils.isNotBlank(guid)) { cache.setGuid(guid); } } - final Matcher matcherCode = patternUrlGeocode.matcher(url); + final MatcherWrapper matcherCode = new MatcherWrapper(patternUrlGeocode, url); if (matcherCode.matches()) { String geocode = matcherCode.group(1); cache.setGeocode(geocode); @@ -836,7 +836,7 @@ public abstract class GPXParser extends FileParser { return; } final String trimmed = input.trim(); - final Matcher matcherGeocode = patternGeocode.matcher(trimmed); + final MatcherWrapper matcherGeocode = new MatcherWrapper(patternGeocode, trimmed); if (matcherGeocode.find()) { final String geocode = matcherGeocode.group(1); // a geocode should not be part of a word diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java index 9c24d39..730e224 100644 --- a/main/src/cgeo/geocaching/files/LocParser.java +++ b/main/src/cgeo/geocaching/files/LocParser.java @@ -9,6 +9,7 @@ import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.lang3.StringUtils; @@ -22,7 +23,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.regex.Matcher; import java.util.regex.Pattern; public final class LocParser extends FileParser { @@ -148,12 +148,12 @@ public final class LocParser extends FileParser { public static cgCache parseCache(final String pointString) { final cgCache cache = new cgCache(); - final Matcher matcherGeocode = patternGeocode.matcher(pointString); + final MatcherWrapper matcherGeocode = new MatcherWrapper(patternGeocode, pointString); if (matcherGeocode.find()) { cache.setGeocode(matcherGeocode.group(1).trim()); } - final Matcher matcherName = patternName.matcher(pointString); + final MatcherWrapper matcherName = new MatcherWrapper(patternName, pointString); if (matcherName.find()) { final String name = matcherName.group(1).trim(); cache.setName(StringUtils.substringBeforeLast(name, " by ").trim()); @@ -161,24 +161,24 @@ public final class LocParser extends FileParser { cache.setName(cache.getGeocode()); } - final Matcher matcherLat = patternLat.matcher(pointString); - final Matcher matcherLon = patternLon.matcher(pointString); + final MatcherWrapper matcherLat = new MatcherWrapper(patternLat, pointString); + final MatcherWrapper matcherLon = new MatcherWrapper(patternLon, pointString); if (matcherLat.find() && matcherLon.find()) { cache.setCoords(parsePoint(matcherLat.group(1).trim(), matcherLon.group(1).trim())); } - final Matcher matcherDifficulty = patternDifficulty.matcher(pointString); + final MatcherWrapper matcherDifficulty = new MatcherWrapper(patternDifficulty, pointString); try { if (matcherDifficulty.find()) { cache.setDifficulty(Float.parseFloat(matcherDifficulty.group(1).trim())); } - final Matcher matcherTerrain = patternTerrain.matcher(pointString); + final MatcherWrapper matcherTerrain = new MatcherWrapper(patternTerrain, pointString); if (matcherTerrain.find()) { cache.setTerrain(Float.parseFloat(matcherTerrain.group(1).trim())); } - final Matcher matcherContainer = patternContainer.matcher(pointString); + final MatcherWrapper matcherContainer = new MatcherWrapper(patternContainer, pointString); if (matcherContainer.find()) { final int size = Integer.parseInt(matcherContainer.group(1).trim()); if (size >= 1 && size <= 8) { diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java index 3d87724..e98ba56 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVote.java +++ b/main/src/cgeo/geocaching/gcvote/GCVote.java @@ -6,6 +6,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -15,7 +16,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; public final class GCVote { @@ -98,7 +98,7 @@ public final class GCVote { return null; } - final Matcher matcherVoteElement = patternVoteElement.matcher(page); + final MatcherWrapper matcherVoteElement = new MatcherWrapper(patternVoteElement, page); while (matcherVoteElement.find()) { String voteData = matcherVoteElement.group(1); if (voteData == null) { @@ -107,7 +107,7 @@ public final class GCVote { String guid = null; try { - final Matcher matcherGuid = patternGuid.matcher(voteData); + final MatcherWrapper matcherGuid = new MatcherWrapper(patternGuid, voteData); if (matcherGuid.find()) { if (matcherGuid.groupCount() > 0) { guid = matcherGuid.group(1); @@ -122,7 +122,7 @@ public final class GCVote { boolean loggedIn = false; try { - final Matcher matcherLoggedIn = patternLogIn.matcher(page); + final MatcherWrapper matcherLoggedIn = new MatcherWrapper(patternLogIn, page); if (matcherLoggedIn.find()) { if (matcherLoggedIn.groupCount() > 0) { if (matcherLoggedIn.group(1).equalsIgnoreCase("true")) { @@ -136,7 +136,7 @@ public final class GCVote { float rating = 0; try { - final Matcher matcherRating = patternRating.matcher(voteData); + final MatcherWrapper matcherRating = new MatcherWrapper(patternRating, voteData); if (matcherRating.find()) { rating = Float.parseFloat(matcherRating.group(1)); } @@ -149,7 +149,7 @@ public final class GCVote { int votes = -1; try { - final Matcher matcherVotes = patternVotes.matcher(voteData); + final MatcherWrapper matcherVotes = new MatcherWrapper(patternVotes, voteData); if (matcherVotes.find()) { votes = Integer.parseInt(matcherVotes.group(1)); } @@ -163,7 +163,7 @@ public final class GCVote { float myVote = 0; if (loggedIn) { try { - final Matcher matcherVote = patternVote.matcher(voteData); + final MatcherWrapper matcherVote = new MatcherWrapper(patternVote, voteData); if (matcherVote.find()) { myVote = Float.parseFloat(matcherVote.group(1)); } diff --git a/main/src/cgeo/geocaching/geopoint/DistanceParser.java b/main/src/cgeo/geocaching/geopoint/DistanceParser.java index d8db8e4..e1692f4 100644 --- a/main/src/cgeo/geocaching/geopoint/DistanceParser.java +++ b/main/src/cgeo/geocaching/geopoint/DistanceParser.java @@ -1,9 +1,10 @@ package cgeo.geocaching.geopoint; +import cgeo.geocaching.utils.MatcherWrapper; + import org.apache.commons.lang3.StringUtils; import java.util.Locale; -import java.util.regex.Matcher; import java.util.regex.Pattern; public final class DistanceParser { @@ -22,7 +23,7 @@ public final class DistanceParser { * if the given number is invalid */ public static float parseDistance(String distanceText, final boolean metricUnit) { - final Matcher matcher = pattern.matcher(distanceText); + final MatcherWrapper matcher = new MatcherWrapper(pattern, distanceText); if (!matcher.find()) { throw new NumberFormatException(distanceText); diff --git a/main/src/cgeo/geocaching/geopoint/GeopointParser.java b/main/src/cgeo/geocaching/geopoint/GeopointParser.java index 7604b9d..97a9ec8 100644 --- a/main/src/cgeo/geocaching/geopoint/GeopointParser.java +++ b/main/src/cgeo/geocaching/geopoint/GeopointParser.java @@ -1,9 +1,10 @@ package cgeo.geocaching.geopoint; +import cgeo.geocaching.utils.MatcherWrapper; + import org.apache.commons.lang3.StringUtils; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -105,7 +106,7 @@ class GeopointParser { { final Pattern pattern = LatLon.LAT == latlon ? patternLat : patternLon; - final Matcher matcher = pattern.matcher(text); + final MatcherWrapper matcher = new MatcherWrapper(pattern, text); if (matcher.find()) { final double sign = matcher.group(1).equalsIgnoreCase("S") || matcher.group(1).equalsIgnoreCase("W") ? -1.0 : 1.0; diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java index 294eb79..dc0dbf8 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java @@ -93,7 +93,7 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { } private static boolean isMapfile024(String mapFileIn) { - return org.mapsforge.android.mapsold.MapDatabase.isValidMapFile(mapFileIn); + return mapFileIn != null && org.mapsforge.android.mapsold.MapDatabase.isValidMapFile(mapFileIn); } @Override diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index e25eec5..cab92b6 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -41,7 +41,8 @@ public class HtmlImage implements Html.ImageGetter { "besucherzaehler-homepage.de", "hitwebcounter.com", "kostenloser-counter.eu", - "trendcounter.com" + "trendcounter.com", + "hit-counter-download.com" }; final private String geocode; diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java index 96edebf..61478b5 100644 --- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java @@ -7,6 +7,7 @@ import cgeo.geocaching.network.Network; import cgeo.geocaching.network.OAuth; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.MatcherWrapper; import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity; import ch.boye.httpclientandroidlib.util.EntityUtils; @@ -24,7 +25,6 @@ import android.view.View; import android.widget.Button; import android.widget.EditText; -import java.util.regex.Matcher; import java.util.regex.Pattern; public class TwitterAuthorizationActivity extends AbstractActivity { @@ -142,11 +142,11 @@ public class TwitterAuthorizationActivity extends AbstractActivity { if (StringUtils.isNotBlank(line)) { - final Matcher paramsMatcher1 = paramsPattern1.matcher(line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final Matcher paramsMatcher2 = paramsPattern2.matcher(line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); if (paramsMatcher2.find()) { OAtokenSecret = paramsMatcher2.group(1); } @@ -189,11 +189,11 @@ public class TwitterAuthorizationActivity extends AbstractActivity { OAtoken = ""; OAtokenSecret = ""; - final Matcher paramsMatcher1 = paramsPattern1.matcher(line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final Matcher paramsMatcher2 = paramsPattern2.matcher(line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) { OAtokenSecret = paramsMatcher2.group(1); } diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java index ea2ecb5..60fb3e6 100644 --- a/main/src/cgeo/geocaching/ui/Formatter.java +++ b/main/src/cgeo/geocaching/ui/Formatter.java @@ -13,6 +13,7 @@ import org.apache.commons.lang3.StringUtils; import android.content.Context; import android.text.format.DateUtils; +import java.text.DateFormat; import java.util.ArrayList; import java.util.List; @@ -70,8 +71,8 @@ public abstract class Formatter { * @return the formatted string */ public static String formatShortDate(long date) { - return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_NUMERIC_DATE); + DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context); + return dateFormat.format(date); } /** diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java index 0df3289..aafce4f 100644 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java @@ -2,6 +2,7 @@ package cgeo.geocaching.utils; import java.util.AbstractSet; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -102,6 +103,18 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E> } /** + * Synchronized removal of all elements contained in another collection. + */ + @Override + public synchronized boolean removeAll(final Collection<?> c) { + boolean changed = false; + for (final Object o: c) { + changed |= remove(o); + } + return changed; + } + + /** * Synchronized clearing of the set * Copy of the HashSet code if clear() * diff --git a/main/src/cgeo/geocaching/utils/MatcherWrapper.java b/main/src/cgeo/geocaching/utils/MatcherWrapper.java new file mode 100644 index 0000000..c3c1663 --- /dev/null +++ b/main/src/cgeo/geocaching/utils/MatcherWrapper.java @@ -0,0 +1,91 @@ +package cgeo.geocaching.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Wrapper around the regex {@link Matcher} class. This implementation optimizes the memory usage of the matched + * Strings. + * + */ +public class MatcherWrapper { + private final Matcher matcher; + + public MatcherWrapper(Pattern pattern, String input) { + this.matcher = pattern.matcher(input); + } + + /** + * see {@link Matcher#find()} + */ + public boolean find() { + return matcher.find(); + } + + /** + * see {@link Matcher#group(int)} + */ + public String group(int index) { + return newString(matcher.group(index)); + } + + /** + * This method explicitly creates a new String instance from an already existing String. This is necessary to avoid + * huge memory leaks in our parser. If we do regular expression matching on large Strings, the returned matches are + * otherwise memory mapped substrings of the huge original String, therefore blocking the garbage collector from + * removing the huge input String. + * <p> + * Do not change this method, even if Findbugs and other tools will report a violation for that line! + * + * @param input + * @return + */ + private static String newString(String input) { + if (input == null) { + return null; + } + return new String(input); // DON'T REMOVE THE "new String" HERE! + } + + /** + * see {@link Matcher#groupCount()} + */ + public int groupCount() { + return matcher.groupCount(); + } + + /** + * see {@link Matcher#group()} + */ + public String group() { + return newString(matcher.group()); + } + + /** + * see {@link Matcher#start()} + */ + public int start() { + return matcher.start(); + } + + /** + * see {@link Matcher#replaceAll(String)} + */ + public String replaceAll(String replacement) { + return newString(matcher.replaceAll(replacement)); + } + + /** + * see {@link Matcher#matches()} + */ + public boolean matches() { + return matcher.matches(); + } + + /** + * see {@link Matcher#replaceFirst(String)} + */ + public String replaceFirst(String replacement) { + return newString(matcher.replaceFirst(replacement)); + } +} |
