org.openmrs.api.db.hibernate.HibernateEncounterDAO.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.api.db.hibernate.HibernateEncounterDAO.java

Source

/**
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
 *
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
 * graphic logo is a trademark of OpenMRS Inc.
 */
package org.openmrs.api.db.hibernate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
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.Conjunction;
import org.hibernate.criterion.Disjunction;
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.EncounterRole;
import org.openmrs.EncounterType;
import org.openmrs.Form;
import org.openmrs.Location;
import org.openmrs.Patient;
import org.openmrs.PatientIdentifierType;
import org.openmrs.Provider;
import org.openmrs.Visit;
import org.openmrs.VisitType;
import org.openmrs.api.EncounterService;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.DAOException;
import org.openmrs.api.db.EncounterDAO;
import org.openmrs.parameter.EncounterSearchCriteria;

/**
 * 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(Restrictions.eq("p.patientId", patientId))
                .add(Restrictions.eq("voided", false)).addOrder(Order.desc("encounterDatetime"));

        return crit.list();
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncounters(org.openmrs.parameter.EncounterSearchCriteria)
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Encounter> getEncounters(EncounterSearchCriteria searchCriteria) {
        Criteria crit = sessionFactory.getCurrentSession().createCriteria(Encounter.class);

        if (searchCriteria.getPatient() != null && searchCriteria.getPatient().getPatientId() != null) {
            crit.add(Restrictions.eq("patient", searchCriteria.getPatient()));
        }
        if (searchCriteria.getLocation() != null && searchCriteria.getLocation().getLocationId() != null) {
            crit.add(Restrictions.eq("location", searchCriteria.getLocation()));
        }
        if (searchCriteria.getFromDate() != null) {
            crit.add(Restrictions.ge("encounterDatetime", searchCriteria.getFromDate()));
        }
        if (searchCriteria.getToDate() != null) {
            crit.add(Restrictions.le("encounterDatetime", searchCriteria.getToDate()));
        }
        if (searchCriteria.getDateChanged() != null) {
            crit.add(Restrictions.or(
                    Restrictions.and(Restrictions.isNull("dateChanged"),
                            Restrictions.ge("dateCreated", searchCriteria.getDateChanged())),
                    Restrictions.ge("dateChanged", searchCriteria.getDateChanged())));
        }
        if (searchCriteria.getEnteredViaForms() != null && searchCriteria.getEnteredViaForms().size() > 0) {
            crit.add(Restrictions.in("form", searchCriteria.getEnteredViaForms()));
        }
        if (searchCriteria.getEncounterTypes() != null && searchCriteria.getEncounterTypes().size() > 0) {
            crit.add(Restrictions.in("encounterType", searchCriteria.getEncounterTypes()));
        }
        if (searchCriteria.getProviders() != null && searchCriteria.getProviders().size() > 0) {
            crit.createAlias("encounterProviders", "ep");
            crit.add(Restrictions.in("ep.provider", searchCriteria.getProviders()));
        }
        if (searchCriteria.getVisitTypes() != null && searchCriteria.getVisitTypes().size() > 0) {
            crit.createAlias("visit", "v");
            crit.add(Restrictions.in("v.visitType", searchCriteria.getVisitTypes()));
        }
        if (searchCriteria.getVisits() != null && searchCriteria.getVisits().size() > 0) {
            crit.add(Restrictions.in("visit", searchCriteria.getVisits()));
        }
        if (!searchCriteria.getIncludeVoided()) {
            crit.add(Restrictions.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(Restrictions.eq("retired", false));
        crit.add(Restrictions.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) {
            criteria.add(Restrictions.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(Restrictions.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 getClassByUuid(Encounter.class, uuid);
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncounterTypeByUuid(java.lang.String)
     */
    public EncounterType getEncounterTypeByUuid(String uuid) {
        return getClassByUuid(EncounterType.class, uuid);
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncounters(String, Integer, Integer, Integer,
     *      boolean)
     */
    @SuppressWarnings("unchecked")
    public List<Encounter> getEncounters(String query, Integer patientId, Integer start, Integer length,
            boolean includeVoided) {
        if (StringUtils.isBlank(query) && patientId == null) {
            return Collections.emptyList();
        }

        Criteria criteria = createEncounterByQueryCriteria(query, patientId, includeVoided, true);

        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) {
        Map<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.getPatient().getPersonId();
            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,
     *      java.lang.Integer, boolean)
     */
    @Override
    public Long getCountOfEncounters(String query, Integer patientId, boolean includeVoided) {
        Criteria criteria = createEncounterByQueryCriteria(query, patientId, includeVoided, false);

        criteria.setProjection(Projections.countDistinct("enc.encounterId"));
        return (Long) 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 patientId the patient id
     * @param includeVoided Specifies whether voided encounters should be included
     * @param orderByNames specifies whether the encounters should be ordered by person names
     * @return Criteria
     */
    private Criteria createEncounterByQueryCriteria(String query, Integer patientId, boolean includeVoided,
            boolean orderByNames) {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Encounter.class, "enc");
        if (!includeVoided) {
            criteria.add(Restrictions.eq("enc.voided", false));
        }

        criteria = criteria.createCriteria("patient", "pat");
        if (patientId != null) {
            criteria.add(Restrictions.eq("pat.patientId", patientId));
            if (StringUtils.isNotBlank(query)) {
                criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
                //match on location.name, encounterType.name, form.name
                //provider.name, provider.identifier, provider.person.names
                MatchMode mode = MatchMode.ANYWHERE;
                criteria.createAlias("enc.location", "loc");
                criteria.createAlias("enc.encounterType", "encType");
                criteria.createAlias("enc.form", "form");
                criteria.createAlias("enc.encounterProviders", "enc_prov");
                criteria.createAlias("enc_prov.provider", "prov");
                criteria.createAlias("prov.person", "person", Criteria.LEFT_JOIN);
                criteria.createAlias("person.names", "personName", Criteria.LEFT_JOIN);

                Disjunction or = Restrictions.disjunction();
                or.add(Restrictions.ilike("loc.name", query, mode));
                or.add(Restrictions.ilike("encType.name", query, mode));
                or.add(Restrictions.ilike("form.name", query, mode));
                or.add(Restrictions.ilike("prov.name", query, mode));
                or.add(Restrictions.ilike("prov.identifier", query, mode));

                String[] splitNames = query.split(" ");
                Disjunction nameOr = Restrictions.disjunction();
                for (String splitName : splitNames) {
                    nameOr.add(Restrictions.ilike("personName.givenName", splitName, mode));
                    nameOr.add(Restrictions.ilike("personName.middleName", splitName, mode));
                    nameOr.add(Restrictions.ilike("personName.familyName", splitName, mode));
                    nameOr.add(Restrictions.ilike("personName.familyName2", splitName, mode));
                }
                //OUTPUT for provider criteria: 
                //prov.name like '%query%' OR prov.identifier like '%query%'
                //OR ( personName.voided = false 
                //       AND (  personName.givenName like '%query%' 
                //         OR personName.middleName like '%query%' 
                //         OR personName.familyName like '%query%'
                //         OR personName.familyName2 like '%query%'
                //         )
                //    )
                Conjunction personNameConjuction = Restrictions.conjunction();
                personNameConjuction.add(Restrictions.eq("personName.voided", false));
                personNameConjuction.add(nameOr);

                or.add(personNameConjuction);

                criteria.add(or);
            }
        } else {
            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, orderByNames, false);
        }

        return criteria;
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncountersByVisit(Visit, boolean)
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<Encounter> getEncountersByVisit(Visit visit, boolean includeVoided) {
        Criteria crit = sessionFactory.getCurrentSession().createCriteria(Encounter.class)
                .add(Restrictions.eq("visit", visit));
        if (!includeVoided) {
            crit.add(Restrictions.eq("voided", false));
        }
        crit.addOrder(Order.asc("encounterDatetime"));

        return crit.list();
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#saveEncounterRole(EncounterRole encounterRole)
     */
    @Override
    public EncounterRole saveEncounterRole(EncounterRole encounterRole) throws DAOException {
        sessionFactory.getCurrentSession().saveOrUpdate(encounterRole);
        return encounterRole;
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#deleteEncounterRole(org.openmrs.EncounterRole)
     */
    @Override
    public void deleteEncounterRole(EncounterRole encounterRole) throws DAOException {
        sessionFactory.getCurrentSession().delete(encounterRole);
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncounterRole(Integer)
     */
    @Override
    public EncounterRole getEncounterRole(Integer encounterRoleId) throws DAOException {
        return (EncounterRole) sessionFactory.getCurrentSession().get(EncounterRole.class, encounterRoleId);
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncounterRoleByUuid(String)
     */
    @Override
    public EncounterRole getEncounterRoleByUuid(String uuid) {
        return getClassByUuid(EncounterRole.class, uuid);
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getAllEncounterRoles(boolean)
     */
    @Override
    public List<EncounterRole> getAllEncounterRoles(boolean includeRetired) throws DAOException {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(EncounterRole.class);
        return includeRetired ? criteria.list() : criteria.add(Restrictions.eq("retired", includeRetired)).list();
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncounterRoleByName(String)
     */
    @Override
    public EncounterRole getEncounterRoleByName(String name) throws DAOException {
        return (EncounterRole) sessionFactory.getCurrentSession().createCriteria(EncounterRole.class)
                .add(Restrictions.eq("name", name)).uniqueResult();

    }

    /**
     * Convenience method since this DAO fetches several different domain objects by uuid
     *
     * @param uuid uuid to fetch
     * @param table a simple classname (e.g. "Encounter")
     * @return
     */
    @SuppressWarnings("unchecked")
    private <T> T getClassByUuid(Class<T> clazz, String uuid) {
        return (T) sessionFactory.getCurrentSession().createCriteria(clazz).add(Restrictions.eq("uuid", uuid))
                .uniqueResult();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Encounter> getEncountersNotAssignedToAnyVisit(Patient patient) throws DAOException {
        return sessionFactory.getCurrentSession().createCriteria(Encounter.class)
                .add(Restrictions.eq("patient", patient)).add(Restrictions.isNull("visit"))
                .add(Restrictions.eq("voided", false)).addOrder(Order.desc("encounterDatetime")).setMaxResults(100)
                .list();
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncountersByVisitsAndPatient(org.openmrs.Patient,
     *      boolean, java.lang.String, java.lang.Integer, java.lang.Integer)
     */
    @Override
    public List<Encounter> getEncountersByVisitsAndPatient(Patient patient, boolean includeVoided, String query,
            Integer start, Integer length) {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Encounter.class);
        addEncountersByPatientCriteria(criteria, patient, includeVoided, query);

        @SuppressWarnings("unchecked")
        List<Encounter> encounters = criteria.list();

        criteria = sessionFactory.getCurrentSession().createCriteria(Visit.class);
        addEmptyVisitsByPatientCriteria(criteria, patient, includeVoided, query);

        @SuppressWarnings("unchecked")
        List<Visit> emptyVisits = criteria.list();

        if (!emptyVisits.isEmpty()) {
            for (Visit emptyVisit : emptyVisits) {
                Encounter mockEncounter = new Encounter();
                mockEncounter.setVisit(emptyVisit);
                encounters.add(mockEncounter);
            }

            Collections.sort(encounters, new Comparator<Encounter>() {

                @Override
                public int compare(Encounter o1, Encounter o2) {
                    Date o1Date = (o1.getVisit() != null) ? o1.getVisit().getStartDatetime()
                            : o1.getEncounterDatetime();
                    Date o2Date = (o2.getVisit() != null) ? o2.getVisit().getStartDatetime()
                            : o2.getEncounterDatetime();
                    return o2Date.compareTo(o1Date);
                }
            });
        }

        if (start == null) {
            start = 0;
        }
        if (length == null) {
            length = encounters.size();
        }
        int end = start + length;
        if (end > encounters.size()) {
            end = encounters.size();
        }

        return encounters.subList(start, end);
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncountersByVisitsAndPatientCount(org.openmrs.Patient,
     *      boolean, java.lang.String)
     */
    @Override
    public Integer getEncountersByVisitsAndPatientCount(Patient patient, boolean includeVoided, String query) {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Visit.class);
        addEmptyVisitsByPatientCriteria(criteria, patient, includeVoided, query);

        criteria.setProjection(Projections.rowCount());
        Integer count = ((Number) criteria.uniqueResult()).intValue();

        criteria = sessionFactory.getCurrentSession().createCriteria(Encounter.class);
        addEncountersByPatientCriteria(criteria, patient, includeVoided, query);

        criteria.setProjection(Projections.rowCount());
        count = count + ((Number) criteria.uniqueResult()).intValue();

        return count;
    }

    private void addEmptyVisitsByPatientCriteria(Criteria criteria, Patient patient, boolean includeVoided,
            String query) {
        criteria.add(Restrictions.eq("patient", patient));
        criteria.add(Restrictions.isEmpty("encounters"));

        if (!includeVoided) {
            criteria.add(Restrictions.eq("voided", includeVoided));
        }

        if (query != null && !StringUtils.isBlank(query)) {
            criteria.createAlias("visitType", "visitType", Criteria.LEFT_JOIN);
            criteria.createAlias("location", "location", Criteria.LEFT_JOIN);

            Disjunction or = Restrictions.disjunction();
            criteria.add(or);
            or.add(Restrictions.ilike("visitType.name", query, MatchMode.ANYWHERE));
            or.add(Restrictions.ilike("location.name", query, MatchMode.ANYWHERE));
        }

        criteria.addOrder(Order.desc("startDatetime"));
        criteria.addOrder(Order.desc("visitId"));
    }

    private void addEncountersByPatientCriteria(Criteria criteria, Patient patient, boolean includeVoided,
            String query) {
        criteria.add(Restrictions.eq("patient", patient));
        criteria.createAlias("visit", "visit", Criteria.LEFT_JOIN);

        if (!includeVoided) {
            criteria.add(Restrictions.eq("voided", includeVoided));
        }

        if (query != null && !StringUtils.isBlank(query)) {
            criteria.createAlias("visit.visitType", "visitType", Criteria.LEFT_JOIN);
            criteria.createAlias("visit.location", "visitLocation", Criteria.LEFT_JOIN);
            criteria.createAlias("location", "location", Criteria.LEFT_JOIN);
            criteria.createAlias("encounterType", "encounterType", Criteria.LEFT_JOIN);

            Disjunction or = Restrictions.disjunction();
            criteria.add(or);
            or.add(Restrictions.ilike("visitType.name", query, MatchMode.ANYWHERE));
            or.add(Restrictions.ilike("visitLocation.name", query, MatchMode.ANYWHERE));
            or.add(Restrictions.ilike("location.name", query, MatchMode.ANYWHERE));
            or.add(Restrictions.ilike("encounterType.name", query, MatchMode.ANYWHERE));
        }

        criteria.addOrder(Order.desc("visit.startDatetime"));
        criteria.addOrder(Order.desc("visit.visitId"));
        criteria.addOrder(Order.desc("encounterDatetime"));
        criteria.addOrder(Order.desc("encounterId"));
    }

    /**
     * @see org.openmrs.api.db.EncounterDAO#getEncounterRolesByName(String)
     */

    @Override
    public List<EncounterRole> getEncounterRolesByName(String name) throws DAOException {
        return sessionFactory.getCurrentSession().createCriteria(EncounterRole.class)
                .add(Restrictions.eq("name", name)).list();
    }
}