private SubmissionResults doSubmission(FormEntrySession session, HttpServletRequest request)
      throws Exception {
    SubmissionResults results = new SubmissionResults();
    session.prepareForSubmit();
    List<FormSubmissionError> validationErrors =
        session.getSubmissionController().validateSubmission(session.getContext(), request);
    if (validationErrors != null && validationErrors.size() > 0) {
      results.setValidationErrors(validationErrors);
      return results;
    }
    session.getSubmissionController().handleFormSubmission(session, request);

    if (session.getContext().getMode() == Mode.ENTER
        && session.hasEncouterTag()
        && (session.getSubmissionActions().getEncountersToCreate() == null
            || session.getSubmissionActions().getEncountersToCreate().size() == 0))
      throw new IllegalArgumentException("This form is not going to create an encounter");
    session.applyActions();
    results.setPatient(session.getPatient());
    results.setEncounterCreated(getLastEncounter(session.getPatient()));
    return results;
  }
  public void run() throws Exception {
    // setup the blank form for the specified patient
    Patient patient = getPatient();
    FormEntrySession session = setupFormEntrySession(patient, getFormName());
    testFormEntrySessionAttribute(session);
    String html = session.getHtmlToDisplay();
    testBlankFormHtml(html);

    // submit some initial data and test it
    Map<String, String> labeledWidgets = getLabeledWidgets(html, widgetLabels());
    MockHttpServletRequest request = new MockHttpServletRequest();
    setupRequest(request, labeledWidgets);
    Patient patientToView = null;
    Encounter encounterToView = null;
    if (request.getParameterMap().size() > 0) {
      SubmissionResults results = doSubmission(session, request);
      testResults(results);
      patientToView = results.getPatient();
      encounterToView = results.getEncounterCreated();
    }

    // view that patient and run tests on it
    Patient overridePatient = getPatientToView();
    boolean doViewPatient = overridePatient != null || doViewPatient();
    if (doViewPatient) {
      if (overridePatient != null) patientToView = overridePatient;
      session = setupFormViewSession(patientToView, null, getFormName());
      testFormViewSessionAttribute(session);
      html = session.getHtmlToDisplay();
      testViewingPatient(patientToView, html);
    }

    // view that encounter and run tests on that
    Encounter override = getEncounterToView();
    boolean doViewEncounter = override != null || doViewEncounter();
    if (doViewEncounter) {
      if (override != null) encounterToView = override;
      session = setupFormViewSession(patientToView, encounterToView, getFormName());
      testFormViewSessionAttribute(session);
      html = session.getHtmlToDisplay();
      testViewingEncounter(encounterToView, html);
    }

    // edit the encounter, and run tests on that
    override = getEncounterToEdit();
    boolean doEditEncounter = override != null || doEditEncounter();

    overridePatient = getPatientToEdit();
    boolean doEditPatient = overridePatient != null || doEditPatient();

    if (doEditEncounter || doEditPatient) {
      Encounter toEdit = encounterToView;
      if (override != null) toEdit = override;

      Patient patientToEdit = patientToView;
      if (overridePatient != null) patientToEdit = overridePatient;

      session = setupFormEditSession(patientToEdit, toEdit, getFormName());
      testFormEditSessionAttribute(session);
      String editHtml = session.getHtmlToDisplay();
      testEditFormHtml(editHtml);

      Map<String, String> labeledWidgetsForEdit =
          getLabeledWidgets(editHtml, widgetLabelsForEdit());
      MockHttpServletRequest editRequest = createEditRequest(editHtml);
      setupEditRequest(editRequest, labeledWidgetsForEdit);
      if (editRequest.getParameterMap().size() > 0) {
        SubmissionResults results = doSubmission(session, editRequest);
        testEditedResults(results);
        results.getEncounterCreated();
        results.getPatient();
      }
    }
  }