private boolean isHistoryUpdateCompleted(final long guestId, final Connector connector) {
   if (connector.isAutonomous()) return isHistoryUpdateCompleted(guestId, connector.getName(), 0);
   final int[] connectorObjectTypeValues = connector.objectTypeValues();
   for (int connectorObjectTypeValue : connectorObjectTypeValues)
     if (!isHistoryUpdateCompleted(guestId, connector.getName(), connectorObjectTypeValue))
       return false;
   return true;
 }
 /**
  * delete pending tasks for a guest's connector
  *
  * @param guestId
  * @param connector
  * @param wipeOutHistory wether to delete everything including the initial history update that we
  *     use to track wether we need to everything from scratch or just do so incrementally
  */
 @Transactional(readOnly = false)
 @Override
 public void flushUpdateWorkerTasks(long guestId, Connector connector, boolean wipeOutHistory) {
   List<AbstractUpdater> toStop = new ArrayList<AbstractUpdater>();
   if (!wipeOutHistory)
     JPAUtils.execute(
         em,
         "updateWorkerTasks.delete.byApi",
         guestId,
         connector.getName(),
         UpdateType.INITIAL_HISTORY_UPDATE);
   else JPAUtils.execute(em, "updateWorkerTasks.deleteAll.byApi", guestId, connector.getName());
 }
 @Override
 public Collection<UpdateWorkerTask> getUpdatingUpdateTasks(
     final long guestId, final Connector connector) {
   List<UpdateWorkerTask> tasks =
       JPAUtils.find(
           em,
           UpdateWorkerTask.class,
           "updateWorkerTasks.isInProgressOrScheduledBefore",
           System.currentTimeMillis(),
           guestId,
           connector.getName());
   HashMap<Integer, UpdateWorkerTask> seen = new HashMap<Integer, UpdateWorkerTask>();
   for (UpdateWorkerTask task : tasks) {
     if (hasStalled(task)) {
       task.status = Status.STALLED;
       em.merge(task);
     } else {
       if (seen.containsKey(task.objectTypes)) {
         if (seen.get(task.objectTypes).timeScheduled < task.timeScheduled)
           seen.put(task.objectTypes, task);
       } else {
         seen.put(task.objectTypes, task);
       }
     }
   }
   return seen.values();
 }
  /**
   * Update all the facet types for a given user and connector.
   *
   * @param guestId the user for whom the connector is to be updated
   * @param connector the connector to be updated
   * @param force force an update (sync now); if false, it means it was called by the background
   *     "cron" task
   * @return
   */
  @Override
  public List<ScheduleResult> updateConnector(
      final long guestId, Connector connector, boolean force) {
    System.out.println("updateConnector");
    List<ScheduleResult> scheduleResults = new ArrayList<ScheduleResult>();
    StringBuilder messageRoot =
        new StringBuilder(
            "module=updateQueue component=connectorUpdateService" + " action=updateConnector");
    if (isShuttingDown) {
      logger.warn(messageRoot.append(" message=\"Service is shutting down... Refusing updates\""));
      return scheduleResults;
    }

    // if forcing an update (sync now), we actually want to flush the update requests
    // that have stacked up in the queue
    if (force) flushUpdateWorkerTasks(guestId, connector, false);

    // some connectors (e.g. the fitbit) need to decide what objectTypes to update by themselves;
    // for those, we pass 0 for the objectType parameter, which will be overridden by the
    // connector's updater
    final boolean historyUpdateCompleted = isHistoryUpdateCompleted(guestId, connector);
    if (connector.isAutonomous()) {
      scheduleObjectTypeUpdate(
          guestId,
          connector,
          0,
          scheduleResults,
          historyUpdateCompleted
              ? UpdateType.INCREMENTAL_UPDATE
              : UpdateType.INITIAL_HISTORY_UPDATE);
    } else {
      int[] objectTypeValues = connector.objectTypeValues();
      for (int objectTypes : objectTypeValues) {
        scheduleObjectTypeUpdate(
            guestId,
            connector,
            objectTypes,
            scheduleResults,
            historyUpdateCompleted
                ? UpdateType.INCREMENTAL_UPDATE
                : UpdateType.INITIAL_HISTORY_UPDATE);
      }
    }
    return scheduleResults;
  }
 @Override
 @Transactional(readOnly = false)
 public void addApiNotification(Connector connector, long guestId, String content) {
   ApiNotification notification = new ApiNotification();
   notification.api = connector.value();
   notification.guestId = guestId;
   notification.ts = System.currentTimeMillis();
   notification.content = content;
   em.persist(notification);
 }
 @Override
 public ApiUpdate getLastSuccessfulUpdate(long guestId, Connector api, int objectTypes) {
   if (objectTypes == -1) return getLastSuccessfulUpdate(guestId, api);
   return JPAUtils.findUnique(
       em,
       ApiUpdate.class,
       "apiUpdates.last.successful.byApiAndObjectTypes",
       guestId,
       api.value(),
       objectTypes);
 }
  @RequestMapping(value = "/upgradeToken")
  public String upgradeToken(HttpServletRequest request, HttpServletResponse response)
      throws OAuthException, OAuthMessageSignerException, OAuthNotAuthorizedException,
          OAuthExpectationFailedException, OAuthCommunicationException {
    OAuthConsumer consumer =
        (OAuthConsumer) request.getSession().getAttribute(FRESHBOOKS_OAUTH_CONSUMER);
    OAuthProvider provider =
        (OAuthProvider) request.getSession().getAttribute(FRESHBOOKS_OAUTH_PROVIDER);
    String verifier = request.getParameter("oauth_verifier");
    provider.retrieveAccessToken(consumer, verifier);
    Guest guest = AuthHelper.getGuest();

    final Connector connector = Connector.getConnector("freshbooks");
    final ApiKey apiKey = guestService.createApiKey(guest.getId(), connector);

    guestService.setApiKeyAttribute(apiKey, "accessToken", consumer.getToken());
    guestService.setApiKeyAttribute(apiKey, "tokenSecret", consumer.getTokenSecret());

    return "redirect:/app/from/" + connector.getName();
  }
 /**
  * Schedules a new update if there is no update for the user for this ObjectType and <code>force
  * </code> is false
  *
  * @param guestId The user's id
  * @param connector The Connector that is to be updated
  * @param objectTypes the integer bitmask of object types to be updated
  * @param scheduleResults The result of adding the update will be added to the list. \result.type
  *     will be of type ScheduleResult.ResultType. If there was a previously existing \result.type
  *     will be ALREADY_SCHEDULED
  */
 private void scheduleObjectTypeUpdate(
     long guestId,
     Connector connector,
     int objectTypes,
     List<ScheduleResult> scheduleResults,
     UpdateType updateType) {
   UpdateWorkerTask updateWorkerTask =
       getScheduledUpdateTask(guestId, connector.getName(), objectTypes);
   if (updateWorkerTask != null)
     scheduleResults.add(
         new ScheduleResult(
             connector.getName(),
             objectTypes,
             ScheduleResult.ResultType.ALREADY_SCHEDULED,
             updateWorkerTask.timeScheduled));
   else {
     final ScheduleResult scheduleResult =
         scheduleUpdate(
             guestId, connector.getName(), objectTypes, updateType, System.currentTimeMillis());
     scheduleResults.add(scheduleResult);
   }
 }
 @Override
 @Transactional(readOnly = false)
 public List<UpdateWorkerTask> getScheduledOrInProgressUpdateTasks(
     long guestId, Connector connector) {
   List<UpdateWorkerTask> updateWorkerTask =
       JPAUtils.find(
           em,
           UpdateWorkerTask.class,
           "updateWorkerTasks.isScheduledOrInProgress",
           guestId,
           connector.getName());
   for (UpdateWorkerTask workerTask : updateWorkerTask) {
     if (hasStalled(workerTask)) {
       workerTask.status = Status.STALLED;
       em.merge(workerTask);
     }
   }
   return updateWorkerTask;
 }
 @Override
 @Transactional(readOnly = false)
 public void addApiUpdate(
     long guestId,
     Connector api,
     int objectTypes,
     long ts,
     long elapsed,
     String query,
     boolean success) {
   ApiUpdate updt = new ApiUpdate();
   updt.guestId = guestId;
   updt.api = api.value();
   updt.ts = System.currentTimeMillis();
   updt.query = query;
   updt.objectTypes = objectTypes;
   updt.elapsed = elapsed;
   updt.success = success;
   em.persist(updt);
 }
 @Override
 public List<ScheduleResult> updateConnectorObjectType(
     final long guestId, final Connector connector, int objectTypes, boolean force) {
   List<ScheduleResult> scheduleResults = new ArrayList<ScheduleResult>();
   if (isShuttingDown) {
     StringBuilder sb =
         new StringBuilder(
                 "module=updateQueue component=connectorUpdateService"
                     + " action=updateConnectorObjectType")
             .append(" message=\"Service is shutting down... Refusing updates\"");
     logger.warn(sb.toString());
     return scheduleResults;
   }
   getScheduledUpdateTask(guestId, connector.getName(), objectTypes);
   // if forcing an update (sync now), we actually want to flush the update requests
   // that have stacked up in the queue
   if (force) flushUpdateWorkerTasks(guestId, connector, objectTypes, false);
   scheduleObjectTypeUpdate(
       guestId, connector, objectTypes, scheduleResults, UpdateType.INCREMENTAL_UPDATE);
   return scheduleResults;
 }
 @Override
 public Collection<UpdateWorkerTask> getLastFinishedUpdateTasks(
     final long guestId, final Connector connector) {
   List<UpdateWorkerTask> tasks =
       JPAUtils.find(
           em,
           UpdateWorkerTask.class,
           "updateWorkerTasks.getLastFinishedTask",
           System.currentTimeMillis(),
           guestId,
           connector.getName());
   HashMap<Integer, UpdateWorkerTask> seen = new HashMap<Integer, UpdateWorkerTask>();
   for (UpdateWorkerTask task : tasks) {
     if (seen.containsKey(task.objectTypes)) {
       if (seen.get(task.objectTypes).timeScheduled < task.timeScheduled)
         seen.put(task.objectTypes, task);
     } else {
       seen.put(task.objectTypes, task);
     }
   }
   return seen.values();
 }
 public boolean checkAuthorization(GuestService guestService, long guestId) {
   ApiKey apiKey = guestService.getApiKey(guestId, Connector.getConnector("toodledo"));
   return apiKey != null;
 }
 @Override
 public long getNumberOfUpdatesSince(long guestId, Connector connector, long then) {
   return JPAUtils.count(em, "apiUpdates.count.byGuest.since", guestId, connector.value(), then);
 }
 @Override
 public long getTotalNumberOfUpdatesSince(Connector connector, long then) {
   return JPAUtils.count(em, "apiUpdates.count.all.since", connector.value(), then);
 }
 @Override
 public long getNumberOfUpdates(long guestId, Connector connector) {
   return JPAUtils.count(em, "apiUpdates.count.byGuest", guestId, connector.value());
 }
 @Override
 public long getTotalNumberOfUpdates(Connector connector) {
   return JPAUtils.count(em, "apiUpdates.count.all", connector.value());
 }
 @Override
 public long getTotalNumberOfGuestsUsingConnector(Connector connector) {
   return JPAUtils.count(em, "apiKey.count.byApi", connector.value());
 }
 public static ConnectorModel connectorModel(Connector api) {
   ConnectorModel vo = new ConnectorModel();
   vo.connectorName = api.getName();
   vo.prettyName = api.prettyName();
   return vo;
 }
 @Override
 public List<ApiUpdate> getUpdates(
     long guestId, final Connector connector, final int pageSize, final int page) {
   return JPAUtils.findPaged(
       em, ApiUpdate.class, "apiUpdates.last.paged", pageSize, page, guestId, connector.value());
 }
 @Override
 public ApiUpdate getLastSuccessfulUpdate(long guestId, Connector api) {
   return JPAUtils.findUnique(
       em, ApiUpdate.class, "apiUpdates.last.successful.byApi", guestId, api.value());
 }
 @Override
 public AbstractUpdater getUpdater(Connector connector) {
   return beanFactory.getBean(connector.getUpdaterClass());
 }