/** * The contents of this file are subject to the OpenMRS Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.api.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.Cohort; import org.openmrs.Concept; import org.openmrs.ConceptSet; import org.openmrs.Drug; import org.openmrs.DrugOrder; import org.openmrs.Encounter; import org.openmrs.EncounterType; import org.openmrs.Form; import org.openmrs.Location; import org.openmrs.Obs; import org.openmrs.Patient; import org.openmrs.PatientIdentifier; import org.openmrs.PatientIdentifierType; import org.openmrs.PatientProgram; import org.openmrs.PatientState; import org.openmrs.Person; import org.openmrs.PersonAttributeType; import org.openmrs.Program; import org.openmrs.ProgramWorkflow; import org.openmrs.ProgramWorkflowState; import org.openmrs.Relationship; import org.openmrs.RelationshipType; import org.openmrs.api.APIAuthenticationException; import org.openmrs.api.PatientSetService; import org.openmrs.api.context.Context; import org.openmrs.api.db.DAOException; import org.openmrs.api.db.PatientSetDAO; import org.openmrs.util.OpenmrsConstants; import org.openmrs.util.OpenmrsUtil; public class PatientSetServiceImpl implements PatientSetService { public final Log log = LogFactory.getLog(this.getClass()); private PatientSetDAO dao; public PatientSetServiceImpl() { } private PatientSetDAO getPatientSetDAO() { if (!Context.hasPrivilege(OpenmrsConstants.PRIV_VIEW_PATIENT_COHORTS)) { throw new APIAuthenticationException("Privilege required: " + OpenmrsConstants.PRIV_VIEW_PATIENT_COHORTS); } return dao; } public void setPatientSetDAO(PatientSetDAO dao) { this.dao = dao; } /** * Clean up after this class. Set the static var to null so that the classloader can reclaim the * space. * * @see org.openmrs.api.impl.BaseOpenmrsService#onShutdown() */ public void onShutdown() { } /** * @param ps The set you want to export as XML * @return an XML representation of this patient-set, including patient characteristics, and * observations */ public String exportXml(Cohort ps) { return getPatientSetDAO().exportXml(ps); } public String exportXml(Integer patientId) { return getPatientSetDAO().exportXml(patientId); } public Cohort getAllPatients() throws DAOException { return getPatientSetDAO().getAllPatients(); } public Cohort getPatientsByCharacteristics(String gender, Date minBirthdate, Date maxBirthdate) throws DAOException { return getPatientsByCharacteristics(gender, minBirthdate, maxBirthdate, null, null, null, null); } public Cohort getPatientsByCharacteristics(String gender, Date minBirthdate, Date maxBirthdate, Integer minAge, Integer maxAge, Boolean aliveOnly, Boolean deadOnly) throws DAOException { return getPatientSetDAO().getPatientsByCharacteristics(gender, minBirthdate, maxBirthdate, minAge, maxAge, aliveOnly, deadOnly); } public Cohort getPatientsByCharacteristics(String gender, Date minBirthdate, Date maxBirthdate, Integer minAge, Integer maxAge, Boolean aliveOnly, Boolean deadOnly, Date effectiveDate) throws DAOException { return getPatientSetDAO().getPatientsByCharacteristics(gender, minBirthdate, maxBirthdate, minAge, maxAge, aliveOnly, deadOnly, effectiveDate); } public Cohort getPatientsHavingDateObs(Integer conceptId, Date startTime, Date endTime) { return getPatientSetDAO().getPatientsHavingDateObs(conceptId, startTime, endTime); } public Cohort getPatientsHavingNumericObs(Integer conceptId, TimeModifier timeModifier, PatientSetServiceImpl.Modifier modifier, Number value, Date fromDate, Date toDate) { return getPatientSetDAO().getPatientsHavingNumericObs(conceptId, timeModifier, modifier, value, fromDate, toDate); } public Cohort getPatientsHavingObs(Integer conceptId, TimeModifier timeModifier, PatientSetServiceImpl.Modifier modifier, Object value, Date fromDate, Date toDate) { return getPatientSetDAO().getPatientsHavingObs(conceptId, timeModifier, modifier, value, fromDate, toDate); } public Cohort getPatientsHavingEncounters(EncounterType encounterType, Location location, Form form, Date fromDate, Date toDate, Integer minCount, Integer maxCount) { List<EncounterType> list = encounterType == null ? null : Collections.singletonList(encounterType); return getPatientSetDAO().getPatientsHavingEncounters(list, location, form, fromDate, toDate, minCount, maxCount); } public Cohort getPatientsHavingEncounters(List<EncounterType> encounterTypeList, Location location, Form form, Date fromDate, Date toDate, Integer minCount, Integer maxCount) { return getPatientSetDAO().getPatientsHavingEncounters(encounterTypeList, location, form, fromDate, toDate, minCount, maxCount); } public Cohort getPatientsByProgramAndState(Program program, List<ProgramWorkflowState> stateList, Date fromDate, Date toDate) { return getPatientSetDAO().getPatientsByProgramAndState(program, stateList, fromDate, toDate); } public Cohort getPatientsInProgram(Program program, Date fromDate, Date toDate) { return getPatientSetDAO().getPatientsInProgram(program.getProgramId(), fromDate, toDate); } public Cohort getPatientsHavingTextObs(Concept concept, String value, TimeModifier timeModifier) { return getPatientsHavingTextObs(concept.getConceptId(), value, timeModifier); } public Cohort getPatientsHavingTextObs(Integer conceptId, String value, TimeModifier timeModifier) { return getPatientSetDAO().getPatientsHavingTextObs(conceptId, value, timeModifier); } public Cohort getPatientsHavingLocation(Location loc) { return getPatientsHavingLocation(loc.getLocationId(), PatientLocationMethod.PATIENT_HEALTH_CENTER); } public Cohort getPatientsHavingLocation(Location loc, PatientLocationMethod method) { return getPatientsHavingLocation(loc.getLocationId(), method); } public Cohort getPatientsHavingLocation(Integer locationId) { return getPatientsHavingLocation(locationId, PatientLocationMethod.PATIENT_HEALTH_CENTER); } public Cohort getPatientsHavingLocation(Integer locationId, PatientLocationMethod method) { return getPatientSetDAO().getPatientsHavingLocation(locationId, method); } /** * Returns a PatientSet of patient who had drug orders for a set of drugs active on a certain * date. Can also be used to find patient with no drug orders on that date. * * @param patientIds Collection of patientIds you're interested in. NULL means all patients. * @param takingIds Collection of drugIds the patient is taking. (Or the empty set to mean * "any drug" or NULL to mean "no drugs") * @param onDate Which date to look at the patients' drug orders. (NULL defaults to now().) * @return Cohort of Patients matching criteria */ public Cohort getPatientsHavingDrugOrder(Collection<Integer> patientIds, Collection<Integer> takingIds, Date onDate) { Map<Integer, Collection<Integer>> activeDrugs = getPatientSetDAO().getActiveDrugIds(patientIds, onDate, onDate); Set<Integer> ret = new HashSet<Integer>(); boolean takingAny = takingIds != null && takingIds.size() == 0; boolean takingNone = takingIds == null; if (takingAny) { ret.addAll(activeDrugs.keySet()); } else if (takingNone) { if (patientIds == null) { patientIds = getAllPatients().getMemberIds(); } patientIds.removeAll(activeDrugs.keySet()); ret.addAll(patientIds); } else { // taking any of the drugs in takingIds for (Map.Entry<Integer, Collection<Integer>> e : activeDrugs.entrySet()) { for (Integer drugId : takingIds) { if (e.getValue().contains(drugId)) { ret.add(e.getKey()); break; } } } } return new Cohort("Cohort from drug orders", "", ret); } public Cohort getPatientsHavingDrugOrder(Collection<Integer> patientIds, Collection<Integer> drugIds, GroupMethod groupMethod, Date fromDate, Date toDate) { Map<Integer, Collection<Integer>> activeDrugs = getPatientSetDAO().getActiveDrugIds(patientIds, fromDate, toDate); Set<Integer> ret = new HashSet<Integer>(); if (drugIds == null) drugIds = new ArrayList<Integer>(); if (drugIds.size() == 0) { if (groupMethod == GroupMethod.NONE) { // Patients taking no drugs if (patientIds == null) { patientIds = getAllPatients().getMemberIds(); } patientIds.removeAll(activeDrugs.keySet()); ret.addAll(patientIds); } else { // Patients taking any drugs ret.addAll(activeDrugs.keySet()); } } else { if (groupMethod == GroupMethod.NONE) { // Patients taking none of the specified drugs // first get all patients taking no drugs at all ret.addAll(patientIds); ret.removeAll(activeDrugs.keySet()); // next get all patients taking drugs, but not the specified ones for (Map.Entry<Integer, Collection<Integer>> e : activeDrugs.entrySet()) if (!OpenmrsUtil.containsAny(e.getValue(), drugIds)) ret.add(e.getKey()); } else if (groupMethod == GroupMethod.ALL) { // Patients taking all of the specified drugs for (Map.Entry<Integer, Collection<Integer>> e : activeDrugs.entrySet()) if (e.getValue().containsAll(drugIds)) ret.add(e.getKey()); } else { // groupMethod == GroupMethod.ANY // Patients taking any of the specified drugs for (Map.Entry<Integer, Collection<Integer>> e : activeDrugs.entrySet()) if (OpenmrsUtil.containsAny(e.getValue(), drugIds)) ret.add(e.getKey()); } } Cohort ps = new Cohort("Cohort from drug orders", "", ret); return ps; } public Cohort getPatientsHavingDrugOrder(List<Drug> drug, List<Concept> drugConcept, Date startDateFrom, Date startDateTo, Date stopDateFrom, Date stopDateTo, Boolean discontinued, List<Concept> discontinuedReason) { return getPatientSetDAO().getPatientsHavingDrugOrder(drug, drugConcept, startDateFrom, startDateTo, stopDateFrom, stopDateTo, discontinued, discontinuedReason); } public Cohort getPatientsHavingPersonAttribute(PersonAttributeType attribute, String value) { return getPatientSetDAO().getPatientsHavingPersonAttribute(attribute, value); } public Map<Integer, String> getShortPatientDescriptions(Collection<Integer> patientIds) { return getPatientSetDAO().getShortPatientDescriptions(patientIds); } public Map<Integer, List<Obs>> getObservations(Cohort patients, Concept concept) { if (patients == null || patients.size() == 0) return new HashMap<Integer, List<Obs>>(); return getPatientSetDAO().getObservations(patients, concept, null, null); } /** * Date range is inclusive of both endpoints */ public Map<Integer, List<Obs>> getObservations(Cohort patients, Concept concept, Date fromDate, Date toDate) { if (patients == null || patients.size() == 0) return new HashMap<Integer, List<Obs>>(); return getPatientSetDAO().getObservations(patients, concept, fromDate, toDate); } public Map<Integer, List<List<Object>>> getObservationsValues(Cohort patients, Concept c) { return getObservationsValues(patients, c, null); } public Map<Integer, List<List<Object>>> getObservationsValues(Cohort patients, Concept c, List<String> attributes) { if (attributes == null) attributes = new Vector<String>(); // add null for the actual obs value if (attributes.size() < 1 || attributes.get(0) != null) attributes.add(0, null); return getPatientSetDAO().getObservationsValues(patients, c, attributes); } public Map<Integer, Encounter> getEncountersByType(Cohort patients, EncounterType encType) { List<EncounterType> types = new Vector<EncounterType>(); if (encType != null) types.add(encType); return getPatientSetDAO().getEncountersByType(patients, types); } public Map<Integer, Object> getEncounterAttrsByType(Cohort patients, List<EncounterType> encTypes, String attr) { if (encTypes == null) encTypes = new Vector<EncounterType>(); return getPatientSetDAO().getEncounterAttrsByType(patients, encTypes, attr, false); } public Map<Integer, Encounter> getEncountersByType(Cohort patients, List<EncounterType> types) { return getPatientSetDAO().getEncountersByType(patients, types); } public Map<Integer, Encounter> getEncounters(Cohort patients) { return getPatientSetDAO().getEncounters(patients); } public Map<Integer, Encounter> getFirstEncountersByType(Cohort patients, EncounterType encType) { List<EncounterType> types = new Vector<EncounterType>(); if (encType != null) types.add(encType); return getPatientSetDAO().getFirstEncountersByType(patients, types); } public Map<Integer, Object> getFirstEncounterAttrsByType(Cohort patients, List<EncounterType> encTypes, String attr) { if (encTypes == null) encTypes = new Vector<EncounterType>(); return getPatientSetDAO().getEncounterAttrsByType(patients, encTypes, attr, true); } public Map<Integer, Encounter> getFirstEncountersByType(Cohort patients, List<EncounterType> types) { return getPatientSetDAO().getFirstEncountersByType(patients, types); } /** * @see org.openmrs.api.PatientSetService#getPatientAttributes(Cohort, String, String, boolean) */ public Map<Integer, Object> getPatientAttributes(Cohort patients, String className, String property, boolean returnAll) { return getPatientSetDAO().getPatientAttributes(patients, className, property, returnAll); } public Map<Integer, Object> getPatientAttributes(Cohort patients, String classNameDotProperty, boolean returnAll) { String[] temp = classNameDotProperty.split("\\."); if (temp.length != 2) { throw new IllegalArgumentException(classNameDotProperty + " must be ClassName.property"); } return getPatientAttributes(patients, temp[0], temp[1], returnAll); } public Map<Integer, PatientIdentifier> getPatientIdentifiersByType(Cohort patients, PatientIdentifierType type) { List<PatientIdentifierType> types = new Vector<PatientIdentifierType>(); if (type != null) types.add(type); return getPatientSetDAO().getPatientIdentifierByType(patients, types); } /** * @see org.openmrs.api.PatientSetService#getPersonAttributes(org.openmrs.Cohort, * java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean) */ public Map<Integer, Object> getPersonAttributes(Cohort patients, String attributeName, String joinClass, String joinProperty, String outputColumn, boolean returnAll) { return getPatientSetDAO().getPersonAttributes(patients, attributeName, joinClass, joinProperty, outputColumn, returnAll); } public Map<Integer, Map<String, Object>> getCharacteristics(Cohort patients) { return getPatientSetDAO().getCharacteristics(patients); } public Cohort convertPatientIdentifier(List<String> identifiers) { return getPatientSetDAO().convertPatientIdentifier(identifiers); } public List<Patient> getPatients(Collection<Integer> patientIds) { return getPatientSetDAO().getPatients(patientIds); } public Map<Integer, List<Relationship>> getRelationships(Cohort ps, RelationshipType relType) { return getPatientSetDAO().getRelationships(ps, relType); } public Map<Integer, List<Person>> getRelatives(Cohort ps, RelationshipType relType, boolean forwards) { return getPatientSetDAO().getRelatives(ps, relType, forwards); } public Map<Integer, PatientState> getCurrentStates(Cohort ps, ProgramWorkflow wf) { return getPatientSetDAO().getCurrentStates(ps, wf); } public Map<Integer, PatientProgram> getCurrentPatientPrograms(Cohort ps, Program program) { return getPatientSetDAO().getPatientPrograms(ps, program, false, false); } public Map<Integer, PatientProgram> getPatientPrograms(Cohort ps, Program program) { return getPatientSetDAO().getPatientPrograms(ps, program, false, true); } /** * @return all active drug orders whose drug concept is in the given set (or all drugs if that's * null) */ public Map<Integer, List<DrugOrder>> getCurrentDrugOrders(Cohort ps, Concept drugSet) { List<Concept> drugConcepts = null; if (drugSet != null) { List<ConceptSet> concepts = Context.getConceptService().getConceptSetsByConcept(drugSet); drugConcepts = new ArrayList<Concept>(); for (ConceptSet cs : concepts) { drugConcepts.add(cs.getConcept()); } } log.debug("drugSet: " + drugSet); log.debug("drugConcepts: " + drugConcepts); return getPatientSetDAO().getCurrentDrugOrders(ps, drugConcepts); } /** * @return all drug orders whose drug concept is in the given set (or all drugs if that's null) */ public Map<Integer, List<DrugOrder>> getDrugOrders(Cohort ps, Concept drugSet) { List<Concept> drugConcepts = null; if (drugSet != null) { List<ConceptSet> concepts = Context.getConceptService().getConceptSetsByConcept(drugSet); drugConcepts = new ArrayList<Concept>(); for (ConceptSet cs : concepts) { drugConcepts.add(cs.getConcept()); } } return getPatientSetDAO().getDrugOrders(ps, drugConcepts); } /** * Gets a list of encounters associated with the given form, filtered by the given patient set. * * @param patients the patients to filter by (null will return all encounters for all patients) * @param forms the forms to filter by */ public List<Encounter> getEncountersByForm(Cohort patients, List<Form> forms) { return getPatientSetDAO().getEncountersByForm(patients, forms); } }