/**
   * @see
   *     org.springframework.web.servlet.mvc.SimpleFormController#processFormSubmission(javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse, java.lang.Object,
   *     org.springframework.validation.BindException)
   */
  @Override
  protected ModelAndView processFormSubmission(
      HttpServletRequest request, HttpServletResponse reponse, Object obj, BindException errors)
      throws Exception {

    Encounter encounter = (Encounter) obj;

    try {
      if (Context.isAuthenticated()) {
        Context.addProxyPrivilege(PrivilegeConstants.VIEW_USERS);
        Context.addProxyPrivilege(PrivilegeConstants.VIEW_PATIENTS);

        if (encounter.getEncounterId() == null
            && StringUtils.hasText(request.getParameter("patientId"))) {
          encounter.setPatient(
              Context.getPatientService()
                  .getPatient(Integer.valueOf(request.getParameter("patientId"))));
        }
        if (encounter.isVoided()) {
          ValidationUtils.rejectIfEmptyOrWhitespace(errors, "voidReason", "error.null");
        }

        String[] providerIdsArray = ServletRequestUtils.getStringParameters(request, "providerIds");
        if (ArrayUtils.isEmpty(providerIdsArray)) {
          errors.reject("Encounter.provider.atleastOneProviderRequired");
        }

        String[] roleIdsArray =
            ServletRequestUtils.getStringParameters(request, "encounterRoleIds");

        ProviderService ps = Context.getProviderService();
        EncounterService es = Context.getEncounterService();
        if (providerIdsArray != null && roleIdsArray != null) {
          // list to store role provider mappings to be used below to detect removed providers
          List<String> unremovedRoleAndProviders = new ArrayList<String>();
          for (int i = 0; i < providerIdsArray.length; i++) {
            if (StringUtils.hasText(providerIdsArray[i]) && StringUtils.hasText(roleIdsArray[i])) {
              unremovedRoleAndProviders.add(roleIdsArray[i] + "-" + providerIdsArray[i]);
              Provider provider = ps.getProvider(Integer.valueOf(providerIdsArray[i]));
              EncounterRole encounterRole = es.getEncounterRole(Integer.valueOf(roleIdsArray[i]));
              // if this is an existing provider, don't create a new one to avoid losing existing
              // details like dateCreated, creator, uuid etc in the encounter_provider table
              if (encounter.getProvidersByRole(encounterRole).contains(provider)) {
                continue;
              }

              // this is a new provider
              encounter.addProvider(encounterRole, provider);
            }
          }
          // Get rid of the removed ones
          for (Map.Entry<EncounterRole, Set<Provider>> entry :
              encounter.getProvidersByRoles().entrySet()) {
            for (Provider p : entry.getValue()) {
              if (!unremovedRoleAndProviders.contains(
                  entry.getKey().getEncounterRoleId() + "-" + p.getProviderId())) {
                encounter.removeProvider(entry.getKey(), p);
              }
            }
          }
        }

        ValidationUtils.invokeValidator(new EncounterValidator(), encounter, errors);
      }
    } finally {
      Context.removeProxyPrivilege(PrivilegeConstants.VIEW_USERS);
      Context.removeProxyPrivilege(PrivilegeConstants.VIEW_PATIENTS);
    }

    return super.processFormSubmission(request, reponse, encounter, errors);
  }