@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;
  }
Example #2
0
 public static void testGetConnectorString() {
   final IConnector connector = ConnectorFactory.getConnector("GC12345");
   assertNotNull(connector);
   assertEquals(GCConnector.getInstance().getName(), connector.getName());
 }
Example #3
0
 public static void testGetConnectorCgCache() {
   assertEquals(GCConnector.getInstance(), ConnectorFactory.getConnector(new GC1ZXX2()));
 }
Example #4
0
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;
  }
}
Example #5
0
  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;
  }
Example #6
0
  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;
  }