@Override public boolean onPrepareOptionsMenu(final Menu menu) { boolean smileyVisible = false; final Geocache cache = getLogContext().getCache(); if (cache != null && ConnectorFactory.getConnector(cache).equals(GCConnector.getInstance())) { smileyVisible = true; } final Trackable trackable = getLogContext().getTrackable(); if (trackable != null && ConnectorFactory.getConnector(trackable).equals(TravelBugConnector.getInstance())) { smileyVisible = true; } menu.findItem(R.id.menu_smilies).setVisible(smileyVisible); return true; }
public static void testGetConnectorString() { final IConnector connector = ConnectorFactory.getConnector("GC12345"); assertNotNull(connector); assertEquals(GCConnector.getInstance().getName(), connector.getName()); }
public static void testGetConnectorCgCache() { assertEquals(GCConnector.getInstance(), ConnectorFactory.getConnector(new GC1ZXX2())); }
public final class ConnectorFactory { @NonNull private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector(); @NonNull private static final Collection<IConnector> CONNECTORS = Collections.unmodifiableCollection( Arrays.<IConnector>asList( GCConnector.getInstance(), ECConnector.getInstance(), new OCApiLiveConnector( "opencaching.de", "www.opencaching.de", "OC", "CC BY-NC-ND, alle Logeinträge © jeweiliger Autor", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, R.string.pref_connectorOCActive, R.string.pref_ocde_tokenpublic, R.string.pref_ocde_tokensecret, ApiSupport.current), new OCCZConnector(), new OCApiLiveConnector( "opencaching.org.uk", "www.opencaching.org.uk", "OK", "CC BY-NC-SA 2.5", R.string.oc_uk_okapi_consumer_key, R.string.oc_uk_okapi_consumer_secret, R.string.pref_connectorOCUKActive, R.string.pref_ocuk_tokenpublic, R.string.pref_ocuk_tokensecret, ApiSupport.oldapi), new OCConnector("OpenCaching.ES", "www.opencachingspain.es", "OC"), new OCConnector("OpenCaching.IT", "www.opencaching.it", "OC"), new OCConnector("OpenCaching.JP", "www.opencaching.jp", "OJ"), new OCConnector("OpenCaching.NO/SE", "www.opencaching.se", "OS"), new OCApiLiveConnector( "opencaching.nl", "www.opencaching.nl", "OB", "CC BY-SA 3.0", R.string.oc_nl_okapi_consumer_key, R.string.oc_nl_okapi_consumer_secret, R.string.pref_connectorOCNLActive, R.string.pref_ocnl_tokenpublic, R.string.pref_ocnl_tokensecret, ApiSupport.current), new OCApiLiveConnector( "opencaching.pl", "www.opencaching.pl", "OP", "CC BY-SA 3.0", R.string.oc_pl_okapi_consumer_key, R.string.oc_pl_okapi_consumer_secret, R.string.pref_connectorOCPLActive, R.string.pref_ocpl_tokenpublic, R.string.pref_ocpl_tokensecret, ApiSupport.current), new OCApiLiveConnector( "opencaching.us", "www.opencaching.us", "OU", "CC BY-NC-SA 2.5", R.string.oc_us_okapi_consumer_key, R.string.oc_us_okapi_consumer_secret, R.string.pref_connectorOCUSActive, R.string.pref_ocus_tokenpublic, R.string.pref_ocus_tokensecret, ApiSupport.current), new OCApiLiveConnector( "opencaching.ro", "www.opencaching.ro", "OR", "CC BY-SA 3.0", R.string.oc_ro_okapi_consumer_key, R.string.oc_ro_okapi_consumer_secret, R.string.pref_connectorOCROActive, R.string.pref_ocro_tokenpublic, R.string.pref_ocro_tokensecret, ApiSupport.current), new GeocachingAustraliaConnector(), new GeopeitusConnector(), new TerraCachingConnector(), new WaymarkingConnector(), new GeocachingSuConnector(), UNKNOWN_CONNECTOR // the unknown connector MUST be the last one )); @NonNull public static final UnknownTrackableConnector UNKNOWN_TRACKABLE_CONNECTOR = new UnknownTrackableConnector(); @NonNull private static final Collection<TrackableConnector> TRACKABLE_CONNECTORS = Collections.unmodifiableCollection( Arrays.<TrackableConnector>asList( new GeokretyConnector(), new SwaggieConnector(), TravelBugConnector .getInstance(), // travel bugs last, as their secret codes overlap with other // connectors UNKNOWN_TRACKABLE_CONNECTOR // must be last )); @NonNull private static final Collection<ISearchByViewPort> searchByViewPortConns = getMatchingConnectors(ISearchByViewPort.class); @NonNull private static final Collection<ISearchByCenter> searchByCenterConns = getMatchingConnectors(ISearchByCenter.class); @NonNull private static final Collection<ISearchByNextPage> searchByNextPageConns = getMatchingConnectors(ISearchByNextPage.class); @NonNull private static final Collection<ISearchByKeyword> searchByKeywordConns = getMatchingConnectors(ISearchByKeyword.class); @NonNull private static final Collection<ISearchByOwner> SEARCH_BY_OWNER_CONNECTORS = getMatchingConnectors(ISearchByOwner.class); @NonNull private static final Collection<ISearchByFinder> SEARCH_BY_FINDER_CONNECTORS = getMatchingConnectors(ISearchByFinder.class); @NonNull @SuppressWarnings("unchecked") private static <T extends IConnector> Collection<T> getMatchingConnectors(final Class<T> clazz) { final List<T> matching = new ArrayList<>(); for (final IConnector connector : CONNECTORS) { if (clazz.isInstance(connector)) { matching.add((T) connector); } } return Collections.unmodifiableCollection(matching); } @NonNull public static Collection<IConnector> getConnectors() { return CONNECTORS; } @NonNull public static Collection<ISearchByCenter> getSearchByCenterConnectors() { return searchByCenterConns; } @NonNull public static Collection<ISearchByNextPage> getSearchByNextPageConnectors() { return searchByNextPageConns; } @NonNull public static Collection<ISearchByKeyword> getSearchByKeywordConnectors() { return searchByKeywordConns; } @NonNull public static Collection<ISearchByOwner> getSearchByOwnerConnectors() { return SEARCH_BY_OWNER_CONNECTORS; } @NonNull public static Collection<ISearchByFinder> getSearchByFinderConnectors() { return SEARCH_BY_FINDER_CONNECTORS; } @NonNull public static ILogin[] getActiveLiveConnectors() { final List<ILogin> liveConns = new ArrayList<>(); for (final IConnector conn : CONNECTORS) { if (conn instanceof ILogin && conn.isActive()) { liveConns.add((ILogin) conn); } } return liveConns.toArray(new ILogin[liveConns.size()]); } public static boolean canHandle(final @Nullable String geocode) { if (geocode == null) { return false; } if (isInvalidGeocode(geocode)) { return false; } for (final IConnector connector : CONNECTORS) { if (connector.canHandle(geocode)) { return true; } } return false; } @NonNull public static IConnector getConnector(final Geocache cache) { return getConnector(cache.getGeocode()); } @NonNull public static TrackableConnector getConnector(final Trackable trackable) { return getTrackableConnector(trackable.getGeocode()); } @NonNull public static TrackableConnector getTrackableConnector(final String geocode) { for (final TrackableConnector connector : TRACKABLE_CONNECTORS) { if (connector.canHandleTrackable(geocode)) { return connector; } } return UNKNOWN_TRACKABLE_CONNECTOR; // avoid null checks by returning a non implementing // connector } public static List<TrackableConnector> getGenericTrackablesConnectors() { final List<TrackableConnector> trackableConnectors = new ArrayList<>(); for (final TrackableConnector connector : TRACKABLE_CONNECTORS) { if (connector.isGenericLoggable() && connector.isActive()) { trackableConnectors.add(connector); } } return trackableConnectors; } @NonNull public static IConnector getConnector(final String geocodeInput) { // this may come from user input final String geocode = StringUtils.trim(geocodeInput); if (geocode == null) { return UNKNOWN_CONNECTOR; } if (isInvalidGeocode(geocode)) { return UNKNOWN_CONNECTOR; } for (final IConnector connector : CONNECTORS) { if (connector.canHandle(geocode)) { return connector; } } // in case of errors, take UNKNOWN to avoid null checks everywhere return UNKNOWN_CONNECTOR; } /** * Obtain the connector by it's name. If connector is not found, return UNKNOWN_CONNECTOR. * * @param connectorName connector name String * @return The connector matching name */ @NonNull public static IConnector getConnectorByName(final String connectorName) { for (final IConnector connector : CONNECTORS) { if (StringUtils.equals(connectorName, connector.getName())) { return connector; } } // in case of errors, take UNKNOWN to avoid null checks everywhere return UNKNOWN_CONNECTOR; } private static boolean isInvalidGeocode(final String geocode) { return StringUtils.isBlank(geocode) || !Character.isLetterOrDigit(geocode.charAt(0)); } /** @see ISearchByViewPort#searchByViewport */ @NonNull public static SearchResult searchByViewport( final @NonNull Viewport viewport, @NonNull final MapTokens tokens) { return SearchResult.parallelCombineActive( searchByViewPortConns, new Func1<ISearchByViewPort, SearchResult>() { @Override public SearchResult call(final ISearchByViewPort connector) { return connector.searchByViewport(viewport, tokens); } }); } @Nullable public static String getGeocodeFromURL(@Nullable final String url) { if (url == null) { return null; } for (final IConnector connector : CONNECTORS) { @Nullable final String geocode = connector.getGeocodeFromUrl(url); if (StringUtils.isNotBlank(geocode)) { return StringUtils.upperCase(geocode); } } return null; } @NonNull public static Collection<TrackableConnector> getTrackableConnectors() { return TRACKABLE_CONNECTORS; } /** * Get trackable's geocode from an URL. * * @return the geocode, {@code null} if the URL cannot be decoded */ @Nullable public static String getTrackableFromURL(final String url) { if (url == null) { return null; } for (final TrackableConnector connector : TRACKABLE_CONNECTORS) { final String geocode = connector.getTrackableCodeFromUrl(url); if (StringUtils.isNotBlank(geocode)) { return geocode; } } return null; } }
private static Geocache parseCache(final ObjectNode response) { final Geocache cache = new Geocache(); cache.setReliableLatLon(true); try { parseCoreCache(response, cache); // not used: url final String owner = parseUser(response.get(CACHE_OWNER)); cache.setOwnerDisplayName(owner); // OpenCaching has no distinction between user id and user display name. Set the ID anyway to // simplify c:geo workflows. cache.setOwnerUserId(owner); cache.getLogCounts().put(LogType.FOUND_IT, response.get(CACHE_FOUNDS).asInt()); cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.get(CACHE_NOTFOUNDS).asInt()); // only current Api cache.getLogCounts().put(LogType.WILL_ATTEND, response.path(CACHE_WILLATTENDS).asInt()); if (response.has(CACHE_RATING)) { cache.setRating((float) response.get(CACHE_RATING).asDouble()); } cache.setVotes(response.get(CACHE_VOTES).asInt()); cache.setFavoritePoints(response.get(CACHE_RECOMMENDATIONS).asInt()); // not used: req_password // Prepend gc-link to description if available final StringBuilder description = new StringBuilder(500); if (response.hasNonNull("gc_code")) { final String gccode = response.get("gc_code").asText(); description .append( CgeoApplication.getInstance() .getResources() .getString(R.string.cache_listed_on, GCConnector.getInstance().getName())) .append(": <a href=\"http://coord.info/") .append(gccode) .append("\">") .append(gccode) .append("</a><br /><br />"); } description.append(response.get(CACHE_DESCRIPTION).asText()); cache.setDescription(description.toString()); // currently the hint is delivered as HTML (contrary to OKAPI documentation), so we can store // it directly cache.setHint(response.get(CACHE_HINT).asText()); // not used: hints final ArrayNode images = (ArrayNode) response.get(CACHE_IMAGES); if (images != null) { for (final JsonNode imageResponse : images) { final String title = imageResponse.get(CACHE_IMAGE_CAPTION).asText(); final String url = absoluteUrl(imageResponse.get(CACHE_IMAGE_URL).asText(), cache.getGeocode()); // all images are added as spoiler images, although OKAPI has spoiler and non spoiler // images cache.addSpoiler(new Image(url, title)); } } cache.setAttributes( parseAttributes( (ArrayNode) response.path(CACHE_ATTRNAMES), (ArrayNode) response.get(CACHE_ATTR_ACODES))); // TODO: Store license per cache // cache.setLicense(response.getString("attribution_note")); cache.setWaypoints(parseWaypoints((ArrayNode) response.path(CACHE_WPTS)), false); cache.setInventory(parseTrackables((ArrayNode) response.path(CACHE_TRACKABLES))); if (response.has(CACHE_IS_WATCHED)) { cache.setOnWatchlist(response.get(CACHE_IS_WATCHED).asBoolean()); } if (response.hasNonNull(CACHE_MY_NOTES)) { cache.setPersonalNote(response.get(CACHE_MY_NOTES).asText()); cache.parseWaypointsFromNote(); } cache.setLogPasswordRequired(response.get(CACHE_REQ_PASSWORD).asBoolean()); cache.setDetailedUpdatedNow(); // save full detailed caches DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); DataStore.saveLogsWithoutTransaction( cache.getGeocode(), parseLogs((ArrayNode) response.path(CACHE_LATEST_LOGS))); } catch (ClassCastException | NullPointerException e) { Log.e("OkapiClient.parseCache", e); } return cache; }
private static Geocache parseCache(final JSONObject response) { final Geocache cache = new Geocache(); cache.setReliableLatLon(true); try { parseCoreCache(response, cache); // not used: url final JSONObject owner = response.getJSONObject(CACHE_OWNER); cache.setOwnerDisplayName(parseUser(owner)); cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS)); cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS)); if (!response.isNull(CACHE_RATING)) { cache.setRating((float) response.getDouble(CACHE_RATING)); } cache.setVotes(response.getInt(CACHE_VOTES)); cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS)); // not used: req_password // Prepend gc-link to description if available final StringBuilder description = new StringBuilder(500); if (!response.isNull("gc_code")) { final String gccode = response.getString("gc_code"); description .append( cgeoapplication .getInstance() .getResources() .getString(R.string.cache_listed_on, GCConnector.getInstance().getName())) .append(": <a href=\"http://coord.info/") .append(gccode) .append("\">") .append(gccode) .append("</a><br /><br />"); } description.append(response.getString(CACHE_DESCRIPTION)); cache.setDescription(description.toString()); // currently the hint is delivered as HTML (contrary to OKAPI documentation), so we can store // it directly cache.setHint(response.getString(CACHE_HINT)); // not used: hints final JSONArray images = response.getJSONArray(CACHE_IMAGES); if (images != null) { for (int i = 0; i < images.length(); i++) { final JSONObject imageResponse = images.getJSONObject(i); if (imageResponse.getBoolean(CACHE_IMAGE_IS_SPOILER)) { final String title = imageResponse.getString(CACHE_IMAGE_CAPTION); final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode()); cache.addSpoiler(new Image(url, title)); } } } cache.setAttributes(parseAttributes(response.getJSONArray(CACHE_ATTRNAMES))); cache.setLogs(parseLogs(response.getJSONArray(CACHE_LATEST_LOGS))); cache.setHidden(parseDate(response.getString(CACHE_HIDDEN))); // TODO: Store license per cache // cache.setLicense(response.getString("attribution_note")); cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false); if (!response.isNull(CACHE_IS_WATCHED)) { cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED)); } if (!response.isNull(CACHE_MY_NOTES)) { cache.setPersonalNote(response.getString(CACHE_MY_NOTES)); } cache.setLogPasswordRequired(response.getBoolean(CACHE_REQ_PASSWORD)); cache.setDetailedUpdatedNow(); // save full detailed caches cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); } catch (final JSONException e) { Log.e("OkapiClient.parseCache", e); } return cache; }