package model.manager; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import java.util.Map.Entry; import model.manager.exports.ScriptColumn; import model.nonPersistent.EntitySet; import model.nonPersistent.ExportDrugInfo; import model.nonPersistent.ExportPackageInfo; import org.apache.log4j.Logger; import org.celllife.idart.database.hibernate.APIException; import org.celllife.idart.database.hibernate.AccumulatedDrugs; import org.celllife.idart.database.hibernate.Appointment; import org.celllife.idart.database.hibernate.Episode; import org.celllife.idart.database.hibernate.PackagedDrugs; import org.celllife.idart.database.hibernate.Packages; import org.celllife.idart.database.hibernate.Patient; import org.celllife.idart.database.hibernate.PatientAttribute; import org.celllife.idart.database.hibernate.PatientIdentifier; import org.celllife.idart.database.hibernate.PrescribedDrugs; import org.celllife.idart.database.hibernate.Prescription; import org.celllife.idart.database.hibernate.Regimen; import org.celllife.idart.database.hibernate.util.DAOException; import org.hibernate.CacheMode; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.Order; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; public class PatientSetManager { private static Logger log = Logger.getLogger(PatientSetManager.class); @SuppressWarnings("unchecked") public static List<Patient> getPatientsInSet(Session sess, Collection<Integer> ids) { return sess.createCriteria(Patient.class).add( Restrictions.in("id", ids)).list(); } /** * Used to get data such about a patient * * e.g. className = Patient, property = firstNames * * className = Appointment, property = appointmentDate, returnAll = true * * @param sess * @param patients * @param className * @param property * the name of the property to fetch * @param returnAll * if false return only the first value of the given field or * return all values if true (only applies to fields that have a * multiplicity greater than one * @return * @throws DAOException */ @SuppressWarnings("unchecked") public static Map<Integer, Object> getPatientFields(Session sess, EntitySet patients, String className, String property, boolean returnAll) throws DAOException { Map<Integer, Object> patFields = new HashMap<Integer, Object>(); className = "org.celllife.idart.database.hibernate." + className; // default query Criteria criteria = null; String patientClassName = Patient.class.getCanonicalName(); // make 'patient.**' reference 'patient' like alias instead of object if (className.equals(patientClassName)) { criteria = sess.createCriteria(patientClassName, "patient"); } else { criteria = sess.createCriteria(className); } // cater for extended properties such as clinic.name if (property.contains(".")) { List<String[]> aliases = createAliasesForExtendedProperty(property); for (String[] strings : aliases) { if (strings.length > 1) { criteria.createAlias(strings[0], strings[1]); } else if (strings.length > 1) { property = strings[0]; } } } criteria.setCacheMode(CacheMode.IGNORE); // set up the query ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.property("patient.id")); projectionList.add(Projections.property(property)); if (patients != null) { criteria .add(Restrictions.in("patient.id", patients.getEntityIds())); } criteria.setProjection(projectionList); List<Object[]> rows = criteria.list(); // set up the return map if (returnAll) { for (Object[] row : rows) { Integer ptId = (Integer) row[0]; Object columnValue = row[1]; if (!patFields.containsKey(ptId)) { Object[] arr = { columnValue }; patFields.put(ptId, arr); } else { Object[] oldArr = (Object[]) patFields.get(ptId); Object[] newArr = new Object[oldArr.length + 1]; System.arraycopy(oldArr, 0, newArr, 0, oldArr.length); newArr[oldArr.length] = columnValue; patFields.put(ptId, newArr); } } } else { for (Object[] row : rows) { Integer ptId = (Integer) row[0]; Object columnValue = row[1]; if (!patFields.containsKey(ptId)) { patFields.put(ptId, columnValue); } } } return patFields; } /** * This method is used to expand a dot separated property into a list of * aliases that can be used to build up a {@link Criteria} * * foo returns {foo} * * foo.bar returns {foo, foo}, {bar} * * foo.bar.bob returns {foo, foo}, {foo.bar, bar}, {bob} * * foo.bar.bob.hat returns {foo, foo}, {foo.bar, bar}, {bar.bob, bob}, {hat} * * @param property * @param criteria * @return */ private static List<String[]> createAliasesForExtendedProperty( String property) { List<String[]> aliases = new Vector<String[]>(); if (!property.contains(".")) { aliases.add(new String[] { property }); return aliases; } String[] splitProperty = property.split("[.]"); aliases.add(new String[] { splitProperty[0], splitProperty[0] }); for (int i = 1; i < splitProperty.length - 1; i++) { String aliasField = splitProperty[i - 1] + "." + splitProperty[i]; aliases.add(new String[] { aliasField, splitProperty[i] }); } aliases.add(new String[] { splitProperty[splitProperty.length - 1] }); return aliases; } @SuppressWarnings("unchecked") public static Map<Integer, Map<Integer, ExportPackageInfo>> getPackageDetail( Session sess, EntitySet patients, Integer mostRecentNum, Date startDate, Date endDate) { Map<Integer, Map<Integer, ExportPackageInfo>> patientPackagesMap = new HashMap<Integer, Map<Integer, ExportPackageInfo>>(); String classNamePackage = Packages.class.getCanonicalName(); List<Integer> patientIds; if (patients != null) { patientIds = patients.getEntityIds(); } else { Query patientQuery = sess.createQuery("select id from Patient"); patientIds = patientQuery.list(); } for (Integer id : patientIds) { Criteria critPackg = sess.createCriteria(classNamePackage, "package").addOrder(Order.desc("package.pickupDate")).add( Restrictions.isNotNull("package.prescription")); critPackg.createAlias("package.prescription", "prescription") .createAlias("prescription.patient", "patient"); critPackg.add(Restrictions.eq("patient.id", id)); critPackg.add(Restrictions.isNotNull("package.pickupDate")); if (startDate != null) { critPackg.add(Restrictions.ge("packDate", startDate)); } if (endDate != null) { critPackg.add(Restrictions.lt("packDate", endDate)); } if (mostRecentNum > 0) { critPackg.setMaxResults(mostRecentNum); } List<Packages> packages = critPackg.list(); for (Packages packag : packages) { Integer pid = packag.getPrescription().getPatient().getId(); ExportPackageInfo exportPackageInfo = getExportPacakgeInfoFromPackage( packag, sess); if (!patientPackagesMap.containsKey(pid)) { Map<Integer, ExportPackageInfo> packagesList = new HashMap<Integer, ExportPackageInfo>(); packagesList.put(packag.getId(), exportPackageInfo); patientPackagesMap.put(pid, packagesList); } else { Map<Integer, ExportPackageInfo> packagesList = patientPackagesMap .get(pid); packagesList.put(packag.getId(), exportPackageInfo); } } } return patientPackagesMap; } private static ExportPackageInfo getExportPacakgeInfoFromPackage( Packages packages, Session session) { ExportPackageInfo epi = new ExportPackageInfo(); epi.setDateCollected(packages.getPickupDate()); epi.setPatientID(packages.getPrescription().getPatient().getId()); epi.setPackageID(packages.getPackageId()); epi.setDispenseDate(packages.getPackDate()); // Obtaining prescription Prescription prescr = packages.getPrescription(); // Obtaining prescribed drugs List<PrescribedDrugs> lstPrescrDrgs = prescr.getPrescribedDrugs(); // Obtaining accumulated drugs Set<AccumulatedDrugs> lstAccDrgs = packages.getAccumulatedDrugs(); // Obtaining packaged drugs List<PackagedDrugs> lstPackagedDrugs = packages.getPackagedDrugs(); for (PackagedDrugs pd : lstPackagedDrugs) { // For some reason it seems that the list may be initialised but // it may contain null elements. if (pd != null) { ExportDrugInfo edi = new ExportDrugInfo(); // Obtaining EDI info String shortName = DrugManager.getShortGenericDrugName(pd .getStock().getDrug(), true); int qtyDisp = pd.getAmount(); double amtPerTime = 0; int timesPerDay = 0; int accumDrgs = 0; for (PrescribedDrugs prd : lstPrescrDrgs) { if (prd.getDrug().getId() == pd.getStock().getDrug() .getId()) { amtPerTime = prd.getAmtPerTime(); timesPerDay = prd.getTimesPerDay(); break; } } for (AccumulatedDrugs acumdrg : lstAccDrgs) { if (acumdrg.getPillCount().getDrug().getId() == pd .getStock().getDrug().getId()) { accumDrgs = acumdrg.getPillCount().getAccum(); break; } } edi.setAccumulatedDrugs(accumDrgs); edi.setAmountPerTime(amtPerTime); edi.setChemicalCompoundName(shortName); edi.setQuantityDispensed(qtyDisp); edi.setTimesPerDay(timesPerDay); edi.setDrugId(pd.getStock().getDrug().getId()); edi.setBatch(pd.getStock().getBatchNumber()); edi.setIsARV(pd.getStock().getDrug().isARV()); epi.getListOfExportDrugInfo().add(edi); } } Map<Regimen, Set<Integer>> regimenIdMap = PrescriptionManager.getRegimenIdMap(session); Set<Integer> drugIdSet = epi.getARVDrugIdSet(); for (Entry<Regimen, Set<Integer>> entry : regimenIdMap.entrySet()) { if (drugIdSet.containsAll(entry.getValue())) { Regimen theReg = entry.getKey(); epi.setRegimen(theReg.getDrugGroup()); epi.setDrugGroupName(theReg.getRegimenName()); break; } } return epi; } @SuppressWarnings("unchecked") public static Map<Integer, List<List<Object>>> getEpisodeDetails( Session session, EntitySet patients, List<String> details, Date startDate, Date endDate) { Map<Integer, List<List<Object>>> ret = new HashMap<Integer, List<List<Object>>>(); Criteria criteria = session.createCriteria( "org.celllife.idart.database.hibernate.Episode", "episode"); criteria.createAlias("episode.patient", "patient"); if (startDate != null){ criteria.add(Restrictions.ge("episode.startDate", startDate)); } if (endDate != null){ criteria.add(Restrictions.or( Restrictions.isNull("episode.stopDate"), Restrictions.le("episode.stopDate", endDate))); } criteria.setCacheMode(CacheMode.IGNORE); List<String> columns = new Vector<String>(); if (details == null || details.size() <= 0) { columns = getDefaultColumns(Episode.class); } else { for (String attribute : details) { if (attribute == null) { attribute = ""; } else if (attribute.equals("startDate")) { // pass -- same column name } else if (attribute.equals("startReason")) { // pass -- same column name } else if (attribute.equals("startNotes")) { // pass -- same column name } else if (attribute.equals("stopDate")) { // pass -- same column name } else if (attribute.equals("stopReason")) { // pass -- same column name } else if (attribute.equals("stopNotes")) { // pass -- same column name } else if (attribute.equals("clinic.clinicName")) { criteria.createAlias("clinic", "clinic"); } else { throw new APIException("Attribute: " + attribute + " is not recognized. Please add reference in " + PatientSetManager.class); } columns.add(attribute); } } // set up the query ProjectionList projections = Projections.projectionList(); projections.add(Projections.property("patient.id")); for (String col : columns) { if (col.length() > 0) { projections.add(Projections.property(col)); } } criteria.setProjection(projections); // only restrict on patient ids if some were passed in if (patients != null) { criteria .add(Restrictions.in("patient.id", patients.getEntityIds())); } criteria.addOrder(org.hibernate.criterion.Order .desc("episode.startDate")); log.debug("criteria: " + criteria); List<Object[]> rows = criteria.list(); // set up the return map for (Object[] rowArray : rows) { Integer ptId = (Integer) rowArray[0]; // get all columns int index = 1; List<Object> row = new Vector<Object>(); while (index < rowArray.length) { Object value = rowArray[index++]; row.add(value == null ? "" : value); } // if we haven't seen a different row for this patient already: if (!ret.containsKey(ptId)) { List<List<Object>> arr = new Vector<List<Object>>(); arr.add(row); ret.put(ptId, arr); } // if we have seen a row for this patient already else { List<List<Object>> oldArr = ret.get(ptId); oldArr.add(row); ret.put(ptId, oldArr); } } return ret; } @SuppressWarnings("unchecked") public static Map<Integer, List<List<Object>>> getPrescriptionDetails( Session sess, EntitySet patients, List<String> details) { Map<Integer, List<List<Object>>> ret = new HashMap<Integer, List<List<Object>>>(); String classNamePrescription = Prescription.class.getCanonicalName(); List<Integer> patientIds; if (patients != null) { patientIds = patients.getEntityIds(); } else { Query patientQuery = sess.createQuery("select id from Patient"); patientIds = patientQuery.list(); } for (Integer id : patientIds) { Criteria critScript = sess.createCriteria(classNamePrescription, "prescription").addOrder(Order.desc("prescription.date")) .add(Restrictions.isNotEmpty("prescription.packages")); critScript.createAlias("prescription.patient", "patient"); critScript.add(Restrictions.eq("patient.id", id)); List<Prescription> prescriptions = critScript.list(); for (Prescription script : prescriptions) { Integer pid = script.getPatient().getId(); if (!ret.containsKey(pid)) { List<List<Object>> scriptList = new ArrayList<List<Object>>(); scriptList.add(getScriptInfoList(script, details)); ret.put(pid, scriptList); } else { List<List<Object>> scriptList = ret.get(pid); scriptList.add(getScriptInfoList(script, details)); } } } return ret; } private static List<Object> getScriptInfoList(Prescription script, List<String> details) { List<Object> info = new ArrayList<Object>(); for (String attrib : details) { if (attrib.equalsIgnoreCase("drugs")) { String drugInfo = getDrugDetailsFromScript(script); info.add(drugInfo); } else if (attrib.equalsIgnoreCase("date")) { info.add(script.getDate()); } else if (attrib.equalsIgnoreCase("clinicalStage")) { info.add(script.getClinicalStage()); } else if (attrib.equalsIgnoreCase("current")) { info.add(script.getCurrent()); } else if (attrib.equalsIgnoreCase("duration")) { info.add(script.getDuration()); } else if (attrib.equalsIgnoreCase("reasonForUpdate")) { info.add(script.getReasonForUpdate()); } else if (attrib.equalsIgnoreCase("notes")) { info.add(script.getNotes()); } else if (attrib.equalsIgnoreCase("weight")) { info.add(script.getWeight()); } else if (attrib.equalsIgnoreCase("endDate")) { info.add(script.getEndDate()); } } return info; } private static String getDrugDetailsFromScript(Prescription script) { List<PrescribedDrugs> prescribedDrugs = script.getPrescribedDrugs(); String drugInfo = ""; for (PrescribedDrugs pd : prescribedDrugs) { String drugName = DrugManager.getShortGenericDrugName(pd.getDrug(), true); String amtPerTime = String.valueOf(pd.getAmtPerTime()); String timesPerDay = String.valueOf(pd.getTimesPerDay()); drugInfo += drugName + "(" + amtPerTime + "x" + timesPerDay + ") "; } return drugInfo; } @SuppressWarnings("unchecked") public static Map<Integer, List<List<Object>>> getAppointmentDetails( Session session, EntitySet patients, List<String> details) { Map<Integer, List<List<Object>>> ret = new HashMap<Integer, List<List<Object>>>(); Criteria criteria = session.createCriteria( "org.celllife.idart.database.hibernate.Appointment", "appointment"); criteria.createAlias("appointment.patient", "patient"); criteria.setCacheMode(CacheMode.IGNORE); List<String> columns = new Vector<String>(); if (details == null || details.size() <= 0) { columns = getDefaultColumns(Appointment.class); } else { for (String attribute : details) { if (attribute == null) { attribute = ""; } else if (attribute.equals("appointmentDate")) { // pass -- same column name } else if (attribute.equals("active")) { // pass -- same column name } else { throw new APIException("Attribute: " + attribute + " is not recognized. Please add reference in " + PatientSetManager.class); } columns.add(attribute); } } // set up the query ProjectionList projections = Projections.projectionList(); projections.add(Projections.property("patient.id")); for (String col : columns) { if (col.length() > 0) { projections.add(Projections.property("appointment." + col)); } } criteria.setProjection(projections); // only restrict on patient ids if some were passed in if (patients != null) { criteria .add(Restrictions.in("patient.id", patients.getEntityIds())); } criteria.addOrder(org.hibernate.criterion.Order .desc("appointment.appointmentDate")); log.debug("criteria: " + criteria); List<Object[]> rows = criteria.list(); // set up the return map for (Object[] rowArray : rows) { Integer ptId = (Integer) rowArray[0]; // get all columns int index = 1; List<Object> row = new Vector<Object>(); while (index < rowArray.length) { Object value = rowArray[index++]; row.add(value == null ? "" : value); } // if we haven't seen a different row for this patient already: if (!ret.containsKey(ptId)) { List<List<Object>> arr = new Vector<List<Object>>(); arr.add(row); ret.put(ptId, arr); } // if we have seen a row for this patient already else { List<List<Object>> oldArr = ret.get(ptId); oldArr.add(row); ret.put(ptId, oldArr); } } return ret; } private static List<String> getDefaultColumns(Class<?> class1) { List<String> columns = new Vector<String>(); if (class1.equals(Episode.class)) { columns.add("startDate"); columns.add("startReason"); columns.add("stopDate"); columns.add("stopReason"); } else if (class1.equals(Prescription.class)) { columns.add("date"); columns.add("reasonForUpdate"); } else if (class1.equals(Appointment.class)) { columns.add("appointmentDate"); } return columns; } public static Map<Integer, Object> getPatientAttributes(Session sess, EntitySet patients, String attributeName) { Map<Integer, Object> patFields = new HashMap<Integer, Object>(); Criteria criteria = null; criteria = sess.createCriteria(PatientAttribute.class, "attr"); criteria.createAlias("attr.patient", "patient").createAlias( "attr.type", "type"); criteria.add(Restrictions.eq("type.name", attributeName)); criteria.setCacheMode(CacheMode.IGNORE); ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.property("patient.id")); projectionList.add(Projections.property("attr.value")); if (patients != null) { criteria .add(Restrictions.in("patient.id", patients.getEntityIds())); } criteria.setProjection(projectionList); List<Object[]> rows = criteria.list(); for (Object[] row : rows) { Integer ptId = (Integer) row[0]; Object columnValue = row[1]; if (!patFields.containsKey(ptId)) { patFields.put(ptId, columnValue); } } return patFields; } public static Map<Integer, Object> getPatientIdentifiers(Session sess, EntitySet patients, String identifierName) { Map<Integer, Object> patFields = new HashMap<Integer, Object>(); Criteria criteria = null; criteria = sess.createCriteria(PatientIdentifier.class, "id"); criteria.createAlias("id.patient", "patient").createAlias( "id.type", "type"); criteria.add(Restrictions.eq("type.name", identifierName)); criteria.setCacheMode(CacheMode.IGNORE); ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.property("patient.id")); projectionList.add(Projections.property("id.value")); if (patients != null) { criteria .add(Restrictions.in("patient.id", patients.getEntityIds())); } criteria.setProjection(projectionList); List<Object[]> rows = criteria.list(); for (Object[] row : rows) { Integer ptId = (Integer) row[0]; Object columnValue = row[1]; if (!patFields.containsKey(ptId)) { patFields.put(ptId, columnValue); } } return patFields; } public static Map<Integer, Map<Integer, Map<String, Object>>> getPrescriptionIds( Session sess, EntitySet patients) { Map<Integer, Map<Integer, Map<String, Object>>> patientScriptMap = new HashMap<Integer, Map<Integer, Map<String, Object>>>(); String classNamePrescription = Prescription.class.getCanonicalName(); List<Integer> patientIds; if (patients != null) { patientIds = patients.getEntityIds(); } else { Query patientQuery = sess.createQuery("select id from Patient"); patientIds = patientQuery.list(); } for (Integer id : patientIds) { Criteria critScript = sess.createCriteria(classNamePrescription, "prescription").addOrder(Order.desc("prescription.date")) .add(Restrictions.isNotEmpty("prescription.packages")); critScript.createAlias("prescription.patient", "patient"); critScript.add(Restrictions.eq("patient.id", id)); List<Prescription> prescriptions = critScript.list(); for (Prescription script : prescriptions) { Integer pid = script.getPatient().getId(); if (!patientScriptMap.containsKey(pid)) { Map<Integer, Map<String, Object>> scriptList = new HashMap<Integer, Map<String, Object>>(); scriptList.put(script.getId(), getScriptInfo(script)); patientScriptMap.put(pid, scriptList); } else { Map<Integer, Map<String, Object>> scriptList = patientScriptMap .get(pid); scriptList.put(script.getId(), getScriptInfo(script)); } } } return patientScriptMap; } /** * Order important!! * * @param script * @return */ private static Map<String, Object> getScriptInfo(Prescription script) { Map<String, Object> info = new HashMap<String, Object>(); info.put(ScriptColumn.COL_ID, script.getPrescriptionId()); info.put(ScriptColumn.COL_DATE, script.getDate()); info.put(ScriptColumn.COL_DURATION, script.getDuration()); String drugInfo = getDrugDetailsFromScript(script); info.put(ScriptColumn.COL_DRUGINFO, drugInfo); return info; } /** * Returns a list of Patient ID's for patients who are pregnant at the * specified date. * * @param session * @param patients * @param date * @return */ public static List<Integer> getPregnantAtDate(Session session, EntitySet patients, Date date) { List<Integer> patientsPregnantAtDate = new ArrayList<Integer>(); Criteria criteria = session.createCriteria( "org.celllife.idart.database.hibernate.Pregnancy", "pregnancy"); criteria.add(Restrictions.and(Restrictions.le("confirmDate", date), Restrictions.gt("endDate", date))); criteria.createAlias("pregnancy.patient", "patient"); criteria.setCacheMode(CacheMode.IGNORE); // set up the query ProjectionList projections = Projections.projectionList(); projections.add(Projections.property("patient.id")); criteria.setProjection(projections); // only restrict on patient ids if some were passed in if (patients != null) { criteria .add(Restrictions.in("patient.id", patients.getEntityIds())); } log.debug("criteria: " + criteria); List<Object> rows = criteria.list(); // set up the return map for (Object rowVal : rows) { patientsPregnantAtDate.add((Integer) rowVal); } return patientsPregnantAtDate; } }