public String getCacheKey(LocalDate date, APICollectionType type) {
   return APIUtil.constructFullUrl(
       client.getApiBaseUrl(),
       client.getApiVersion(),
       FitbitUser.CURRENT_AUTHORIZED_USER,
       type,
       date,
       APIFormat.JSON);
 }
  public void evictUpdatedResourcesFromCache(
      String subscriberId, InputStream updateMessageStream, String serverSignature)
      throws FitbitAPIException {
    try {
      if (null == serverSignature) {
        throw new FitbitAPISecurityException("Missing signature.");
      }

      String updateMessage = APIUtil.inputStreamToString(updateMessageStream);

      String ourSignature = APIUtil.generateSignature(updateMessage, subscriberSecret);
      if (null == ourSignature || !ourSignature.equals(serverSignature)) {
        throw new FitbitAPISecurityException("Signatures do not match, given " + serverSignature);
      }

      UpdateNotification notification = new UpdateNotification(new JSONArray(updateMessage));

      int i = 0;
      for (UpdatedResource resource : notification.getUpdatedResources()) {
        //noinspection UnnecessaryParentheses,ValueOfIncrementOrDecrementUsed
        log.info(
            "Processing update notification "
                + (++i)
                + " for subscription "
                + resource.getSubscriptionId());

        LocalSubscriptionDetail sub =
            subscriptionStore.getBySubscriptionId(resource.getSubscriptionId());
        if (null == sub) {
          log.info(
              "Nothing known about subscription "
                  + resource.getSubscriptionId()
                  + ", creating placeholder.");

          sub =
              new LocalSubscriptionDetail(
                  new SubscriptionDetail(
                      subscriberId,
                      resource.getSubscriptionId(),
                      resource.getOwner(),
                      resource.getCollectionType()),
                  false);
          subscriptionStore.save(sub);
        }

        sub.setLastUpdateNotificationDate(new Date());

        APIResourceCredentials credentials =
            credentialsCache.getResourceCredentials(
                new LocalUserDetail(resource.getSubscriptionId()));

        String cacheKeyWithUserId =
            APIUtil.constructFullUrl(
                client.getApiBaseUrl(),
                client.getApiVersion(),
                resource.getOwner(),
                resource.getCollectionType(),
                resource.getDate(),
                APIFormat.JSON);

        Activities entity = (Activities) entityCache.get(credentials, cacheKeyWithUserId);
        if (null != entity) {
          log.info("Evicting entity " + cacheKeyWithUserId);
          entityCache.remove(credentials, cacheKeyWithUserId);
        } else {
          log.info("There is no cached version of entity " + cacheKeyWithUserId);
        }

        String cacheKeyWithPlaceholder =
            APIUtil.constructFullUrl(
                client.getApiBaseUrl(),
                client.getApiVersion(),
                FitbitUser.CURRENT_AUTHORIZED_USER,
                resource.getCollectionType(),
                resource.getDate(),
                APIFormat.JSON);

        entity = (Activities) entityCache.get(credentials, cacheKeyWithPlaceholder);
        if (null != entity) {
          log.info("Evicting entity " + cacheKeyWithPlaceholder);
          entityCache.remove(credentials, cacheKeyWithPlaceholder);
        } else {
          log.info("There is no cached version of entity " + cacheKeyWithPlaceholder);
        }
      }
    } catch (IOException e) {
      throw new FitbitAPIException("Notification stream is malformed: " + e, e);
    } catch (JSONException e) {
      throw new FitbitAPIException("Unable to parse update message: " + e, e);
    }
  }