package org.msh.tb.cases; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.core.Expressions; import org.msh.tb.ETB; import org.msh.tb.application.App; import org.msh.tb.entities.*; import org.msh.tb.entities.enums.*; import org.msh.tb.login.UserSession; import org.msh.utils.EntityQuery; import org.msh.utils.date.Period; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; // 02.04.2012 Change some from public to to protected Alexey Kurasov /** * Return the result search of cases based on the filters defined in {@link CaseFilters} * @author Ricardo Memoria * */ @Name("cases") @BypassInterceptors public class CasesQuery extends EntityQuery { private static final long serialVersionUID = 7867819205241149388L; protected CaseFilters caseFilters; private Workspace defaultWorkspace; protected List resultList; protected String hqlCondition; private boolean loadCaseData = false; private static final String[] orderValues = {"p.recordNumber, c.caseNumber", "p.gender,p.name", "c.classification", "#{cases.namesOrderBy}", "c.age", "upper(nu.name.name1)", "c.notifAddress.adminUnit.parent.name.name1", "c.notifAddress.adminUnit.name.name1", "c.state", "c.registrationDate", "c.treatmentPeriod.iniDate", "c.validationState"}; private static final String[] inverseOrderValues = {"p.recordNumber desc, c.caseNumber", "p.gender desc, upper(p.name) desc, upper(p.middleName) desc, upper(p.lastName) desc", "c.classification desc", "#{cases.namesOrderBy}", "c.age desc", "upper(nu.name.name1) desc", "c.notifAddress.adminUnit.parent.name.name1 desc", "c.notifAddress.adminUnit.name.name1 desc", "c.state desc", "c.registrationDate desc", "c.treatmentPeriod.iniDate desc", "c.validationState desc"}; // static filters private static final String[] restrictions = {/*"nu.id = #{caseFilters.tbunit.id}",*/ /*"p.recordNumber = #{caseFilters.recordNumber}", */ // just search by recordNumber if workspace.displayCaseNumber = RECORD_NUMBER // "p.recordNumber = #{caseFilters.patientRecordNumber}", //"c.registrationCode = #{caseFilters.registrationCode}", "c.unitRegCode = #{caseFilters.unitRegCode}", //"c.caseNumber = #{caseFilters.caseNumber}", "p.workspace.id = #{defaultWorkspace.id}", "c.state = #{caseFilters.caseState}", "c.notifAddress.adminUnit.code like #{caseFilters.adminUnitLike}", "c.classification = #{caseFilters.classification}", "upper(p.name) like #{caseFilters.nameLike}", "upper(p.middleName) like #{caseFilters.middleNameLike}", "upper(p.lastName) like #{caseFilters.lastNameLike}", "c.patientType = #{caseFilters.patientType}", "c.previouslyTreatedType = #{caseFilters.previouslyTreatedType}", "c.infectionSite = #{caseFilters.infectionSite}", "c.diagnosisType = #{caseFilters.diagnosisType}", "c.validationState = #{caseFilters.validationState}", "nu.healthSystem.id = #{userWorkspace.healthSystem.id}", "year(p.birthDate) = #{caseFilters.birthYear}", "c.drugResistanceType = #{caseFilters.drugResistanceType}"}; protected static final String notifCond = "(nu.id = #{caseFilters.tbunitselection.tbunit.id})"; protected static final String treatCond = "c.ownerUnit.id = #{caseFilters.tbunitselection.tbunit.id}"; protected static final String notifRegCond = "(nu.adminUnit.code like #{caseFilters.tbAdminUnitLike})"; protected static final String treatRegCond = "c.ownerUnit.adminUnit.code like #{caseFilters.tbAdminUnitLike}"; private static final String prescribedMedicineCond = "exists(SELECT cs.id, pm.id " + "FROM " + ETB.getWsClassName(TbCase.class) + " cs " + "INNER JOIN cs.prescribedMedicines pm " + "WHERE pm.medicine.id = #{caseFilters.prescribedMedicine.id} " + "and c.id = cs.id)"; /* (non-Javadoc) * @see org.jboss.seam.framework.EntityQuery#getResultList() */ @Override public List getResultList() { if (caseFilters.getPatientType() != null && !caseFilters.getPatientType().equals(PatientType.PREVIOUSLY_TREATED)) { caseFilters.setPreviouslyTreatedType(null); } if (resultList == null) { javax.persistence.Query query = createQuery(); List lst = query == null ? null : query.getResultList(); fillResultList(lst); } return resultList; } /* (non-Javadoc) * @see org.jboss.seam.framework.Query#getEjbql() */ @Override public String getEjbql() { String select; if (loadCaseData) { select = "select c, 1 "; } else { select = "select p.name, c.age, p.gender, p.recordNumber, c.caseNumber, " + "c.treatmentPeriod.iniDate, c.registrationDate, nu.name.name1, " + "loc.name.name1, loc.code, c.id, " + "c.treatmentPeriod.endDate, c.state, c.classification, p.middleName, p.lastName, " + "c.validationState, c.registrationCode, c.diagnosisType, p.birthDate, c.diagnosisDate, c.outcomeDate "; } select = select + getFromHQL() + " join c.patient p " + "join c.notificationUnit nu " + "join c.notifAddress.adminUnit loc ".concat(dynamicConditions()); return select; } /* (non-Javadoc) * @see org.jboss.seam.framework.Query#getCountEjbql() */ @Override public String getCountEjbql() { caseFilters = getCaseFilters(); return "select count(*) " + getFromHQL() + " join c.patient p " + "join c.notificationUnit nu " + dynamicConditions(); } /** * Return join tables in use in this query * @return */ public String getFromHQL() { return "from " + ETB.getWsClassName(TbCase.class) + " c"; } /** * Generate HQL conditions for filters that cannot be included in the restrictions clause * @return */ protected String dynamicConditions() { if (hqlCondition != null) { return hqlCondition; } hqlCondition = ""; FilterHealthUnit filterUnit = getCaseFilters().getFilterHealthUnit(); // health unit condition if (filterUnit != null) { // health unit was set ? if (getCaseFilters().getTbunitselection().getSelected() != null) { switch (filterUnit) { case NOTIFICATION_UNIT: addCondition(notifCond); break; case TREATMENT_UNIT: addCondition(treatCond); break; case BOTH: addCondition("(" + treatCond + " or " + notifCond + ")"); } } else // region was set ? if (getCaseFilters().getTbunitselection().getAdminUnit() != null) { switch (filterUnit) { case NOTIFICATION_UNIT: addCondition(notifRegCond); break; case TREATMENT_UNIT: //AM: Split condition because of null pointer exception can arise in some cases if (caseFilters.getStateIndex() == null && caseFilters.getSearchCriteria().equals(SearchCriteria.CASE_TAG)) addCondition(treatRegCond); if (caseFilters.getStateIndex() != null) if (caseFilters.getStateIndex() != CaseFilters.TRANSFER_OUT) addCondition(treatRegCond); break; case BOTH: addCondition("(" + treatRegCond + " or " + notifRegCond + ")"); } } } if (caseFilters.getPrescribedMedicine() != null && caseFilters.getPrescribedMedicine().getId() != 0) { addCondition(prescribedMedicineCond); } if (caseFilters.getClassifications().getSelectedItems().size() > 0) { String clas = " c.classification in ("; for (CaseClassification c : caseFilters.getClassifications().getSelectedItems()){ clas = clas + c.ordinal() + ","; } clas = clas.substring(0, clas.length() - 1); clas = clas + ")"; addCondition(clas); } if (caseFilters.getDiagnosisTypes().getSelectedItems().size() > 0) { String diagT = " c.diagnosisType in ("; for (DiagnosisType d : caseFilters.getDiagnosisTypes().getSelectedItems()){ diagT = diagT + d.ordinal() + ","; } diagT = diagT.substring(0, diagT.length() - 1); diagT = diagT + ")"; addCondition(diagT); } mountAdvancedSearchConditions(); mountSingleSearchConditions(); tagRestriction(); if (caseFilters.getMovedToSecLineReg() != null) { if (caseFilters.getMovedToSecLineReg().equals(YesNoType.NO)) { addCondition(" c.movedSecondLineTreatment = false"); } else if (caseFilters.getMovedToSecLineReg().equals(YesNoType.YES)) { addCondition(" c.movedSecondLineTreatment = true"); } } if (!hqlCondition.isEmpty()) hqlCondition = " where ".concat(hqlCondition); return hqlCondition; } protected void tagRestriction() { String unitRestriction = "c.ownerUnit.id = #{caseFilters.unitId}"; if (caseFilters.getTagid() == null) { if (caseFilters.getUnitId() != null) { addCondition(unitRestriction); } return; } Tag tag = getEntityManager().find(Tag.class, caseFilters.getTagid()); addCondition("exists(select t.id from c.tags t where t.id = #{caseFilters.tagid})"); if (tag.isAllCasesUnit()) { addCondition("exists(select hu.id from c.healthUnits hu where hu.tbunit.id = #{caseFilters.unitId})"); } else if (caseFilters.getUnitId() != null) { addCondition(unitRestriction); } } /** * Generate HQL instructions for advanced search conditions */ protected void mountAdvancedSearchConditions() { CaseFilters caseFilters = getCaseFilters(); // include filters by date Date dtIni = caseFilters.getIniDate(); Date dtEnd = caseFilters.getEndDate(); if ((dtIni != null) || (dtEnd != null)) { if (caseFilters.isDiagnosisDate()) { generateHQLPeriod(dtIni, dtEnd, "c.diagnosisDate"); } if (caseFilters.isOutcomeDate()) { generateHQLPeriod(dtIni, dtEnd, "c.outcomeDate"); } if (caseFilters.isIniTreatmentDate()) { generateHQLPeriod(dtIni, dtEnd, "c.treatmentPeriod.iniDate"); } if (caseFilters.isRegistrationDate()) generateHQLPeriod(dtIni, dtEnd, "c.registrationDate"); } String hql = generateHQLPatientNumber(caseFilters.getRecordNumber()); if (!hql.isEmpty()) addCondition( hql ); } /** * Generate HQL instructions for single search by patient name */ protected void mountSingleSearchConditions() { CaseFilters caseFilters = getCaseFilters(); if (caseFilters.getPatient() != null) { String numberCond = generateHQLPatientNumber(caseFilters.getPatient()); String[] names = caseFilters.getPatient().split(" "); if (names.length == 0) return; String s = "("; for (String name: names) { name = name.replaceAll("'", "''"); if (s.length() > 1) s += " and "; s += "((upper(p.name) like '%" + name.toUpperCase() + "%') or (upper(p.middleName) like '%" + name.toUpperCase() + "%') or (upper(p.lastName) like '%" + name.toUpperCase() + "%'))"; } addCondition(s + (numberCond.isEmpty() ? ")": " or (" + numberCond + "))")); } Integer stateIndex = caseFilters.getStateIndex(); if (stateIndex != null) { String cond = null; switch (stateIndex) { // CLOSED case CaseFilters.CLOSED: cond = "c.state >= " + Integer.toString( CaseState.CURED.ordinal() ); break; // SUSPECT NOT ON TREATMENT case CaseFilters.SUSPECT_NOT_ON_TREATMENT: cond = "c.state = " + CaseState.WAITING_TREATMENT.ordinal() + " and c.diagnosisType = " + DiagnosisType.SUSPECT.ordinal(); break; // SUSPECT ON TREATMENT case CaseFilters.SUSPECT_ON_TREATMENT: cond = "c.state = " + CaseState.ONTREATMENT.ordinal() + " and c.diagnosisType = " + DiagnosisType.SUSPECT.ordinal(); break; // CONFIRMED ON TREATMENT case CaseFilters.CONFIRMED_ON_TREATMENT: cond = "c.state = " + CaseState.ONTREATMENT.ordinal() + " and c.diagnosisType = " + DiagnosisType.CONFIRMED.ordinal(); break; // CONFIRMED NOT ON TREATMENT case CaseFilters.CONFIRMED_NOT_ON_TREATMENT: cond = "c.state = " + CaseState.WAITING_TREATMENT.ordinal() + " and c.diagnosisType = " + DiagnosisType.CONFIRMED.ordinal(); break; // WAIT TO START TREATMENT case CaseFilters.WAIT_FOR_TREATMENT: cond = "c.state = " + CaseState.WAITING_TREATMENT.ordinal(); break; // ON TREATMENT case CaseFilters.ON_TREATMENT: cond = "c.state = " + CaseState.ONTREATMENT.ordinal(); break; // ON TREATMENT - TRANSFERIN case CaseFilters.TRANSFER_IN: cond = "c.state = " + CaseState.ONTREATMENT.ordinal() + " and exists(select id from TreatmentHealthUnit t" + " where t.period.iniDate > c.treatmentPeriod.iniDate and period.endDate = c.treatmentPeriod.endDate and c.state= " + CaseState.ONTREATMENT.ordinal() + " and transferring=false and tbunit.id = "+ caseFilters.getUnitId() + " and tbcase.id = c.id)"; break; // ON TREATMENT / TRANSFERING - TRANSFEROUT case CaseFilters.TRANSFER_OUT: cond = " exists(select id from TreatmentHealthUnit t" + " where t.period.endDate < c.treatmentPeriod.endDate" + " and c.state in (" + CaseState.ONTREATMENT.ordinal() + "," + CaseState.TRANSFERRING.ordinal() + ")" + " and tbunit.id = "+ caseFilters.getUnitId() + " and tbcase.id = c.id)"; break; // MISSING EXAM CASES case CaseFilters.MED_CONSULTATION_MISSING: cond = " exists(select tc.id " + "from MedicalExamination med " + "inner join med.tbcase tc " + "inner join tc.ownerUnit as tu " + "inner join tu.adminUnit as a " + "where tu.workspace.id = " + defaultWorkspace.getId().toString() + " and med.nextAppointment is not null and datediff(current_date, med.nextAppointment) > 15 " + " and tc.state < " + CaseState.CURED.ordinal() + " and med.date = (select max(m.date) from MedicalExamination m where m.tbcase.id = tc.id)" + " and tu.id = "+ caseFilters.getUnitId() + " and tc.id = c.id)"; break; case CaseFilters.TRANSFERRING: cond = "c.state = " + CaseState.TRANSFERRING.ordinal(); break; } if (cond != null) addCondition(cond); } } /** * Convert the number entered by the user and separates patient number and case number * @return */ protected String generateHQLPatientNumber(String key) { if (key == null || key.equals("")) return ""; String hql = ""; // check if search is by case ID Workspace ws = getDefaultWorkspace(); if ((ws.getSuspectCaseNumber() == DisplayCaseNumber.CASE_ID) || (ws.getConfirmedCaseNumber() == DisplayCaseNumber.CASE_ID)) { String[] s = key.split("-"); if (s.length == 1) { Integer patnum = stringToNumber(s[0]); if (patnum != null) { if (!hql.isEmpty()) hql += " or "; hql += "(p.recordNumber = " + patnum + " or "; } } else { if (s.length == 2) { Integer patnum = stringToNumber(s[0]); Integer digit = stringToNumber(s[1]); if ((patnum != null) && (digit != null)) { if (!hql.isEmpty()) hql += " or "; hql += "((p.recordNumber = " + patnum + " and c.caseNumber = " + digit + ") or "; } } } Integer caseId = stringToNumber(key); if (caseId != null) hql += "c.id = " + caseId + ")"; } // check if search is by record number if ((ws.getSuspectCaseNumber() == DisplayCaseNumber.VALIDATION_NUMBER) || (ws.getConfirmedCaseNumber() == DisplayCaseNumber.VALIDATION_NUMBER)) { String[] s = key.split("-"); if (s.length == 1) { Integer patnum = stringToNumber(s[0]); if (patnum != null) { if (!hql.isEmpty()) hql += " or "; hql += "p.recordNumber = " + patnum; } } else { if (s.length == 2) { Integer patnum = stringToNumber(s[0]); Integer digit = stringToNumber(s[1]); if ((patnum != null) && (digit != null)) { if (!hql.isEmpty()) hql += " or "; hql += "(p.recordNumber = " + patnum + " and c.caseNumber = " + digit + ")"; } } } } // add filters by suspect registration code if (ws.getSuspectCaseNumber() == DisplayCaseNumber.USER_DEFINED) { if (!hql.isEmpty()) hql += " or "; hql += "c.suspectRegistrationCode = '" + key + "'"; } // add filters by registration code if (ws.getSuspectCaseNumber() == DisplayCaseNumber.USER_DEFINED) { if (!hql.isEmpty()) hql += " or "; hql += "c.registrationCode = '" + key + "'"; } if (!hql.isEmpty()) hql = "(" + hql + ")"; return hql; } /** * Convert a number from string to integer. If the number is not a valid number, * it'll return null * @param s the string representation of the number * @return Integer number or null */ protected Integer stringToNumber(String s) { try { return Integer.parseInt(s); } catch (Exception e) { return null; } } /** * Generates HQL condition to a date field filter * @param dtIni - Initial date of the filter * @param dtEnd - Ending date of the filter * @param dateField - Date field name in the HQL query */ protected void generateHQLPeriod(Date dtIni, Date dtEnd, String dateField) { if (dtIni != null) addCondition("(" + dateField + ">=#{caseFilters.iniDate})"); if (dtEnd != null) addCondition("(" + dateField + "<=#{caseFilters.endDate})"); } /** * Includes a condition to the hql instruction * @param condition - the condition to be included */ protected void addCondition(String condition) { if (hqlCondition.isEmpty()) hqlCondition = condition; else hqlCondition = hqlCondition + " and " + condition; } @Override public List getStringRestrictions() { return Arrays.asList(restrictions); } @Override public String getOrder() { String s = getCaseFilters().isInverseOrder()? inverseOrderValues[getCaseFilters().getOrder()] : orderValues[getCaseFilters().getOrder()]; s = Expressions.instance().createValueExpression(s).getValue().toString(); return s; } @Override public Integer getMaxResults() { Integer max = super.getMaxResults(); if (max != null) return max; else return 50; } /** * Create the result list based on the result query from the database * @param lst */ protected void fillResultList(List lst) { List adminUnits = getCaseFilters().getAuselection().getOptionsLevel1(); if (adminUnits == null) { adminUnits = new ArrayList(); adminUnits.add(getCaseFilters().getAuselection().getUnitLevel1()); } resultList = new ArrayList(); if (loadCaseData) { for (Object[] obj: lst){ CaseResultItem item = new CaseResultItem(); TbCase tbcase = (TbCase)obj[0]; item.setTbcase(tbcase); resultList.add(item); } } else { Workspace ws = getDefaultWorkspace(); for (Object[] obj: lst) { CaseResultItem item = new CaseResultItem(); TbCase tbcase = item.getTbcase(); Patient p = new Patient(); p.setWorkspace(ws); tbcase.setPatient(p); p.setName((String)obj[0]); p.setMiddleName((String)obj[14]); p.setLastName((String)obj[15]); p.setGender((Gender)obj[2]); tbcase.setAge((Integer)obj[1]); tbcase.setTreatmentPeriod( new Period((Date)obj[5], (Date)obj[11]) ); tbcase.setRegistrationDate((Date)obj[6]); Tbunit unit = new Tbunit(); unit.getName().setName1((String)obj[7]); tbcase.setOwnerUnit(unit); item.setAdminUnitDisplay((String)obj[8]); tbcase.setId((Integer)obj[10]); tbcase.setState((CaseState)obj[12]); tbcase.setClassification((CaseClassification)obj[13]); tbcase.setValidationState((ValidationState)obj[16]); p.setBirthDate((Date)obj[19]); tbcase.setRegistrationCode((String)obj[17]); p.setRecordNumber((Integer)obj[3]); tbcase.setCaseNumber((Integer)obj[4]); tbcase.setDiagnosisType((DiagnosisType)obj[18]); tbcase.setDiagnosisDate((Date)obj[20]); tbcase.setOutcomeDate((Date)obj[21]); // search for administrative unit AdministrativeUnit adm = null; String code = (String)obj[9]; for (AdministrativeUnit aux: adminUnits) { if (aux.isSameOrChildCode(code)) { if (!code.equals(aux.getCode())) adm = aux; break; } } if (adm != null) item.setAdminUnitDisplay(adm.getName().getDefaultName() + ", " + item.getAdminUnitDisplay()); resultList.add(item); } } } @Override @Transactional public boolean isNextExists() { boolean b = (resultList != null) && (resultList.size() > getMaxResults()); return b; } @Override public void refresh() { resultList = null; hqlCondition = null; super.refresh(); } /** * Return the HQL order by declaration * @return String containing the order by clause */ public String getNamesOrderBy() { boolean descOrder = getCaseFilters().isInverseOrder(); switch (getDefaultWorkspace().getPatientNameComposition()) { case FULLNAME: return "upper(p.name)" + (descOrder? " desc": ""); case FIRSTSURNAME: return (descOrder? "upper(p.name) desc, upper(p.middleName) desc": "upper(p.name), upper(p.middleName)"); case LAST_FIRST_MIDDLENAME: case LAST_FIRST_MIDDLENAME_WITHOUT_COMMAS: return (descOrder? "upper(p.lastName) desc, upper(p.name) desc, upper(p.middleName) desc": "upper(p.lastName), upper(p.name), upper(p.middleName)"); case SURNAME_FIRSTNAME: return "upper(p.middleName) desc, upper(p.name) desc"; case FIRST_MIDDLE_LASTNAME: default: return descOrder? "upper(p.name) desc, upper(p.middleName) desc, upper(p.lastName) desc": "upper(p.name), upper(p.middleName), upper(p.lastName)"; } } /** * Return the default workspace in use * @return */ public Workspace getDefaultWorkspace() { if (defaultWorkspace == null) defaultWorkspace = UserSession.getWorkspace(); return defaultWorkspace; } public void selectTBSuspects() { CaseFilters filters = getCaseFilters(); if (caseFilters.getTypeSelection() == CaseFilters.TypeSelection.TB_SUSPECTS) { caseFilters.setClassification(null); caseFilters.setDiagnosisType(null); return; } filters.setClassification(CaseClassification.TB); filters.setDiagnosisType(DiagnosisType.SUSPECT); refresh(); } public void selectDRTBSuspects() { CaseFilters filters = getCaseFilters(); if (caseFilters.getTypeSelection() == CaseFilters.TypeSelection.DRTB_SUSPECTS) { caseFilters.setClassification(null); caseFilters.setDiagnosisType(null); return; } filters.setClassification(CaseClassification.DRTB); filters.setDiagnosisType(DiagnosisType.SUSPECT); refresh(); } public void selectTBConfirmed() { CaseFilters filters = getCaseFilters(); if (caseFilters.getTypeSelection() == CaseFilters.TypeSelection.TB_CONFIRMED) { caseFilters.setClassification(null); caseFilters.setDiagnosisType(null); return; } filters.setClassification(CaseClassification.TB); filters.setDiagnosisType(DiagnosisType.CONFIRMED); refresh(); } public void selectDRTBConfirmed() { CaseFilters filters = getCaseFilters(); if (caseFilters.getTypeSelection() == CaseFilters.TypeSelection.DRTB_CONFIRMED) { caseFilters.setClassification(null); caseFilters.setDiagnosisType(null); return; } filters.setClassification(CaseClassification.DRTB); filters.setDiagnosisType(DiagnosisType.CONFIRMED); refresh(); } /** * Return the filters to be applied to the search * @return */ public CaseFilters getCaseFilters() { if (caseFilters == null) caseFilters = CaseFilters.instance(); return caseFilters; } public static CasesQuery instance() { return (CasesQuery)App.getComponent("casesQuery"); } public boolean isLoadCaseData() { return loadCaseData; } public void setLoadCaseData(boolean loadCaseData) { this.loadCaseData = loadCaseData; } /** * @return the ordervalues */ public static String[] getOrdervalues() { return orderValues; } /** * @return the inverseordervalues */ public static String[] getInverseordervalues() { return inverseOrderValues; } }