@Override
 public String getValueAsString(Locale locale) {
   if (obs.getValueCoded() != null) {
     return obs.getValueCoded().getNames(false).iterator().next().getName();
   } else if (obs.getValueDate() != null) {
     return new SimpleDateFormat("dd MMM yyyy hh:mm a", locale).format(obs.getValueDate());
   } else {
     return obs.getValueAsString(locale);
   }
 }
  /**
   * @see org.openmrs.calculation.patient.PatientCalculation#evaluate(java.util.Collection,
   *     java.util.Map, org.openmrs.calculation.patient.PatientCalculationContext)
   */
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort,
      Map<String, Object> parameterValues,
      PatientCalculationContext context) {

    Program mchcsProgram = MetadataUtils.getProgram(MchMetadata._Program.MCHCS);

    // Get all patients who are alive and in MCH-CS program
    Set<Integer> alive = Filters.alive(cohort, context);
    Set<Integer> inMchcsProgram = Filters.inProgram(mchcsProgram, alive, context);

    // get wheather the child is HIV Exposed
    CalculationResultMap lastChildHivStatus =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.CHILDS_CURRENT_HIV_STATUS), inMchcsProgram, context);
    CalculationResultMap medOrdersObss =
        Calculations.allObs(Dictionary.getConcept(Dictionary.MEDICATION_ORDERS), cohort, context);

    // Get concepts for  medication prophylaxis
    Concept nvp = Dictionary.getConcept(Dictionary.NEVIRAPINE);
    Concept nvpazt3tc = Dictionary.getConcept(Dictionary.LAMIVUDINE_NEVIRAPINE_ZIDOVUDINE);
    Concept hivExposed = Dictionary.getConcept(Dictionary.EXPOSURE_TO_HIV);

    CalculationResultMap ret = new CalculationResultMap();

    for (Integer ptId : cohort) {
      boolean notOnPcp = false;

      // checking wheather the infant is in mchcs program, alive and HEI
      Obs hivStatusObs = EmrCalculationUtils.obsResultForPatient(lastChildHivStatus, ptId);
      if (inMchcsProgram.contains(ptId)
          && lastChildHivStatus != null
          && hivStatusObs != null
          && (hivStatusObs.getValueCoded().equals(hivExposed))) {
        notOnPcp = true;
        ListResult patientMedOrders = (ListResult) medOrdersObss.get(ptId);
        if (patientMedOrders != null) {
          // Look through list of medication order obs for any  CTX
          List<Obs> medOrderObsList = CalculationUtils.extractResultValues(patientMedOrders);
          for (Obs medOrderObs : medOrderObsList) {
            if (medOrderObs.getValueCoded().equals(nvp)
                || medOrderObs.getValueCoded().equals(nvpazt3tc)) {
              notOnPcp = false;
              break;
            }
          }
        }
      }
      ret.put(ptId, new BooleanResult(notOnPcp, this, context));
    }

    return ret;
  }
 private ArrayList<String> getValuCodedNames(Set<Obs> diagnosisObservationGroupMembers) {
   ArrayList<String> valueCodedNames = new ArrayList<String>();
   for (Obs diagnosisObservationGroupMember : diagnosisObservationGroupMembers) {
     valueCodedNames.add(diagnosisObservationGroupMember.getValueCoded().getName().getName());
   }
   return valueCodedNames;
 }
Exemple #4
0
  /**
   * Builds a coded result from an observation
   *
   * @param obs
   */
  public Result(Obs obs) {
    this(
        obs.getObsDatetime(),
        null,
        obs.getValueAsBoolean(),
        obs.getValueCoded(),
        obs.getValueDatetime(),
        obs.getValueNumeric(),
        obs.getValueText(),
        obs);

    Concept concept = obs.getConcept();
    ConceptDatatype conceptDatatype = null;

    if (concept != null) {
      conceptDatatype = concept.getDatatype();

      if (conceptDatatype == null) {
        return;
      }
      if (conceptDatatype.isCoded()) {
        this.datatype = Datatype.CODED;
      } else if (conceptDatatype.isNumeric()) {
        this.datatype = Datatype.NUMERIC;
      } else if (conceptDatatype.isDate()) {
        this.datatype = Datatype.DATETIME;
      } else if (conceptDatatype.isText()) {
        this.datatype = Datatype.TEXT;
      } else if (conceptDatatype.isBoolean()) {
        this.datatype = Datatype.BOOLEAN;
      }
    }
  }
    /**
     * Fails if there isn't an obs group with these exact characteristics
     *
     * @param groupingConceptId the concept id of the grouping obs
     * @param conceptIdsAndValues these parameters must be given in pairs, the first element of
     *     which is the conceptId of a child obs (Integer) and the second element of which is the
     *     value of the child obs
     */
    public void assertObsGroupCreated(int groupingConceptId, Object... conceptIdsAndValues) {
      // quick checks
      Assert.assertNotNull(encounterCreated);
      Collection<Obs> temp = encounterCreated.getAllObs();
      Assert.assertNotNull(temp);

      List<ObsValue> expected = new ArrayList<ObsValue>();
      for (int i = 0; i < conceptIdsAndValues.length; i += 2) {
        int conceptId = (Integer) conceptIdsAndValues[i];
        Object value = conceptIdsAndValues[i + 1];
        expected.add(new ObsValue(conceptId, value));
      }

      for (Obs o : temp) {
        if (o.getConcept().getConceptId() == groupingConceptId) {
          if (o.getValueCoded() != null
              || o.getValueComplex() != null
              || o.getValueDatetime() != null
              || o.getValueDrug() != null
              || o.getValueNumeric() != null
              || o.getValueText() != null) {
            Assert.fail(
                "Obs group with groupingConceptId "
                    + groupingConceptId
                    + " should has a non-null value");
          }
          if (TestUtil.isMatchingObsGroup(o, expected)) {
            return;
          }
        }
      }
      Assert.fail("Cannot find an obs group matching " + expected);
    }
 public static List<Chemotherapy> generateChemotherapies(Patient patient) {
   List<Encounter> encounters =
       getEncountersByTreatment(patient, PatientPortalToolkitConstants.CHEMOTHERAPY_ENCOUNTER);
   List<Chemotherapy> chemotherapiesList = new ArrayList<Chemotherapy>();
   for (Encounter e : encounters) {
     Chemotherapy chemotherapy = new Chemotherapy();
     List<String> chemomedications = new ArrayList<String>();
     Set<Obs> obsList = e.getObs();
     chemotherapy.setEncounterUuid(e.getUuid());
     for (Obs o : obsList) {
       if (o.getConcept().getUuid().equals("8481b9da-74e3-45a9-9124-d69ab572d636"))
         chemomedications.add(o.getValueCoded().getName().getName());
       if (o.getConcept().getUuid().equals("85c3a99e-0598-4c63-912b-796dee9c75b2"))
         chemotherapy.setChemoStartDate(o.getValueDate());
       if (o.getConcept().getUuid().equals("7dd8b8aa-b0f1-4eb1-862d-b6d737bdd315"))
         chemotherapy.setChemoEndDate(o.getValueDate());
       if (o.getConcept().getUuid().equals("361b7f9b-a985-4b18-9055-03af3b41b8b3")) {
         if (o.getValueCoded().getUuid().equals("1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
           chemotherapy.setCentralLine(true);
         else chemotherapy.setCentralLine(false);
       }
       // doctors name
       if (o.getConcept().getUuid().equals("c2cb2220-c07d-47c6-a4df-e5918aac3fc2"))
         chemotherapy.setPcpName(o.getValueText());
       // doctors email
       if (o.getConcept().getUuid().equals("898a0028-8c65-4db9-a802-1577fce59864"))
         chemotherapy.setPcpEmail(o.getValueText());
       // doctors phone
       if (o.getConcept().getUuid().equals("9285b227-4054-4830-ac32-5ea78462e8c4"))
         chemotherapy.setPcpPhone(o.getValueText());
       if (o.getConcept().getUuid().equals("47d58999-d3b5-4869-a52e-841e2e6bdbb3"))
         chemotherapy.setInstitutionName(o.getValueText());
       if (o.getConcept().getUuid().equals("bfa752d6-2037-465e-b0a2-c4c2d485ec32"))
         chemotherapy.setInstitutionCity(o.getValueText());
       if (o.getConcept().getUuid().equals("34489100-487e-443a-bf27-1b6869fb9332"))
         chemotherapy.setInstitutionState(o.getValueText());
     }
     chemotherapy.setChemoMedications(chemomedications);
     chemotherapiesList.add(chemotherapy);
   }
   return chemotherapiesList;
 }
 public static List<Surgery> generateSurgeries(Patient patient) {
   List<Encounter> encounters =
       getEncountersByTreatment(patient, PatientPortalToolkitConstants.SURGERY_ENCOUNTER);
   List<Surgery> surgeriesList = new ArrayList<Surgery>();
   for (Encounter e : encounters) {
     Surgery surgery = new Surgery();
     List<String> surgeryTypes = new ArrayList<String>();
     Set<Obs> obsList = e.getObs();
     surgery.setEncounterUuid(e.getUuid());
     for (Obs o : obsList) {
       if (o.getConcept().getUuid().equals("d409122c-8a0b-4282-a17f-07abad81f278"))
         surgeryTypes.add(o.getValueCoded().getName().getName());
       if (o.getConcept().getUuid().equals("99ef1d68-05ed-4f37-b98b-c982e3574138")) {
         if (o.getValueCoded().getUuid().equals("1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
           surgery.setHasMajorComplications(true);
         else surgery.setHasMajorComplications(false);
       }
       if (o.getConcept().getUuid().equals("c2d9fca3-1e0b-4007-8c3c-b3ebb4e67963"))
         surgery.setMajorComplications(o.getValueText());
       if (o.getConcept().getUuid().equals("87a69397-65ef-4576-a709-ae0a526afd85"))
         surgery.setSurgeryDate(o.getValueDate());
       // doctors name
       if (o.getConcept().getUuid().equals("c2cb2220-c07d-47c6-a4df-e5918aac3fc2"))
         surgery.setPcpName(o.getValueText());
       // doctors email
       if (o.getConcept().getUuid().equals("898a0028-8c65-4db9-a802-1577fce59864"))
         surgery.setPcpEmail(o.getValueText());
       // doctors phone
       if (o.getConcept().getUuid().equals("9285b227-4054-4830-ac32-5ea78462e8c4"))
         surgery.setPcpPhone(o.getValueText());
       if (o.getConcept().getUuid().equals("47d58999-d3b5-4869-a52e-841e2e6bdbb3"))
         surgery.setInstitutionName(o.getValueText());
       if (o.getConcept().getUuid().equals("bfa752d6-2037-465e-b0a2-c4c2d485ec32"))
         surgery.setInstitutionCity(o.getValueText());
       if (o.getConcept().getUuid().equals("34489100-487e-443a-bf27-1b6869fb9332"))
         surgery.setInstitutionState(o.getValueText());
     }
     surgery.setSurgeryTypes(surgeryTypes);
     surgeriesList.add(surgery);
   }
   return surgeriesList;
 }
 /** @see java.util.Iterator#next() */
 public Map<String, Object> next() {
   Locale locale = Context.getLocale();
   Obs obs = iter.next();
   Map<String, Object> ret = new HashMap<String, Object>();
   ret.put("patientId", obs.getPersonId());
   ret.put("question", obs.getConcept().getName(locale, false));
   ret.put("questionConceptId", obs.getConcept().getConceptId());
   ret.put("answer", obs.getValueAsString(locale));
   if (obs.getValueCoded() != null) {
     ret.put("answerConceptId", obs.getValueCoded());
   }
   ret.put("obsDatetime", obs.getObsDatetime());
   if (obs.getEncounter() != null) {
     ret.put("encounterId", obs.getEncounter().getEncounterId());
   }
   if (obs.getObsGroup() != null) {
     ret.put("obsGroupId", obs.getObsGroup().getObsId());
   }
   return ret;
 }
 public static List<GeneralHistory> generateGeneralHistory(Patient patient) {
   List<Encounter> encounters =
       getEncountersByTreatment(patient, PatientPortalToolkitConstants.TREATMENTSUMMARY_ENCOUNTER);
   List<GeneralHistory> generalHistoryList = new ArrayList<GeneralHistory>();
   for (Encounter e : encounters) {
     GeneralHistory generalHistory = new GeneralHistory();
     generalHistory.setEncounterUuid(e.getUuid());
     Set<Obs> obsList = e.getObs();
     for (Obs o : obsList) {
       if (o.getConcept().getUuid().equals("efa3f9eb-ade4-4ddb-92c9-0fc1119d112d"))
         generalHistory.setCancerStage(o.getValueCoded().getName().getName());
       if (o.getConcept().getUuid().equals("cdf6d767-2aa3-40b6-ae78-0386eebe2411"))
         generalHistory.setCancerType(o.getValueCoded().getName().getName());
       if (o.getConcept().getUuid().equals("395878ae-5108-4aad-8ad8-9b88e812d278")) {
         if (o.getValueCoded().getUuid().equals("1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
           generalHistory.setHasGeneticOrPredisposingAbnormality(true);
         else generalHistory.setHasGeneticOrPredisposingAbnormality(false);
       }
       if (o.getConcept().getUuid().equals("8719adbe-0975-477f-a95f-2fae4d6cbdae"))
         generalHistory.setGeneticOrPredisposingAbnormality(o.getValueCoded().getName().getName());
       if (o.getConcept().getUuid().equals("654e32f0-8b57-4d1f-845e-500922e800f6"))
         generalHistory.setDiagnosisDate(o.getValueDate());
       // doctors name
       if (o.getConcept().getUuid().equals("c2cb2220-c07d-47c6-a4df-e5918aac3fc2"))
         generalHistory.setPcpName(o.getValueText());
       // doctors email
       if (o.getConcept().getUuid().equals("898a0028-8c65-4db9-a802-1577fce59864"))
         generalHistory.setPcpEmail(o.getValueText());
       // doctors phone
       if (o.getConcept().getUuid().equals("9285b227-4054-4830-ac32-5ea78462e8c4"))
         generalHistory.setPcpPhone(o.getValueText());
     }
     generalHistoryList.add(generalHistory);
   }
   return generalHistoryList;
 }
 Obs getLatestVlOrder(List<Obs> lstObs) {
   Obs latestObs = null;
   for (Obs o : lstObs) {
     if (o.getValueCoded() == Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD)) {
       if (latestObs == null) {
         latestObs = o;
       } else {
         if (o.getObsDatetime().after(latestObs.getObsDatetime())) {
           latestObs = o;
         }
       }
     }
   }
   return latestObs;
 }
  /**
   * Evaluates the calculation
   *
   * @should calculate false for deceased patients
   * @should calculate false for patients not in HIV program
   * @should calculate false for patients with an encounter in last LOST_TO_FOLLOW_UP_THRESHOLD_DAYS
   *     days days since appointment date
   * @should calculate true for patient with no encounter in last LOST_TO_FOLLOW_UP_THRESHOLD_DAYS
   *     days days since appointment date
   */
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort, Map<String, Object> arg1, PatientCalculationContext context) {

    Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);
    Concept reasonForDiscontinuation =
        Dictionary.getConcept(Dictionary.REASON_FOR_PROGRAM_DISCONTINUATION);
    Concept transferout = Dictionary.getConcept(Dictionary.TRANSFERRED_OUT);

    Set<Integer> alive = Filters.alive(cohort, context);
    Set<Integer> inHivProgram = Filters.inProgram(hivProgram, alive, context);

    // CalculationResultMap lastEncounters = Calculations.lastEncounter(null, inHivProgram,
    // context);
    CalculationResultMap lastReturnDateObss =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.RETURN_VISIT_DATE), inHivProgram, context);
    CalculationResultMap lastProgramDiscontinuation =
        Calculations.lastObs(reasonForDiscontinuation, cohort, context);

    CalculationResultMap ret = new CalculationResultMap();
    for (Integer ptId : cohort) {
      boolean lost = false;

      // Is patient alive and in the HIV program
      if (alive.contains(ptId)) {

        // Patient is lost if no encounters in last X days
        // Encounter lastEncounter = EmrCalculationUtils.encounterResultForPatient(lastEncounters,
        // ptId);
        Date lastScheduledReturnDate =
            EmrCalculationUtils.datetimeObsResultForPatient(lastReturnDateObss, ptId);
        Obs discontuation =
            EmrCalculationUtils.obsResultForPatient(lastProgramDiscontinuation, ptId);
        if (lastScheduledReturnDate != null) {
          if (daysSince(lastScheduledReturnDate, context)
              > HivConstants.LOST_TO_FOLLOW_UP_THRESHOLD_DAYS) {
            lost = true;
          }
          if (discontuation != null && discontuation.getValueCoded().equals(transferout)) {
            lost = false;
          }
        }
      }
      ret.put(ptId, new SimpleResult(lost, this, context));
    }
    return ret;
  }
Exemple #12
0
  /**
   * This is an equivalent to a copy constructor. Creates a new copy of the given <code>obsToCopy
   * </code> with a null obs id
   *
   * @param obsToCopy The Obs that is going to be copied
   * @return a new Obs object with all the same attributes as the given obs
   */
  public static Obs newInstance(Obs obsToCopy) {
    Obs newObs =
        new Obs(
            obsToCopy.getPerson(),
            obsToCopy.getConcept(),
            obsToCopy.getObsDatetime(),
            obsToCopy.getLocation());

    newObs.setObsGroup(obsToCopy.getObsGroup());
    newObs.setAccessionNumber(obsToCopy.getAccessionNumber());
    newObs.setValueCoded(obsToCopy.getValueCoded());
    newObs.setValueDrug(obsToCopy.getValueDrug());
    newObs.setValueGroupId(obsToCopy.getValueGroupId());
    newObs.setValueDatetime(obsToCopy.getValueDatetime());
    newObs.setValueNumeric(obsToCopy.getValueNumeric());
    newObs.setValueModifier(obsToCopy.getValueModifier());
    newObs.setValueText(obsToCopy.getValueText());
    newObs.setComment(obsToCopy.getComment());
    newObs.setOrder(obsToCopy.getOrder());
    newObs.setEncounter(obsToCopy.getEncounter());
    newObs.setDateStarted(obsToCopy.getDateStarted());
    newObs.setDateStopped(obsToCopy.getDateStopped());
    newObs.setCreator(obsToCopy.getCreator());
    newObs.setDateCreated(obsToCopy.getDateCreated());
    newObs.setVoided(obsToCopy.getVoided());
    newObs.setVoidedBy(obsToCopy.getVoidedBy());
    newObs.setDateVoided(obsToCopy.getDateVoided());
    newObs.setVoidReason(obsToCopy.getVoidReason());

    newObs.setValueComplex(obsToCopy.getValueComplex());
    newObs.setComplexData(obsToCopy.getComplexData());

    if (obsToCopy.getGroupMembers() != null)
      for (Obs member : obsToCopy.getGroupMembers()) {
        // if the obs hasn't been saved yet, no need to duplicate it
        if (member.getObsId() == null) newObs.addGroupMember(member);
        else newObs.addGroupMember(Obs.newInstance(member));
      }

    return newObs;
  }
  /**
   * Checks if any of the 'E' risk factors are present in the group obs.
   *
   * @param grp
   * @return
   */
  private boolean anyRiskFactorsTypeE(GroupObs grp) {
    final Concept yes = Functions.trueConcept();

    // check if any of the 'E' risk factors are present
    for (CachedConceptId rfEConceptId :
        new CachedConceptId[] {
          MCMedicalHistoryConcepts.TUBERCULOSIS, //
          MCMedicalHistoryConcepts.HEART_DISEASE, //
          MCMedicalHistoryConcepts.DIABETES, //
          MCMedicalHistoryConcepts.ASTHMA, //
          MCMedicalHistoryConcepts.THYROID
        }) {
      final Obs conditionObs = grp.getMember(rfEConceptId);
      if (conditionObs != null && yes.equals(conditionObs.getValueCoded())) {
        // risk factor 'E' is present
        return true;
      }
    }

    // risk factor 'E' not found in this group observation
    return false;
  }
 public static List<Radiation> generateRadiations(Patient patient) {
   List<Encounter> encounters =
       getEncountersByTreatment(patient, PatientPortalToolkitConstants.RADIATION_ENCOUNTER);
   List<Radiation> radiationsList = new ArrayList<Radiation>();
   for (Encounter e : encounters) {
     Radiation radiation = new Radiation();
     List<String> radiationTypes = new ArrayList<String>();
     Set<Obs> obsList = e.getObs();
     radiation.setEncounterUuid(e.getUuid());
     for (Obs o : obsList) {
       if (o.getConcept().getUuid().equals("42fb7bb5-f840-4518-814c-893813211cba"))
         radiationTypes.add(o.getValueCoded().getName().getName());
       if (o.getConcept().getUuid().equals("85c3a99e-0598-4c63-912b-796dee9c75b2"))
         radiation.setStartDate(o.getValueDate());
       if (o.getConcept().getUuid().equals("7dd8b8aa-b0f1-4eb1-862d-b6d737bdd315"))
         radiation.setEndDate(o.getValueDate());
       // doctors name
       if (o.getConcept().getUuid().equals("c2cb2220-c07d-47c6-a4df-e5918aac3fc2"))
         radiation.setPcpName(o.getValueText());
       // doctors email
       if (o.getConcept().getUuid().equals("898a0028-8c65-4db9-a802-1577fce59864"))
         radiation.setPcpEmail(o.getValueText());
       // doctors phone
       if (o.getConcept().getUuid().equals("9285b227-4054-4830-ac32-5ea78462e8c4"))
         radiation.setPcpPhone(o.getValueText());
       if (o.getConcept().getUuid().equals("47d58999-d3b5-4869-a52e-841e2e6bdbb3"))
         radiation.setInstitutionName(o.getValueText());
       if (o.getConcept().getUuid().equals("bfa752d6-2037-465e-b0a2-c4c2d485ec32"))
         radiation.setInstitutionCity(o.getValueText());
       if (o.getConcept().getUuid().equals("34489100-487e-443a-bf27-1b6869fb9332"))
         radiation.setInstitutionState(o.getValueText());
     }
     radiation.setRadiationTypes(radiationTypes);
     radiationsList.add(radiation);
   }
   return radiationsList;
 }
  /**
   * Adds the column headers and column data to the DataSet
   *
   * @param dataSet
   * @param encounters
   * @param patientIdentifierTypes
   * @param optionalColumns
   * @param columnDisplayFormat
   * @param maxColumnHeaderWidth
   * @param allColumns
   * @param fieldMap
   * @return
   */
  public DataSet addData(
      SimpleDataSet dataSet,
      List<Encounter> encounters,
      List<PatientIdentifierType> patientIdentifierTypes,
      List<EncounterAndObsDataSetDefinition.ObsOptionalColumn> optionalColumns,
      List<EncounterAndObsDataSetDefinition.ColumnDisplayFormat> columnDisplayFormat,
      Integer maxColumnHeaderWidth,
      Set<ObsColumnDescriptor> allColumns,
      Map<Encounter, Map<ObsColumnDescriptor, Obs>> fieldMap) {
    for (Encounter encounter : encounters) {

      DataSetRow row = new DataSetRow();

      List<String> providerNames = new ArrayList<String>();
      for (EncounterProvider ep : encounter.getEncounterProviders()) {
        providerNames.add(ep.getProvider().getName());
      }

      // Add the standard columns for encounters
      DataSetColumn c1 =
          new DataSetColumn(
              ObjectUtil.trimStringIfNeeded("ENCOUNTER_ID", maxColumnHeaderWidth),
              ObjectUtil.trimStringIfNeeded("ENCOUNTER_ID", maxColumnHeaderWidth),
              Integer.class);
      row.addColumnValue(c1, encounter.getEncounterId());
      DataSetColumn c2 =
          new DataSetColumn(
              ObjectUtil.trimStringIfNeeded("ENCOUNTER_DATETIME", maxColumnHeaderWidth),
              ObjectUtil.trimStringIfNeeded("ENCOUNTER_DATETIME", maxColumnHeaderWidth),
              String.class);
      row.addColumnValue(c2, encounter.getEncounterDatetime().toString());
      DataSetColumn c3 =
          new DataSetColumn(
              ObjectUtil.trimStringIfNeeded("LOCATION", maxColumnHeaderWidth),
              ObjectUtil.trimStringIfNeeded("LOCATION", maxColumnHeaderWidth),
              String.class);
      row.addColumnValue(
          c3, (encounter.getLocation() != null) ? encounter.getLocation().getName() : EMPTY);
      DataSetColumn c4 =
          new DataSetColumn(
              ObjectUtil.trimStringIfNeeded("PROVIDER", maxColumnHeaderWidth),
              ObjectUtil.trimStringIfNeeded("PROVIDER", maxColumnHeaderWidth),
              String.class);
      row.addColumnValue(c4, OpenmrsUtil.join(providerNames, ", "));
      DataSetColumn c5 =
          new DataSetColumn(
              ObjectUtil.trimStringIfNeeded("INTERNAL_PATIENT_ID", maxColumnHeaderWidth),
              ObjectUtil.trimStringIfNeeded("INTERNAL_PATIENT_ID", maxColumnHeaderWidth),
              Integer.class);
      row.addColumnValue(
          c5, encounter.getPatient() != null ? encounter.getPatient().getPatientId() : EMPTY);

      if (patientIdentifierTypes != null) {
        for (PatientIdentifierType pit : patientIdentifierTypes) {
          List<PatientIdentifier> patientIdentifiers =
              encounter.getPatient().getPatientIdentifiers(pit);

          StringBuffer sbPatientIdentifiers = new StringBuffer();
          int count = 0;
          for (PatientIdentifier patientIdentifier : patientIdentifiers) {
            if (count > 0) {
              sbPatientIdentifiers.append(", ");
            }
            sbPatientIdentifiers.append(patientIdentifier.toString());
            count++;
          }

          DataSetColumn c6 =
              new DataSetColumn(
                  pit.getName(),
                  ObjectUtil.trimStringIfNeeded(pit.getName(), maxColumnHeaderWidth),
                  String.class);
          row.addColumnValue(c6, sbPatientIdentifiers.toString());
        }
      }

      Map<ObsColumnDescriptor, Obs> obsInEncounter = fieldMap.get(encounter);

      // Look up all obs for a given encounter based on column headers for all encounters
      for (ObsColumnDescriptor columnKey : allColumns) {

        Obs obs = obsInEncounter.get(columnKey);
        String columnName = columnKey.format(columnDisplayFormat, maxColumnHeaderWidth);
        DataSetColumn obsDsc = new DataSetColumn(columnName, columnName, String.class);

        StringBuffer columnValue = new StringBuffer();
        if (obs != null && obs.getValueCoded() != null) {
          if (columnDisplayFormat.contains(
              EncounterAndObsDataSetDefinition.ColumnDisplayFormat.ID)) {
            columnValue.append(obs.getValueCoded());
          }

          if (columnDisplayFormat.contains(EncounterAndObsDataSetDefinition.ColumnDisplayFormat.ID)
              && columnDisplayFormat.contains(
                  EncounterAndObsDataSetDefinition.ColumnDisplayFormat.BEST_SHORT_NAME)) {
            columnValue.append("_");
          }

          if (columnDisplayFormat.contains(
              EncounterAndObsDataSetDefinition.ColumnDisplayFormat.BEST_SHORT_NAME)) {
            String conceptName = obs.getValueAsString(Context.getLocale());
            columnValue.append(
                maxColumnHeaderWidth != null
                        && conceptName.length() > maxColumnHeaderWidth - columnValue.length()
                    ? conceptName.substring(0, maxColumnHeaderWidth - columnValue.length() - 1)
                    : conceptName);
          }
          row.addColumnValue(obsDsc, (obs != null) ? columnValue.toString() : EMPTY);
        } else {
          row.addColumnValue(
              obsDsc, (obs != null) ? obs.getValueAsString(Context.getLocale()) : EMPTY);
        }

        String dateColumnName =
            columnKey.format(
                columnDisplayFormat,
                maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 5 : null);
        DataSetColumn obsDscDate =
            new DataSetColumn(dateColumnName + "_DATE", dateColumnName + "_DATE", String.class);
        row.addColumnValue(obsDscDate, (obs != null) ? obs.getObsDatetime().toString() : EMPTY);

        String parentColumnName =
            columnKey.format(
                columnDisplayFormat,
                maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 7 : null);
        DataSetColumn obsDscParent =
            new DataSetColumn(
                parentColumnName + "_PARENT", parentColumnName + "_PARENT", String.class);
        row.addColumnValue(
            obsDscParent,
            (obs != null && obs.getObsGroup() != null) ? obs.getObsGroup().getId() : EMPTY);

        if (optionalColumns != null) {

          if (optionalColumns.contains(
              EncounterAndObsDataSetDefinition.ObsOptionalColumn.VALUE_MODIFIER)) {
            String valModColumnName =
                columnKey.format(
                    columnDisplayFormat,
                    maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 10 : null);
            DataSetColumn obsDscValueModifier =
                new DataSetColumn(
                    valModColumnName + "_VALUE_MOD", valModColumnName + "_VALUE_MOD", String.class);
            row.addColumnValue(obsDscValueModifier, (obs != null) ? obs.getValueModifier() : EMPTY);
          }
          if (optionalColumns.contains(
              EncounterAndObsDataSetDefinition.ObsOptionalColumn.ACCESSION_NUMBER)) {
            String accessionNumColumnName =
                columnKey.format(
                    columnDisplayFormat,
                    maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 14 : null);
            DataSetColumn obsDscAccessionNumber =
                new DataSetColumn(
                    accessionNumColumnName + "_ACCESSION_NUM",
                    accessionNumColumnName + "_ACCESSION_NUM",
                    String.class);
            row.addColumnValue(
                obsDscAccessionNumber, (obs != null) ? obs.getAccessionNumber() : EMPTY);
          }
          if (optionalColumns.contains(
              EncounterAndObsDataSetDefinition.ObsOptionalColumn.COMMENT)) {
            String commentColumnName =
                columnKey.format(
                    columnDisplayFormat,
                    maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 8 : null);
            DataSetColumn obsDscComment =
                new DataSetColumn(
                    commentColumnName + "_COMMENT", commentColumnName + "_COMMENT", String.class);
            row.addColumnValue(obsDscComment, (obs != null) ? obs.getComment() : EMPTY);
          }
        }
      }

      dataSet.addRow(row);
    }
    return dataSet;
  }
  /**
   * This method produces a model containing the following mappings:
   *
   * <pre>
   *     (always)
   *          (java.util.Date) now
   *          (String) size
   *          (Locale) locale
   *          (String) portletUUID // unique for each instance of any portlet
   *          (other parameters)
   *     (if there's currently an authenticated user)
   *          (User) authenticatedUser
   *     (if the request has a patientId attribute)
   *          (Integer) patientId
   *          (Patient) patient
   *          (List<Obs>) patientObs
   *          (List<Encounter>) patientEncounters
   *          (List<DrugOrder>) patientDrugOrders
   *          (List<DrugOrder>) currentDrugOrders
   *          (List<DrugOrder>) completedDrugOrders
   *          (Obs) patientWeight // most recent weight obs
   *          (Obs) patientHeight // most recent height obs
   *          (Double) patientBmi // BMI derived from most recent weight and most recent height
   *          (String) patientBmiAsString // BMI rounded to one decimal place, or "?" if unknown
   *          (Integer) personId
   *          (if the patient has any obs for the concept in the global property 'concept.reasonExitedCare')
   *              (Obs) patientReasonForExit
   *     (if the request has a personId or patientId attribute)
   *          (Person) person
   *          (List<Relationship>) personRelationships
   *          (Map<RelationshipType, List<Relationship>>) personRelationshipsByType
   *     (if the request has an encounterId attribute)
   *          (Integer) encounterId
   *          (Encounter) encounter
   *          (Set<Obs>) encounterObs
   *     (if the request has a userId attribute)
   *          (Integer) userId
   *          (User) user
   *     (if the request has a patientIds attribute, which should be a (String) comma-separated list of patientIds)
   *          (PatientSet) patientSet
   *          (String) patientIds
   *     (if the request has a conceptIds attribute, which should be a (String) commas-separated list of conceptIds)
   *          (Map<Integer, Concept>) conceptMap
   *          (Map<String, Concept>) conceptMapByStringIds
   * </pre>
   *
   * @should calculate bmi into patientBmiAsString
   * @should not fail with empty height and weight properties
   */
  @SuppressWarnings("unchecked")
  public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    AdministrationService as = Context.getAdministrationService();
    ConceptService cs = Context.getConceptService();

    // find the portlet that was identified in the openmrs:portlet taglib
    Object uri = request.getAttribute("javax.servlet.include.servlet_path");
    String portletPath = "";
    Map<String, Object> model = null;
    {
      HttpSession session = request.getSession();
      String uniqueRequestId = (String) request.getAttribute(WebConstants.INIT_REQ_UNIQUE_ID);
      String lastRequestId =
          (String) session.getAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID);
      if (uniqueRequestId.equals(lastRequestId)) {
        model =
            (Map<String, Object>) session.getAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL);

        // remove cached parameters
        List<String> parameterKeys = (List<String>) model.get("parameterKeys");
        for (String key : parameterKeys) {
          model.remove(key);
        }
      }
      if (model == null) {
        log.debug("creating new portlet model");
        model = new HashMap<String, Object>();
        session.setAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID, uniqueRequestId);
        session.setAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL, model);
      }
    }

    if (uri != null) {
      long timeAtStart = System.currentTimeMillis();
      portletPath = uri.toString();

      // Allowable extensions are '' (no extension) and '.portlet'
      if (portletPath.endsWith("portlet")) portletPath = portletPath.replace(".portlet", "");
      else if (portletPath.endsWith("jsp"))
        throw new ServletException(
            "Illegal extension used for portlet: '.jsp'. Allowable extensions are '' (no extension) and '.portlet'");

      log.debug("Loading portlet: " + portletPath);

      String id = (String) request.getAttribute("org.openmrs.portlet.id");
      String size = (String) request.getAttribute("org.openmrs.portlet.size");
      Map<String, Object> params =
          (Map<String, Object>) request.getAttribute("org.openmrs.portlet.parameters");
      Map<String, Object> moreParams =
          (Map<String, Object>) request.getAttribute("org.openmrs.portlet.parameterMap");

      model.put("now", new Date());
      model.put("id", id);
      model.put("size", size);
      model.put("locale", Context.getLocale());
      model.put("portletUUID", UUID.randomUUID().toString().replace("-", ""));
      List<String> parameterKeys = new ArrayList<String>(params.keySet());
      model.putAll(params);
      if (moreParams != null) {
        model.putAll(moreParams);
        parameterKeys.addAll(moreParams.keySet());
      }
      model.put("parameterKeys", parameterKeys); // so we can clean these up in the next request

      // if there's an authenticated user, put them, and their patient set, in the model
      if (Context.getAuthenticatedUser() != null) {
        model.put("authenticatedUser", Context.getAuthenticatedUser());
      }

      Integer personId = null;

      // if a patient id is available, put patient data documented above in the model
      Object o = request.getAttribute("org.openmrs.portlet.patientId");
      if (o != null) {
        String patientVariation = "";
        Integer patientId = (Integer) o;
        if (!model.containsKey("patient")) {
          // we can't continue if the user can't view patients
          if (Context.hasPrivilege(PrivilegeConstants.VIEW_PATIENTS)) {
            Patient p = Context.getPatientService().getPatient(patientId);
            model.put("patient", p);

            // add encounters if this user can view them
            if (Context.hasPrivilege(PrivilegeConstants.VIEW_ENCOUNTERS))
              model.put(
                  "patientEncounters", Context.getEncounterService().getEncountersByPatient(p));

            if (Context.hasPrivilege(PrivilegeConstants.VIEW_OBS)) {
              List<Obs> patientObs = Context.getObsService().getObservationsByPerson(p);
              model.put("patientObs", patientObs);
              Obs latestWeight = null;
              Obs latestHeight = null;
              String bmiAsString = "?";
              try {
                String weightString = as.getGlobalProperty("concept.weight");
                ConceptNumeric weightConcept = null;
                if (StringUtils.hasLength(weightString))
                  weightConcept =
                      cs.getConceptNumeric(
                          cs.getConcept(Integer.valueOf(weightString)).getConceptId());
                String heightString = as.getGlobalProperty("concept.height");
                ConceptNumeric heightConcept = null;
                if (StringUtils.hasLength(heightString))
                  heightConcept =
                      cs.getConceptNumeric(
                          cs.getConcept(Integer.valueOf(heightString)).getConceptId());
                for (Obs obs : patientObs) {
                  if (obs.getConcept().equals(weightConcept)) {
                    if (latestWeight == null
                        || obs.getObsDatetime().compareTo(latestWeight.getObsDatetime()) > 0)
                      latestWeight = obs;
                  } else if (obs.getConcept().equals(heightConcept)) {
                    if (latestHeight == null
                        || obs.getObsDatetime().compareTo(latestHeight.getObsDatetime()) > 0)
                      latestHeight = obs;
                  }
                }
                if (latestWeight != null) model.put("patientWeight", latestWeight);
                if (latestHeight != null) model.put("patientHeight", latestHeight);
                if (latestWeight != null && latestHeight != null) {
                  double weightInKg;
                  double heightInM;
                  if (weightConcept.getUnits().equals("kg"))
                    weightInKg = latestWeight.getValueNumeric();
                  else if (weightConcept.getUnits().equals("lb"))
                    weightInKg = latestWeight.getValueNumeric() * 0.45359237;
                  else
                    throw new IllegalArgumentException(
                        "Can't handle units of weight concept: " + weightConcept.getUnits());
                  if (heightConcept.getUnits().equals("cm"))
                    heightInM = latestHeight.getValueNumeric() / 100;
                  else if (heightConcept.getUnits().equals("m"))
                    heightInM = latestHeight.getValueNumeric();
                  else if (heightConcept.getUnits().equals("in"))
                    heightInM = latestHeight.getValueNumeric() * 0.0254;
                  else
                    throw new IllegalArgumentException(
                        "Can't handle units of height concept: " + heightConcept.getUnits());
                  double bmi = weightInKg / (heightInM * heightInM);
                  model.put("patientBmi", bmi);
                  String temp = "" + bmi;
                  bmiAsString = temp.substring(0, temp.indexOf('.') + 2);
                }
              } catch (Exception ex) {
                if (latestWeight != null && latestHeight != null)
                  log.error(
                      "Failed to calculate BMI even though a weight and height were found", ex);
              }
              model.put("patientBmiAsString", bmiAsString);
            } else {
              model.put("patientObs", new HashSet<Obs>());
            }

            // information about whether or not the patient has exited care
            Obs reasonForExitObs = null;
            String reasonForExitConceptString = as.getGlobalProperty("concept.reasonExitedCare");
            if (StringUtils.hasLength(reasonForExitConceptString)) {
              Concept reasonForExitConcept = cs.getConcept(reasonForExitConceptString);
              if (reasonForExitConcept != null) {
                List<Obs> patientExitObs =
                    Context.getObsService()
                        .getObservationsByPersonAndConcept(p, reasonForExitConcept);
                if (patientExitObs != null) {
                  log.debug("Exit obs is size " + patientExitObs.size());
                  if (patientExitObs.size() == 1) {
                    reasonForExitObs = patientExitObs.iterator().next();
                    Concept exitReason = reasonForExitObs.getValueCoded();
                    Date exitDate = reasonForExitObs.getObsDatetime();
                    if (exitReason != null && exitDate != null) {
                      patientVariation = "Exited";
                    }
                  } else {
                    if (patientExitObs.size() == 0) {
                      log.debug("Patient has no reason for exit");
                    } else {
                      log.error("Too many reasons for exit - not putting data into model");
                    }
                  }
                }
              }
            }
            model.put("patientReasonForExit", reasonForExitObs);

            if (Context.hasPrivilege(PrivilegeConstants.VIEW_ORDERS)) {
              List<DrugOrder> drugOrderList = Context.getOrderService().getDrugOrdersByPatient(p);
              model.put("patientDrugOrders", drugOrderList);
              List<DrugOrder> currentDrugOrders = new ArrayList<DrugOrder>();
              List<DrugOrder> discontinuedDrugOrders = new ArrayList<DrugOrder>();
              Date rightNow = new Date();
              for (Iterator<DrugOrder> iter = drugOrderList.iterator(); iter.hasNext(); ) {
                DrugOrder next = iter.next();
                if (next.isCurrent() || next.isFuture()) currentDrugOrders.add(next);
                if (next.isDiscontinued(rightNow)) discontinuedDrugOrders.add(next);
              }
              model.put("currentDrugOrders", currentDrugOrders);
              model.put("completedDrugOrders", discontinuedDrugOrders);

              List<RegimenSuggestion> standardRegimens =
                  Context.getOrderService().getStandardRegimens();
              if (standardRegimens != null) model.put("standardRegimens", standardRegimens);
            }

            if (Context.hasPrivilege(PrivilegeConstants.VIEW_PROGRAMS)
                && Context.hasPrivilege(PrivilegeConstants.VIEW_PATIENT_PROGRAMS)) {
              model.put(
                  "patientPrograms",
                  Context.getProgramWorkflowService()
                      .getPatientPrograms(p, null, null, null, null, null, false));
              model.put(
                  "patientCurrentPrograms",
                  Context.getProgramWorkflowService()
                      .getPatientPrograms(p, null, null, new Date(), new Date(), null, false));
            }

            model.put("patientId", patientId);
            if (p != null) {
              personId = p.getPatientId();
              model.put("personId", personId);
            }

            model.put("patientVariation", patientVariation);
          }
        }
      }

      // if a person id is available, put person and relationships in the model
      if (personId == null) {
        o = request.getAttribute("org.openmrs.portlet.personId");
        if (o != null) {
          personId = (Integer) o;
          model.put("personId", personId);
        }
      }
      if (personId != null) {
        if (!model.containsKey("person")) {
          Person p = (Person) model.get("patient");
          if (p == null) p = Context.getPersonService().getPerson(personId);
          model.put("person", p);

          if (Context.hasPrivilege(PrivilegeConstants.VIEW_RELATIONSHIPS)) {
            List<Relationship> relationships = new ArrayList<Relationship>();
            relationships.addAll(Context.getPersonService().getRelationshipsByPerson(p));
            Map<RelationshipType, List<Relationship>> relationshipsByType =
                new HashMap<RelationshipType, List<Relationship>>();
            for (Relationship rel : relationships) {
              List<Relationship> list = relationshipsByType.get(rel.getRelationshipType());
              if (list == null) {
                list = new ArrayList<Relationship>();
                relationshipsByType.put(rel.getRelationshipType(), list);
              }
              list.add(rel);
            }

            model.put("personRelationships", relationships);
            model.put("personRelationshipsByType", relationshipsByType);
          }
        }
      }

      // if an encounter id is available, put "encounter" and "encounterObs" in the model
      o = request.getAttribute("org.openmrs.portlet.encounterId");
      if (o != null && !model.containsKey("encounterId")) {
        if (!model.containsKey("encounter")) {
          if (Context.hasPrivilege(PrivilegeConstants.VIEW_ENCOUNTERS)) {
            Encounter e = Context.getEncounterService().getEncounter((Integer) o);
            model.put("encounter", e);
            if (Context.hasPrivilege(PrivilegeConstants.VIEW_OBS))
              model.put("encounterObs", e.getObs());
          }
          model.put("encounterId", (Integer) o);
        }
      }

      // if a user id is available, put "user" in the model
      o = request.getAttribute("org.openmrs.portlet.userId");
      if (o != null) {
        if (!model.containsKey("user")) {
          if (Context.hasPrivilege(PrivilegeConstants.VIEW_USERS)) {
            User u = Context.getUserService().getUser((Integer) o);
            model.put("user", u);
          }
          model.put("userId", (Integer) o);
        }
      }

      // if a list of patient ids is available, make a patientset out of it
      o = request.getAttribute("org.openmrs.portlet.patientIds");
      if (o != null && !"".equals(o) && !model.containsKey("patientIds")) {
        if (!model.containsKey("patientSet")) {
          Cohort ps = new Cohort((String) o);
          model.put("patientSet", ps);
          model.put("patientIds", (String) o);
        }
      }

      o = model.get("conceptIds");
      if (o != null && !"".equals(o)) {
        if (!model.containsKey("conceptMap")) {
          log.debug("Found conceptIds parameter: " + o);
          Map<Integer, Concept> concepts = new HashMap<Integer, Concept>();
          Map<String, Concept> conceptsByStringIds = new HashMap<String, Concept>();
          String conceptIds = (String) o;
          String[] ids = conceptIds.split(",");
          for (String cId : ids) {
            try {
              Integer i = Integer.valueOf(cId);
              Concept c = cs.getConcept(i);
              concepts.put(i, c);
              conceptsByStringIds.put(i.toString(), c);
            } catch (Exception ex) {
            }
          }
          model.put("conceptMap", concepts);
          model.put("conceptMapByStringIds", conceptsByStringIds);
        }
      }

      populateModel(request, model);
      log.debug(portletPath + " took " + (System.currentTimeMillis() - timeAtStart) + " ms");
    }

    return new ModelAndView(portletPath, "model", model);
  }
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort,
      Map<String, Object> parameterValues,
      PatientCalculationContext context) {
    Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);

    Set<Integer> alive = Filters.alive(cohort, context);
    Set<Integer> inHivProgram = Filters.inProgram(hivProgram, alive, context);

    Set<Integer> aliveAndFemale = Filters.female(Filters.alive(cohort, context), context);

    CalculationResultMap ret = new CalculationResultMap();

    // need to exclude those on ART already
    Set<Integer> onArt =
        CalculationUtils.patientsThatPass(calculate(new OnArtCalculation(), cohort, context));
    // find the observation for viral load recorded
    CalculationResultMap viralLoad =
        Calculations.lastObs(Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD), cohort, context);
    // get a list of all the viral load
    CalculationResultMap viralLoadList =
        Calculations.allObs(Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD), cohort, context);
    // check for non detectables
    CalculationResultMap ldlViralLoad =
        Calculations.allObs(
            Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD_QUALITATIVE), cohort, context);

    // check for test orders
    CalculationResultMap testOrders =
        Calculations.allObs(Dictionary.getConcept(Dictionary.TESTS_ORDERED), cohort, context);

    // check for last ldl
    CalculationResultMap ldlLast =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD_QUALITATIVE), cohort, context);

    // find for prgnant females

    CalculationResultMap pregStatusObss =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.PREGNANCY_STATUS), aliveAndFemale, context);

    // get the initial art start date
    CalculationResultMap artStartDate =
        calculate(new InitialArtStartDateCalculation(), cohort, context);

    for (Integer ptId : cohort) {
      boolean needsViralLoadTest = false;
      Obs viralLoadObs = EmrCalculationUtils.obsResultForPatient(viralLoad, ptId);
      Date dateInitiated = EmrCalculationUtils.datetimeResultForPatient(artStartDate, ptId);
      ListResult listResult = (ListResult) viralLoadList.get(ptId);
      ListResult testOrdersList = (ListResult) testOrders.get(ptId);
      List<Obs> testObsList = CalculationUtils.extractResultValues(testOrdersList);
      List<Obs> listObsViralLoads = CalculationUtils.extractResultValues(listResult);
      ListResult ldlList = (ListResult) ldlViralLoad.get(ptId);
      List<List> listLdl = CalculationUtils.extractResultValues(ldlList);
      Obs lastLdlObs = EmrCalculationUtils.obsResultForPatient(ldlLast, ptId);
      // find pregnancy obs
      Obs pregnantEdd = EmrCalculationUtils.obsResultForPatient(pregStatusObss, ptId);

      // Find latest viral load test order
      Obs lastVlTestOrder = getLatestVlOrder(testObsList);

      if (inHivProgram.contains(ptId) && onArt.contains(ptId)) {
        if (listObsViralLoads.size() == 0
            && listLdl.size() == 0
            && dateInitiated != null
            && (daysSince(dateInitiated, context) >= 180)) {
          needsViralLoadTest = true;
        }
        // need to check here if patient has had any viral load
        /*if(dateInitiated != null && (daysSince(dateInitiated, context) >= 360)) {
            needsViralLoadTest = true;
        }*/

        // those continuing should receive one VL every year
        // pick the date of the last viral load numeric values
        if (viralLoadObs != null && (daysSince(viralLoadObs.getObsDatetime(), context) >= 360)) {
          needsViralLoadTest = true;
        }
        // pick the date of the ldl
        if (lastLdlObs != null && (daysSince(lastLdlObs.getObsDatetime(), context) >= 360)) {
          needsViralLoadTest = true;
        }

        // if vl more than
        if (viralLoadObs != null
            && viralLoadObs.getValueNumeric() > 1000
            && (daysSince(viralLoadObs.getObsDatetime(), context) > 90)) {
          needsViralLoadTest = true;

          if (lastLdlObs != null && (daysSince(lastLdlObs.getObsDatetime(), context) < 360)) {
            needsViralLoadTest = false;
          }
        }

        // check for pregnancy
        if (pregnantEdd != null
            && pregnantEdd.getValueCoded().equals(Dictionary.getConcept(Dictionary.YES))
            && dateInitiated != null) {
          Date whenVLWillBeDue =
              DateUtil.adjustDate(
                  DateUtil.adjustDate(dateInitiated, 6, DurationUnit.MONTHS),
                  -1,
                  DurationUnit.DAYS);
          // if last vl is 6 months older then the patient is due for vl
          if (viralLoadObs == null && lastLdlObs == null) {
            needsViralLoadTest = true;
          }
          if (viralLoadObs == null
              && lastLdlObs == null
              && (context.getNow().after(whenVLWillBeDue))) {
            needsViralLoadTest = true;
          }
          if (viralLoadObs != null
              && viralLoadObs.getValueNumeric() > 1000
              && (monthsBetween(viralLoadObs.getObsDatetime(), context.getNow()) >= 3)) {
            needsViralLoadTest = true;
            if (lastLdlObs != null && (daysSince(lastLdlObs.getObsDatetime(), context) < 360)) {
              needsViralLoadTest = false;
            }
          }
          if (viralLoadObs != null && daysSince(viralLoadObs.getObsDatetime(), context) >= 180) {
            needsViralLoadTest = true;
          }
          if (lastLdlObs != null && daysSince(lastLdlObs.getObsDatetime(), context) >= 180) {
            needsViralLoadTest = true;
          }
        }

        // check if has vl test order within 6 months
        if (lastVlTestOrder != null
            && daysSince(lastVlTestOrder.getObsDatetime(), context) >= 180) {
          needsViralLoadTest = true;
        }

        if (lastVlTestOrder != null && daysSince(lastVlTestOrder.getObsDatetime(), context) < 180) {
          needsViralLoadTest = false;
        }
      }

      ret.put(ptId, new BooleanResult(needsViralLoadTest, this));
    }
    return ret;
  }
  /**
   * @param omrsPatient
   * @param omrsPerson
   * @throws APIException
   * @throws Exception
   */
  public void processDrugOrders(Patient omrsPatient) throws APIException, Exception {
    org.openmrs.Person omrsPerson = Context.getPersonService().getPerson(omrsPatient.getPersonId());
    @SuppressWarnings("deprecation")
    List<DrugOrder> drugOrders = Context.getOrderService().getDrugOrdersByPatient(omrsPatient);
    if (drugOrders != null) {
      /*
       * Check if the drug order fulfills the combination of 3 or more
       * drugs per regimen
       */
      if (drugOrders.size() >= MIN_DRUGS_IN_A_REGIMEN) {
        // Construct the regimen from drug orders
        String regimen = "";
        Date drugStartDate = null; // Capture the regimen start date
        for (DrugOrder drugOrder : drugOrders) {
          drugStartDate = drugOrder.getStartDate();
          regimen += drugOrder.getConcept().getShortNameInLocale(Locale.ENGLISH).getName() + "/";
        }
        // Truncate the trailing "/" from the regimen string
        regimen = regimen.substring(0, regimen.length() - 1);

        // check the ARV plan
        // 1255=> ARV Plan
        Concept arvPlanConcept = Context.getConceptService().getConcept(ARV_PLAN_CONCEPT_ID);

        // 1256 => start drugs
        Concept startDrugsConcept = Context.getConceptService().getConcept(START_DRUGS_CONCEPT_ID);
        // 1259 => Change Regimen
        Concept changeRegimenConcept =
            Context.getConceptService().getConcept(CHANGE_REGIMEN_CONCEPT_ID);

        List<Obs> lastArvPlanObsList =
            Context.getObsService()
                .getObservations(
                    Collections.singletonList(omrsPerson),
                    null,
                    Collections.singletonList(arvPlanConcept),
                    null,
                    null,
                    null,
                    null,
                    1,
                    null,
                    null,
                    null,
                    false);
        if (lastArvPlanObsList != null) {
          if (lastArvPlanObsList.size() > 0) {
            AppProperties appProperties =
                new AppPropertiesLoader(new AppProperties()).getAppProperties();
            Person oecPerson = new Person();
            List<OruFiller> fillers = new ArrayList<OruFiller>();
            OruFiller oruFiller = new OruFiller();
            Obs lastArvPlanObs = lastArvPlanObsList.get(0);
            OruFillerMapper oruFillerMapper = new OruFillerMapper(lastArvPlanObs, oruFiller);
            HashSet<PersonIdentifier> patientIds =
                new PatientIdsMapper(omrsPatient).getPatientIds();
            PersonMapper personMapper = new PersonMapper(omrsPatient, oecPerson);
            personMapper.mapPatient(patientIds);
            oruFiller.setCodingSystem(
                (String) appProperties.getProperty(CODING_SYSTEM_PROPERTY_NAME));
            Boolean proceed = true;
            if (lastArvPlanObs.getValueCoded().equals(startDrugsConcept)) {
              oruFillerMapper.setEvent(Event.FIRST_LINE_REGIMEN.getValue());
              fillers.add(oruFillerMapper.getOruFiller());
              oruFillerMapper.mapObs(regimen);

            } else if (lastArvPlanObs.getValueCoded().equals(changeRegimenConcept)) {
              oruFillerMapper.setEvent(Event.SECOND_LINE_REGIMEN.getValue());
              fillers.add(oruFillerMapper.getOruFiller());
              oruFillerMapper.mapObs(regimen);
            } else {
              proceed = false;
            }
            oruFillerMapper.getOruFiller().setDateTimeOfObservation(sdf.format(drugStartDate));
            if (proceed) {
              try {
                EventsHl7Service eventsHl7Service =
                    new EventsHl7Service(personMapper.getOecPerson(), fillers, appProperties);
                eventsHl7Service.doWork(Triggers.R01.getValue());
              } catch (Exception ex) {
                log.debug(ex);
                System.out.println("Unable to send HL7 message: " + ex.getMessage());
              }
            }
          }
        }
      }
    }
  }
  @RequestMapping(method = RequestMethod.GET)
  public String showPatientInfo(
      @RequestParam("patientId") Integer patientId,
      @RequestParam(value = "encounterId", required = false) Integer encounterId,
      @RequestParam(value = "reprint", required = false) Boolean reprint,
      Model model)
      throws IOException, ParseException {

    Patient patient = Context.getPatientService().getPatient(patientId);
    PatientModel patientModel = new PatientModel(patient);
    model.addAttribute("patient", patientModel);
    model.addAttribute(
        "OPDs", RegistrationWebUtils.getSubConcepts(RegistrationConstants.CONCEPT_NAME_OPD_WARD));

    // Get current date
    SimpleDateFormat sdf = new SimpleDateFormat("EEE dd/MM/yyyy kk:mm");
    model.addAttribute("currentDateTime", sdf.format(new Date()));

    // Get patient registration fee
    if (GlobalPropertyUtil.getInteger(RegistrationConstants.PROPERTY_NUMBER_OF_DATE_VALIDATION, 0)
        > 0) {
      List<RegistrationFee> fees =
          Context.getService(RegistrationService.class)
              .getRegistrationFees(
                  patient,
                  GlobalPropertyUtil.getInteger(
                      RegistrationConstants.PROPERTY_NUMBER_OF_DATE_VALIDATION, 0));
      if (!CollectionUtils.isEmpty(fees)) {
        RegistrationFee fee = fees.get(0);
        Calendar dueDate = Calendar.getInstance();
        dueDate.setTime(fee.getCreatedOn());
        dueDate.add(Calendar.DATE, 30);
        model.addAttribute("dueDate", RegistrationUtils.formatDate(dueDate.getTime()));
        model.addAttribute("daysLeft", dateDiff(dueDate.getTime(), new Date()));
      }
    }

    // Get selected OPD room if this is the first time of visit
    if (encounterId != null) {
      Encounter encounter = Context.getEncounterService().getEncounter(encounterId);
      for (Obs obs : encounter.getObs()) {
        if (obs.getConcept()
            .getName()
            .getName()
            .equalsIgnoreCase(RegistrationConstants.CONCEPT_NAME_OPD_WARD)) {
          model.addAttribute("selectedOPD", obs.getValueCoded().getConceptId());
        }
      }
    }

    // If reprint, get the latest registration encounter
    if ((reprint != null) && reprint) {

      /** June 7th 2012 - Supported #250 - Registration 2.2.14 (Mohali): Date on Reprint */
      HospitalCoreService hcs = Context.getService(HospitalCoreService.class);
      model.addAttribute("currentDateTime", sdf.format(hcs.getLastVisitTime(patientId)));

      Encounter encounter = Context.getService(RegistrationService.class).getLastEncounter(patient);
      if (encounter != null) {
        Map<Integer, String> observations = new HashMap<Integer, String>();

        for (Obs obs : encounter.getAllObs()) {
          if (obs.getConcept()
              .getDisplayString()
              .equalsIgnoreCase(RegistrationConstants.CONCEPT_NAME_TEMPORARY_CATEGORY)) {
            model.addAttribute("tempCategoryId", obs.getConcept().getConceptId());
          } else if (obs.getConcept()
              .getDisplayString()
              .equalsIgnoreCase(RegistrationConstants.CONCEPT_NAME_OPD_WARD)) {
            model.addAttribute("opdWardId", obs.getConcept().getConceptId());
          }
          observations.put(obs.getConcept().getConceptId(), ObsUtils.getValueAsString(obs));
        }
        model.addAttribute("observations", observations);
      }
    }

    return "/module/registration/patient/showPatientInfo";
  }