@Override
  protected EncounterAddFailedEvent doInBackground(Void... params) {
    RequestFuture<Encounter> encounterFuture = RequestFuture.newFuture();

    mServer.addEncounter(mPatient, mEncounter, encounterFuture, encounterFuture);
    Encounter encounter;
    try {
      encounter = encounterFuture.get();
    } catch (InterruptedException e) {
      return new EncounterAddFailedEvent(EncounterAddFailedEvent.Reason.INTERRUPTED, e);
    } catch (ExecutionException e) {
      LOG.e(e, "Server error while adding encounter");

      EncounterAddFailedEvent.Reason reason = EncounterAddFailedEvent.Reason.UNKNOWN_SERVER_ERROR;
      if (e.getCause() != null) {
        String errorMessage = e.getCause().getMessage();
        if (errorMessage.contains("failed to validate")) {
          reason = EncounterAddFailedEvent.Reason.FAILED_TO_VALIDATE;
        } else if (errorMessage.contains("Privileges required")) {
          reason = EncounterAddFailedEvent.Reason.FAILED_TO_AUTHENTICATE;
        }
      }
      LOG.e("Error response: %s", ((VolleyError) e.getCause()).networkResponse);

      return new EncounterAddFailedEvent(reason, (VolleyError) e.getCause());
    }

    if (encounter.uuid == null) {
      LOG.e(
          "Although the server reported an encounter successfully added, it did not "
              + "return a UUID for that encounter. This indicates a server error.");

      return new EncounterAddFailedEvent(
          EncounterAddFailedEvent.Reason.FAILED_TO_SAVE_ON_SERVER, null /*exception*/);
    }

    AppEncounter appEncounter = AppEncounter.fromNet(mPatient.uuid, encounter);

    if (appEncounter.observations.length > 0) {
      int inserted =
          mContentResolver.bulkInsert(
              Contracts.Observations.CONTENT_URI, appEncounter.toContentValuesArray());

      if (inserted != appEncounter.observations.length) {
        LOG.w(
            "Inserted %d observations for encounter. Expected: %d",
            inserted, appEncounter.observations.length);
        return new EncounterAddFailedEvent(
            EncounterAddFailedEvent.Reason.INVALID_NUMBER_OF_OBSERVATIONS_SAVED,
            null /*exception*/);
      }
    } else {
      LOG.w("Encounter was sent to the server but contained no observations.");
    }

    mUuid = encounter.uuid;

    return null;
  }
  @Override
  protected void onPostExecute(EncounterAddFailedEvent event) {
    // If an error occurred, post the error event.
    if (event != null) {
      mBus.post(event);
      return;
    }

    // If the UUID was not set, a programming error occurred. Log and post an error event.
    if (mUuid == null) {
      LOG.e(
          "Although an encounter add ostensibly succeeded, no UUID was set for the newly-"
              + "added encounter. This indicates a programming error.");

      mBus.post(
          new EncounterAddFailedEvent(EncounterAddFailedEvent.Reason.UNKNOWN, null /*exception*/));
      return;
    }

    // Otherwise, start a fetch task to fetch the encounter from the database.
    mBus.register(new CreationEventSubscriber());
    FetchSingleAsyncTask<AppEncounter> task =
        mTaskFactory.newFetchSingleAsyncTask(
            Contracts.Observations.CONTENT_URI,
            ENCOUNTER_PROJECTION,
            new EncounterUuidFilter(),
            mUuid,
            new AppEncounterConverter(mPatient.uuid),
            mBus);
    task.execute();
  }