public void controller(
      FragmentModel model,
      @FragmentParam("patient") Patient patient,
      @FragmentParam("program") Program program,
      @FragmentParam(required = false, value = "registrationFormUuid") String regFormUuid,
      @FragmentParam(required = false, value = "exitFormUuid") String exitFormUuid) {

    ProgramWorkflowService pws = Context.getProgramWorkflowService();
    PatientProgram currentEnrollment = null;
    List<PatientProgram> pastEnrollments = new ArrayList<PatientProgram>();
    for (PatientProgram pp :
        pws.getPatientPrograms(patient, program, null, null, null, null, false)) {
      if (pp.getActive()) {
        currentEnrollment = pp;
      } else {
        pastEnrollments.add(pp);
      }
    }

    model.addAttribute("patient", patient);
    model.addAttribute("program", program);
    model.addAttribute("registrationFormUuid", regFormUuid);
    model.addAttribute("exitFormUuid", exitFormUuid);
    model.addAttribute("currentEnrollment", currentEnrollment);
    model.addAttribute("pastEnrollments", pastEnrollments);
  }
  @Test
  @Verifies(
      value = "should return program enrollment after specified date",
      method = "getClosestFutureProgramEnrollment(Patient,Program,Date)")
  public void shouldReturnPatientProgramWithEnrollmentAfterSpecifiedDate() throws Exception {
    // load this data set so that we get the additional patient program created in this data case
    executeDataSet(
        XML_DATASET_PATH + new TestUtil().getTestDatasetFilename(XML_REGRESSION_TEST_DATASET));

    ProgramWorkflowService pws = Context.getProgramWorkflowService();
    Patient patient = Context.getPatientService().getPatient(2);
    Program program = pws.getProgram(1);

    Calendar cal = Calendar.getInstance();
    cal.set(2001, 6, 31);
    Date date = cal.getTime();

    PatientProgram pp = HtmlFormEntryUtil.getClosestFutureProgramEnrollment(patient, program, date);
    Assert.assertEquals("32296060-03aa-102d-b0e3-001ec94a0cc5", pp.getUuid());

    // now, if we roll the date back a year earlier, it should get the earlier of the two programs
    // for this patient
    cal.set(2000, 6, 31);
    date = cal.getTime();

    pp = HtmlFormEntryUtil.getClosestFutureProgramEnrollment(patient, program, date);
    Assert.assertEquals("32596060-03aa-102d-b0e3-001ec94a0cc5", pp.getUuid());
  }
  @Test
  @Verifies(
      value = "should return a list consisting of active, not retired, states",
      method = "getPossibleNextStates")
  public void getPossibleNextStates_shouldReturnNonRetiredStates() throws Exception {
    executeDataSet(PROGRAM_NEXT_STATES_XML);

    Integer patient = 11;
    Integer workflow = 501;
    Vector<ListItem> possibleNextStates;

    /* retire a workflow state  */
    PatientProgram pp = Context.getProgramWorkflowService().getPatientProgram(patient);
    ProgramWorkflow pw = pp.getProgram().getWorkflow(workflow);
    Set<ProgramWorkflowState> pwss = pw.getStates();

    for (ProgramWorkflowState pws : pwss) {
      Concept cp = pws.getConcept();
      ConceptName cn = cp.getName();
      if (cn != null) {
        String cnn = cn.getName();
        if (cnn.equalsIgnoreCase("Test State 3")) {
          pws.setRetired(true);
        }
      }
    }

    possibleNextStates = dwrProgramWorkflowService.getPossibleNextStates(patient, workflow);
    assertFalse(possibleNextStates.isEmpty());
    assertEquals(2, possibleNextStates.size());
  }
 /**
  * returns active patient program corresponding to valid programId
  *
  * @param ppList
  * @param programIds
  * @return
  */
 private PatientProgram activePatientProgram(
     List<PatientProgram> ppList, Set<Integer> programIds) {
   if (ppList != null) {
     for (PatientProgram pp : ppList) {
       if (pp.getActive() && programIds.contains(pp.getProgram().getProgramId())) return pp;
     }
   }
   return null;
 }
  /** @see {@link HtmlFormEntryUtil#isEnrolledInProgram(Patient,Program,Date)} */
  @Test
  @Verifies(
      value = "should return false if the program was completed",
      method = "isEnrolledInProgram(Patient,Program,Date)")
  public void isEnrolledInProgram_shouldReturnFalseIfTheProgramWasCompleted() throws Exception {
    ProgramWorkflowService pws = Context.getProgramWorkflowService();
    Patient patient = Context.getPatientService().getPatient(2);

    // for test purposes, lets set a program as complete
    PatientProgram pp = pws.getPatientProgram(1);
    Assert.assertSame(patient, pp.getPatient());
    pp.setDateCompleted(new Date());
    Thread.sleep(100);
    pws.savePatientProgram(pp);

    Assert.assertFalse(
        HtmlFormEntryUtil.isEnrolledInProgramOnDate(patient, pws.getProgram(1), new Date()));
  }
  /** @see {@link HtmlFormEntryUtil#isEnrolledInProgram(Patient,Program,Date)} */
  @Test
  @Verifies(
      value =
          "should return false if the date is before the existing patient program enrollment date",
      method = "isEnrolledInProgram(Patient,Program,Date)")
  public void
      isEnrolledInProgram_shouldReturnFalseIfTheDateIsBeforeTheExistingPatientProgramEnrollmentDateIgnoringTimeFields()
          throws Exception { // 2008-08-01 00:00:00.0
    ProgramWorkflowService pws = Context.getProgramWorkflowService();
    Patient patient = Context.getPatientService().getPatient(2);
    Program program = pws.getProgram(1);
    PatientProgram pp = pws.getPatientProgram(1);

    Calendar cal = Calendar.getInstance();
    cal.set(2008, 6, 31);
    Date newEnrollmentDate = cal.getTime();
    Assert.assertTrue(newEnrollmentDate.before(pp.getDateEnrolled())); // sanity check
    Assert.assertFalse(
        HtmlFormEntryUtil.isEnrolledInProgramOnDate(patient, program, newEnrollmentDate));
  }
  public DataSetRow renderRow(
      Patient p,
      PatientIdentifierType patientIdentifierType,
      Location location,
      Date startDate,
      Date endDate) {

    PatientDataHelper pdh = new PatientDataHelper();
    ProgramHelper ph = new ProgramHelper();
    HivMetadata hivMetadata = new HivMetadata();

    DataSetRow row = new DataSetRow();
    pdh.addCol(row, "#", p.getPatientId());
    pdh.addCol(row, "KS ID", pdh.preferredIdentifierAtLocation(p, patientIdentifierType, location));
    pdh.addCol(
        row,
        "ART ID",
        pdh.preferredIdentifierAtLocation(p, lookupPatientIdentifierType("ARV Number"), location));
    pdh.addCol(row, "Birthdate", pdh.getBirthdate(p));
    pdh.addCol(row, "Gender", pdh.getGender(p));
    pdh.addCol(row, "VHW", pdh.vhwName(p, false));
    pdh.addCol(row, "Village", pdh.getVillage(p));

    PatientProgram latestKsProgram =
        ph.getMostRecentProgramEnrollmentAtLocation(
            p, lookupProgram("Kaposis sarcoma program"), location);

    Date latestKsProgramDate = null;
    if (latestKsProgram != null) {
      latestKsProgramDate = latestKsProgram.getDateEnrolled();
      pdh.addCol(row, "KS Program Enrollment Date", pdh.formatYmd(latestKsProgramDate));

      for (PatientState ps : ph.getActiveStatesOnDate(p, latestKsProgramDate)) {
        String programName = ps.getPatientProgram().getProgram().getName();
        pdh.addCol(row, programName + " Status at Enrollment", pdh.formatStateName(ps));
        pdh.addCol(row, programName + " Status Date at Enrollment", pdh.formatStateStartDate(ps));
      }
    }

    Obs mostRecentDxDate = pdh.getLatestObs(p, "DATE OF HIV DIAGNOSIS", null, endDate);
    pdh.addCol(row, "Date HIV Diagnosis", pdh.formatValueDatetime(mostRecentDxDate));

    Program hivProgram = hivMetadata.getHivProgram();
    ProgramWorkflowState onArvState = hivMetadata.getOnArvsState();

    PatientState earliestOnArvsState = ph.getFirstTimeInState(p, hivProgram, onArvState, endDate);
    Date arvStartDate = (earliestOnArvsState == null ? null : earliestOnArvsState.getStartDate());

    if (latestKsProgramDate != null) {
      pdh.addCol(
          row,
          "On ART at KS Enrollment",
          arvStartDate != null && arvStartDate.compareTo(latestKsProgramDate) <= 0);
    }

    Map<String, String> reasonsForStartingArvs = pdh.getReasonStartingArvs(p, endDate);
    for (String reasonKey : reasonsForStartingArvs.keySet()) {
      pdh.addCol(row, "ARV Reason " + reasonKey, reasonsForStartingArvs.get(reasonKey));
    }

    if (arvStartDate != null) {
      pdh.addCol(row, "Start Date for ART", pdh.formatStateStartDate(earliestOnArvsState));
      if (latestKsProgramDate != null) {
        pdh.addCol(
            row,
            "Months on ART at KS Enrollment",
            DateUtil.monthsBetween(arvStartDate, latestKsProgramDate));
      }
    }

    if (latestKsProgramDate != null) {
      Obs artRegimen =
          pdh.getLatestObs(p, "Malawi Antiretroviral drugs received", null, latestKsProgramDate);
      pdh.addCol(row, "ART Regimen Obs at Enrollment", pdh.formatValue(artRegimen));

      Set<Concept> drugOrdersAtEnrollment = pdh.getDrugsTakingOnDate(p, latestKsProgramDate);
      pdh.addCol(
          row, "Drugs Taking at Enrollment", pdh.formatConcepts(drugOrdersAtEnrollment, "+"));

      Obs cd4 = pdh.getLatestObs(p, "CD4 count", null, latestKsProgramDate);
      pdh.addCol(row, "CD4 at enrollment", pdh.formatValue(cd4));
      pdh.addCol(row, "CD4 at enrollment date", pdh.formatObsDatetime(cd4));
    }

    Obs height = pdh.getLatestObs(p, "Height (cm)", null, endDate);
    pdh.addCol(row, "Latest Height", pdh.formatValue(height));
    pdh.addCol(row, "Latest Height Date", pdh.formatObsDatetime(height));

    Obs firstTaxolObs = pdh.getEarliestObs(p, "Paclitaxel (taxol) dose received", null, endDate);
    pdh.addCol(row, "First Taxol Dose Received Date", pdh.formatObsDatetime(firstTaxolObs));

    DrugOrder firstTaxolOrder = pdh.getEarliestDrugOrder(p, "Paclitaxel", endDate);
    pdh.addCol(row, "First Taxol Drug Order Date", pdh.formatOrderStartDate(firstTaxolOrder));

    Date firstTaxolDate = null;
    if (firstTaxolObs != null) {
      firstTaxolDate = firstTaxolObs.getObsDatetime();
    }
    if (firstTaxolOrder != null) {
      if (firstTaxolDate == null || firstTaxolOrder.getStartDate().before(firstTaxolDate)) {
        firstTaxolDate = firstTaxolOrder.getStartDate();
      }
    }
    pdh.addCol(row, "First Taxol Date", pdh.formatYmd(firstTaxolDate));

    if (firstTaxolDate != null) {
      Obs cd4AtTaxol = pdh.getLatestObs(p, "CD4 count", null, firstTaxolDate);
      pdh.addCol(row, "Most recent CD4 at First Taxol", pdh.formatValue(cd4AtTaxol));
      pdh.addCol(row, "Most recent CD4 at First Taxol Date", pdh.formatObsDatetime(cd4AtTaxol));
    }

    for (PatientState ps : ph.getActiveStatesOnDate(p, endDate)) {
      String ed = pdh.formatYmd(endDate);
      String programName = ps.getPatientProgram().getProgram().getName();
      pdh.addCol(row, programName + " Status on " + ed, pdh.formatStateName(ps));
      pdh.addCol(row, programName + " Status Date on " + ed, pdh.formatStateStartDate(ps));
    }

    pdh.addCol(row, "Death Date", pdh.formatYmd(p.getDeathDate()));

    return row;
  }
  @Override
  public String getOverrideContent(String str) {
    if (!Context.isAuthenticated()) {
      return "";
    }
    String gp =
        Context.getAdministrationService()
            .getGlobalProperty("htmlformflowsheet.patientChartFormIds");

    if (StringUtils.isEmpty(gp)) {
      return "";
    }

    StringBuilder sbExisting = new StringBuilder("");
    StringBuilder sbNonExisting = new StringBuilder("");
    try {
      String patientId = this.getParameterMap().get("patientId");
      Patient p = Context.getPatientService().getPatient(Integer.valueOf(patientId));

      for (StringTokenizer st = new StringTokenizer(gp, ","); st.hasMoreTokens(); ) {

        Map<Integer, Set<Integer>> progForms = new HashMap<Integer, Set<Integer>>();
        Set<Integer> programIds = new HashSet<Integer>();

        String formId = st.nextToken().trim();
        if (formId.contains(":")) {
          String[] formIdSplit = formId.split(":");
          formId = formIdSplit[0];
          // check for required programs:
          String programInfo = formIdSplit[1];
          if (programInfo.contains("|")) {
            for (StringTokenizer strTok = new StringTokenizer(programInfo, "|");
                strTok.hasMoreTokens(); ) {
              String sTmp = strTok.nextToken().trim();
              addFormToProgramList(progForms, Integer.valueOf(formId), Integer.valueOf(sTmp));
              programIds.add(Integer.valueOf(sTmp));
            }
          } else {
            // todo: support lookup programs by uuid and forms by uuid?
            addFormToProgramList(progForms, Integer.valueOf(formId), Integer.valueOf(programInfo));
            programIds.add(Integer.valueOf(programInfo));
          }
        }
        Form form = HtmlFormFlowsheetUtil.getFormFromString(formId);
        List<PatientProgram> pps =
            Context.getProgramWorkflowService()
                .getPatientPrograms(p, null, null, null, null, null, false);
        List<Encounter> encs =
            Context.getEncounterService()
                .getEncounters(
                    p, null, null, null, Collections.singletonList(form), null, null, false);

        //	            for (Map.Entry<Integer, Set<Integer>> m : progForms.entrySet()){
        //	            	System.out.println(m.getKey()+ ":" + m.getValue());
        //	            }

        // 1. no program association to form.  always show.
        if (progForms.get(Integer.valueOf(formId)) == null
            || progForms.get(Integer.valueOf(formId)).size() == 0) {
          if (encs.size() == 0) {
            // if no encs, show add new
            sbNonExisting.append(
                " | <a href=\"/"
                    + WebConstants.WEBAPP_NAME
                    + "/module/htmlformentry/htmlFormEntry.form?personId="
                    + p.getPersonId()
                    + "&patientId="
                    + p.getPatientId()
                    + "&returnUrl=&formId="
                    + form.getFormId()
                    + "\">"
                    + form.getName()
                    + "</a> | ");
          } else {
            // if encs, show existing flowsheet parent(s)
            for (Encounter e : encs) {
              sbExisting.append(
                  " | <a href=\"/"
                      + WebConstants.WEBAPP_NAME
                      + "/module/htmlformentry/htmlFormEntry.form?encounterId="
                      + e.getEncounterId()
                      + "&mode=EDIT\">"
                      + form.getName()
                      + " "
                      + "("
                      + Context.getDateFormat().format(e.getEncounterDatetime())
                      + ")</a> | ");
            }
          }
        } else {
          // 2. program(s) specified for form
          // this builds a map of encounter corresponding to the parent form creation to the
          // patientProgram is was created in.
          Map<Encounter, PatientProgram> encounterToPatientProgram =
              new HashMap<Encounter, PatientProgram>();
          for (Encounter e : encs) {
            for (PatientProgram pp : pps) {

              // if encounter is later than start date and less than end date or end date is null
              if (programIds.contains(pp.getProgram().getProgramId())
                  && e.getEncounterDatetime().getTime() >= pp.getDateEnrolled().getTime()
                  && ((pp.getDateCompleted() == null
                      || pp.getDateCompleted().getTime() >= e.getEncounterDatetime().getTime()))) {
                // encounter is in patientprogram
                encounterToPatientProgram.put(e, pp);
              }
            }
          }
          // show existing based on the map
          for (Map.Entry<Encounter, PatientProgram> m : encounterToPatientProgram.entrySet()) {
            sbExisting.append(
                " | <a href=\"/"
                    + WebConstants.WEBAPP_NAME
                    + "/module/htmlformentry/htmlFormEntry.form?encounterId="
                    + m.getKey().getEncounterId()
                    + "&mode=EDIT\">"
                    + form.getName());
            if (m.getValue() != null) {
              sbExisting.append(
                  " "
                      + "("
                      + Context.getDateFormat().format(m.getValue().getDateEnrolled())
                      + " - ");
              if (m.getValue().getDateCompleted() != null)
                sbExisting.append(Context.getDateFormat().format(m.getValue().getDateCompleted()));
              sbExisting.append(")");
            }
            sbExisting.append("</a> | ");
          }

          // show add new
          // if patient is in program currently, AND patient doesn't have an encounter for this
          // program
          PatientProgram ppActive = activePatientProgram(pps, programIds);
          boolean found = false;
          if (ppActive != null) {
            for (Map.Entry<Encounter, PatientProgram> m : encounterToPatientProgram.entrySet()) {
              if (m.getValue() != null && m.getValue().equals(ppActive)) found = true;
            }
            if (!found)
              sbNonExisting.append(
                  " | <a href=\"/"
                      + WebConstants.WEBAPP_NAME
                      + "/module/htmlformentry/htmlFormEntry.form?personId="
                      + p.getPersonId()
                      + "&patientId="
                      + p.getPatientId()
                      + "&returnUrl=&formId="
                      + form.getFormId()
                      + "\"> "
                      + form.getName()
                      + "</a> | ");
          }
        }
      }
      String retString = "<table><tr><td>";
      if (!sbExisting.toString().equals(""))
        retString += "Existing Patient Chart(s): " + sbExisting.toString();
      retString += "</td></tr><tr><td>";
      if (!sbNonExisting.toString().equals(""))
        retString += "Create A New Patient Charts: " + sbNonExisting.toString();
      retString += "</td></tr></table>";
      return retString.replace("|  |", " | ");

    } catch (Exception ex) {
      ex.printStackTrace();
      return "";
    }
  }