/**
* 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.db.hibernate;
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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.openmrs.Cohort;
import org.openmrs.Encounter;
import org.openmrs.EncounterType;
import org.openmrs.Form;
import org.openmrs.Location;
import org.openmrs.Patient;
import org.openmrs.PatientIdentifierType;
import org.openmrs.User;
import org.openmrs.api.EncounterService;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.DAOException;
import org.openmrs.api.db.EncounterDAO;
/**
* Hibernate specific dao for the {@link EncounterService} All calls should be made on the
* Context.getEncounterService() object
*
* @see EncounterDAO
* @see EncounterService
*/
public class HibernateEncounterDAO implements EncounterDAO {
protected final Log log = LogFactory.getLog(getClass());
/**
* Hibernate session factory
*/
private SessionFactory sessionFactory;
/**
* Set session factory
*
* @param sessionFactory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* @see org.openmrs.api.db.EncounterDAO#saveEncounter(org.openmrs.Encounter)
*/
public Encounter saveEncounter(Encounter encounter) throws DAOException {
sessionFactory.getCurrentSession().saveOrUpdate(encounter);
return encounter;
}
/**
* @see org.openmrs.api.EncounterService#deleteEncounter(org.openmrs.Encounter)
*/
public void deleteEncounter(Encounter encounter) throws DAOException {
sessionFactory.getCurrentSession().delete(encounter);
}
/**
* @see org.openmrs.api.EncounterService#getEncounter(java.lang.Integer)
*/
public Encounter getEncounter(Integer encounterId) throws DAOException {
return (Encounter) sessionFactory.getCurrentSession().get(Encounter.class, encounterId);
}
/**
* @see org.openmrs.api.db.EncounterDAO#getEncountersByPatientId(java.lang.Integer)
*/
@SuppressWarnings("unchecked")
public List<Encounter> getEncountersByPatientId(Integer patientId) throws DAOException {
Criteria crit = sessionFactory.getCurrentSession().createCriteria(Encounter.class).createAlias("patient", "p").add(
Expression.eq("p.patientId", patientId)).add(Expression.eq("voided", false)).addOrder(
Order.desc("encounterDatetime"));
return crit.list();
}
/**
* @see org.openmrs.api.db.EncounterDAO#getEncounters(org.openmrs.Patient, org.openmrs.Location,
* java.util.Date, java.util.Date, java.util.Collection, java.util.Collection,
* java.util.Collection, boolean)
*/
@SuppressWarnings("unchecked")
public List<Encounter> getEncounters(Patient patient, Location location, Date fromDate, Date toDate,
Collection<Form> enteredViaForms, Collection<EncounterType> encounterTypes, Collection<User> providers,
boolean includeVoided) {
Criteria crit = sessionFactory.getCurrentSession().createCriteria(Encounter.class);
if (patient != null && patient.getPatientId() != null) {
crit.add(Expression.eq("patient", patient));
}
if (location != null && location.getLocationId() != null) {
crit.add(Expression.eq("location", location));
}
if (fromDate != null) {
crit.add(Expression.ge("encounterDatetime", fromDate));
}
if (toDate != null) {
crit.add(Expression.le("encounterDatetime", toDate));
}
if (enteredViaForms != null && enteredViaForms.size() > 0) {
crit.add(Expression.in("form", enteredViaForms));
}
if (encounterTypes != null && encounterTypes.size() > 0) {
crit.add(Expression.in("encounterType", encounterTypes));
}
if (providers != null && providers.size() > 0) {
crit.add(Expression.in("provider", providers));
}
if (!includeVoided) {
crit.add(Expression.eq("voided", false));
}
crit.addOrder(Order.asc("encounterDatetime"));
return crit.list();
}
/**
* @see org.openmrs.api.db.EncounterDAO#saveEncounterType(org.openmrs.EncounterType)
*/
public EncounterType saveEncounterType(EncounterType encounterType) {
sessionFactory.getCurrentSession().saveOrUpdate(encounterType);
return encounterType;
}
/**
* @see org.openmrs.api.db.EncounterDAO#deleteEncounterType(org.openmrs.EncounterType)
*/
public void deleteEncounterType(EncounterType encounterType) throws DAOException {
sessionFactory.getCurrentSession().delete(encounterType);
}
/**
* @see org.openmrs.api.EncounterService#getEncounterType(java.lang.Integer)
*/
public EncounterType getEncounterType(Integer encounterTypeId) throws DAOException {
return (EncounterType) sessionFactory.getCurrentSession().get(EncounterType.class, encounterTypeId);
}
/**
* @see org.openmrs.api.EncounterService#getEncounterType(java.lang.String)
*/
public EncounterType getEncounterType(String name) throws DAOException {
Criteria crit = sessionFactory.getCurrentSession().createCriteria(EncounterType.class);
crit.add(Expression.eq("retired", false));
crit.add(Expression.eq("name", name));
EncounterType encounterType = (EncounterType) crit.uniqueResult();
return encounterType;
}
/**
* @see org.openmrs.api.db.EncounterDAO#getAllEncounterTypes(java.lang.Boolean)
*/
@SuppressWarnings("unchecked")
public List<EncounterType> getAllEncounterTypes(Boolean includeRetired) throws DAOException {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(EncounterType.class);
criteria.addOrder(Order.asc("name"));
if (includeRetired == false)
criteria.add(Expression.eq("retired", false));
return criteria.list();
}
/**
* @see org.openmrs.api.db.EncounterDAO#findEncounterTypes(java.lang.String)
*/
@SuppressWarnings("unchecked")
public List<EncounterType> findEncounterTypes(String name) throws DAOException {
return sessionFactory.getCurrentSession().createCriteria(EncounterType.class)
// 'ilike' case insensitive search
.add(Expression.ilike("name", name, MatchMode.START)).addOrder(Order.asc("name")).addOrder(
Order.asc("retired")).list();
}
/**
* @see org.openmrs.api.db.EncounterDAO#getSavedEncounterDatetime(org.openmrs.Encounter)
*/
public Date getSavedEncounterDatetime(Encounter encounter) {
SQLQuery sql = sessionFactory.getCurrentSession().createSQLQuery(
"select encounter_datetime from encounter where encounter_id = :encounterId");
sql.setInteger("encounterId", encounter.getEncounterId());
return (Date) sql.uniqueResult();
}
/**
* @see org.openmrs.api.db.EncounterDAO#getEncounterByUuid(java.lang.String)
*/
public Encounter getEncounterByUuid(String uuid) {
return (Encounter) sessionFactory.getCurrentSession().createQuery("from Encounter e where e.uuid = :uuid")
.setString("uuid", uuid).uniqueResult();
}
/**
* @see org.openmrs.api.db.EncounterDAO#getEncounterTypeByUuid(java.lang.String)
*/
public EncounterType getEncounterTypeByUuid(String uuid) {
return (EncounterType) sessionFactory.getCurrentSession().createQuery("from EncounterType et where et.uuid = :uuid")
.setString("uuid", uuid).uniqueResult();
}
/**
* @see org.openmrs.api.db.EncounterDAO#getEncounters(String, Integer, Integer, boolean)
*/
@SuppressWarnings("unchecked")
public List<Encounter> getEncounters(String query, Integer start, Integer length, boolean includeVoided) {
Criteria criteria = createEncounterByQueryCriteria(query, includeVoided);
if (start != null)
criteria.setFirstResult(start);
if (length != null && length > 0)
criteria.setMaxResults(length);
return criteria.list();
}
/**
* @see org.openmrs.api.db.EncounterDAO#getSavedEncounterLocation(org.openmrs.Encounter)
*/
public Location getSavedEncounterLocation(Encounter encounter) {
SQLQuery sql = sessionFactory.getCurrentSession().createSQLQuery(
"select location_id from encounter where encounter_id = :encounterId");
sql.setInteger("encounterId", encounter.getEncounterId());
return Context.getLocationService().getLocation((Integer) sql.uniqueResult());
}
/**
* @see EncounterDAO#getAllEncounters(org.openmrs.Cohort)
*/
@Override
public Map<Integer, List<Encounter>> getAllEncounters(Cohort patients) {
HashMap<Integer, List<Encounter>> encountersBypatient = new HashMap<Integer, List<Encounter>>();
@SuppressWarnings("unchecked")
List<Encounter> allEncounters = createEncounterCriteria(patients).list();
// set up the return map
for (Encounter encounter : allEncounters) {
Integer patientId = encounter.getPatientId();
List<Encounter> encounters = encountersBypatient.get(patientId);
if (encounters == null) {
encounters = new ArrayList<Encounter>();
}
encounters.add(encounter);
if (!encountersBypatient.containsKey(patientId)) {
encountersBypatient.put(patientId, encounters);
}
}
return encountersBypatient;
}
/**
* Create the criteria for fetching all encounters based on cohort
*
* @param patients
* @return a map of patient with their encounters
*/
private Criteria createEncounterCriteria(Cohort patients) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Encounter.class);
criteria.setCacheMode(org.hibernate.CacheMode.IGNORE);
// only include this where clause if patients were passed in
if (patients != null)
criteria.add(Restrictions.in("patient.personId", patients.getMemberIds()));
criteria.add(Restrictions.eq("voided", false));
criteria.addOrder(org.hibernate.criterion.Order.desc("patient.personId"));
criteria.addOrder(org.hibernate.criterion.Order.desc("encounterDatetime"));
return criteria;
}
/**
* @see org.openmrs.api.db.EncounterDAO#getCountOfEncounters(java.lang.String, boolean)
*/
@Override
public Integer getCountOfEncounters(String query, boolean includeVoided) {
Criteria criteria = createEncounterByQueryCriteria(query, includeVoided);
criteria.setProjection(Projections.rowCount());
return (Integer) criteria.uniqueResult();
}
/**
* Utility method that returns a criteria for searching for patient encounters that match the
* specified search phrase
*
* @param query patient name or identifier
* @param includeVoided Specifies whether voided encounters should be included
* @return
*/
private Criteria createEncounterByQueryCriteria(String query, boolean includeVoided) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Encounter.class);
if (!includeVoided)
criteria.add(Restrictions.eq("voided", false));
criteria = criteria.createCriteria("patient", "pat");
String name = null;
String identifier = null;
if (query.matches(".*\\d+.*")) {
identifier = query;
} else {
// there is no number in the string, search on name
name = query;
}
criteria = new PatientSearchCriteria(sessionFactory, criteria).prepareCriteria(name, identifier,
new ArrayList<PatientIdentifierType>(), false);
return criteria;
}
}