package cgeo.geocaching.sorting; import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.models.Geocache; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; /** * abstract super implementation for all cache comparators * */ abstract class AbstractCacheComparator implements CacheComparator { @Override public final int compare(final Geocache cache1, final Geocache cache2) { try { final boolean canCompare1 = canCompare(cache1); final boolean canCompare2 = canCompare(cache2); if (!canCompare1) { return canCompare2 ? 1 : fallbackToGeocode(cache1, cache2); } return canCompare2 ? compareCaches(cache1, cache2) : -1; } catch (final Exception e) { Log.e("AbstractCacheComparator.compare", e); // This may violate the Comparator interface if the exception is not systematic. return fallbackToGeocode(cache1, cache2); } } private static int fallbackToGeocode(final Geocache cache1, final Geocache cache2) { final int comparePrefix = StringUtils.compareIgnoreCase(StringUtils.substring(cache1.getGeocode(), 0, 2), StringUtils.substring(cache2.getGeocode(), 0, 2)); if (comparePrefix == 0) { return (int) (GCConstants.gccodeToGCId(cache1.getGeocode()) - GCConstants.gccodeToGCId(cache2.getGeocode())); } return comparePrefix; } /** * Check necessary preconditions (like missing fields) before running the comparison itself. * Caches not filling the conditions will be placed last, sorted by Geocode. * * The default implementation returns {@code true} and can be overridden if needed in sub classes. * * @param cache * the cache to be sorted * * @return {@code true} if the cache holds the necessary data to be compared meaningfully */ protected boolean canCompare(final Geocache cache) { return true; } /** * Compares two caches. Logging and exception handling is implemented outside this method already. * <p/> * A cache is smaller than another cache if it is desirable to show it first when presented to the user. * For example, a highly rated cache must be considered smaller than a poorly rated one. * * @return an integer < 0 if cache1 is less than cache2, 0 if they are equal, and > 0 if cache1 is greater than * cache2. */ protected abstract int compareCaches(final Geocache cache1, final Geocache cache2); @Override public boolean isAutoManaged() { return false; } }