/**
* 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.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.openmrs.Concept;
import org.openmrs.Location;
import org.openmrs.Patient;
import org.openmrs.Visit;
import org.openmrs.VisitAttribute;
import org.openmrs.VisitAttributeType;
import org.openmrs.VisitType;
import org.openmrs.api.APIException;
import org.openmrs.api.VisitService;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.VisitDAO;
import org.openmrs.customdatatype.CustomDatatypeUtil;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.PrivilegeConstants;
import org.openmrs.validator.ValidateUtil;
import org.springframework.transaction.annotation.Transactional;
/**
* Default implementation of the {@link VisitService}. This class should not be used on its own. The
* current OpenMRS implementation should be fetched from the Context.
*
* @since 1.9
*/
@Transactional
public class VisitServiceImpl extends BaseOpenmrsService implements VisitService {
private VisitDAO dao;
/**
* Method used to inject the visit data access object.
*
* @param dao the visit data access object.
*/
public void setVisitDAO(VisitDAO dao) {
this.dao = dao;
}
public VisitDAO getVisitDAO() {
return dao;
}
/**
* @see org.openmrs.api.VisitService#getAllVisitTypes()
*/
@Override
@Transactional(readOnly = true)
public List<VisitType> getAllVisitTypes() {
return getVisitDAO().getAllVisitTypes();
}
/**
* @see org.openmrs.api.VisitService#getAllVisitTypes(boolean)
*/
@Override
@Transactional(readOnly = true)
public List<VisitType> getAllVisitTypes(boolean includeRetired) {
return dao.getAllVisitTypes(includeRetired);
}
/**
* @see org.openmrs.api.VisitService#getVisitType(java.lang.Integer)
*/
@Override
@Transactional(readOnly = true)
public VisitType getVisitType(Integer visitTypeId) {
return getVisitDAO().getVisitType(visitTypeId);
}
/**
* @see org.openmrs.api.VisitService#getVisitTypeByUuid(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public VisitType getVisitTypeByUuid(String uuid) {
return getVisitDAO().getVisitTypeByUuid(uuid);
}
/**
* @see org.openmrs.api.VisitService#getVisitTypes(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public List<VisitType> getVisitTypes(String fuzzySearchPhrase) {
return getVisitDAO().getVisitTypes(fuzzySearchPhrase);
}
/**
* @see org.openmrs.api.VisitService#saveVisitType(org.openmrs.VisitType)
*/
@Override
public VisitType saveVisitType(VisitType visitType) throws APIException {
ValidateUtil.validate(visitType);
return getVisitDAO().saveVisitType(visitType);
}
/**
* @see org.openmrs.api.VisitService#retireVisitType(org.openmrs.VisitType, java.lang.String)
*/
@Override
public VisitType retireVisitType(VisitType visitType, String reason) {
return Context.getVisitService().saveVisitType(visitType);
}
/**
* @see org.openmrs.api.VisitService#unretireVisitType(org.openmrs.VisitType)
*/
@Override
public VisitType unretireVisitType(VisitType visitType) {
return Context.getVisitService().saveVisitType(visitType);
}
/**
* @see org.openmrs.api.VisitService#purgeVisitType(org.openmrs.VisitType)
*/
@Override
public void purgeVisitType(VisitType visitType) {
getVisitDAO().purgeVisitType(visitType);
}
/**
* @see org.openmrs.api.VisitService#getAllVisits()
*/
@Override
@Transactional(readOnly = true)
public List<Visit> getAllVisits() throws APIException {
return dao.getVisits(null, null, null, null, null, null, null, null, null, true, false);
}
/**
* @see org.openmrs.api.VisitService#getVisit(java.lang.Integer)
*/
@Override
@Transactional(readOnly = true)
public Visit getVisit(Integer visitId) throws APIException {
return dao.getVisit(visitId);
}
/**
* @see org.openmrs.api.VisitService#getVisitByUuid(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public Visit getVisitByUuid(String uuid) throws APIException {
return dao.getVisitByUuid(uuid);
}
/**
* @see org.openmrs.api.VisitService#saveVisit(org.openmrs.Visit)
*/
@Override
public Visit saveVisit(Visit visit) throws APIException {
if (visit.getVisitId() == null) {
Context.requirePrivilege(PrivilegeConstants.ADD_VISITS);
} else {
Context.requirePrivilege(PrivilegeConstants.EDIT_VISITS);
}
CustomDatatypeUtil.saveAttributesIfNecessary(visit);
return dao.saveVisit(visit);
}
/**
* @see org.openmrs.api.VisitService#endVisit(org.openmrs.Visit, java.util.Date)
*/
@Override
public Visit endVisit(Visit visit, Date stopDate) {
if (stopDate == null) {
stopDate = new Date();
}
visit.setStopDatetime(stopDate);
return Context.getVisitService().saveVisit(visit);
}
/**
* @see org.openmrs.api.VisitService#voidVisit(org.openmrs.Visit, java.lang.String)
*/
@Override
public Visit voidVisit(Visit visit, String reason) throws APIException {
return dao.saveVisit(visit);
}
/**
* @see org.openmrs.api.VisitService#unvoidVisit(org.openmrs.Visit)
*/
@Override
public Visit unvoidVisit(Visit visit) throws APIException {
return Context.getVisitService().saveVisit(visit);
}
/**
* @see org.openmrs.api.VisitService#purgeVisit(org.openmrs.Visit)
*/
@Override
public void purgeVisit(Visit visit) throws APIException {
if (visit.getVisitId() == null) {
return;
}
if (!Context.getEncounterService().getEncountersByVisit(visit, true).isEmpty()) {
throw new APIException("Visit.purge.inUse", (Object[]) null);
}
dao.deleteVisit(visit);
}
/**
* @see org.openmrs.api.VisitService#getVisits(Collection, Collection, Collection, Collection, Date, Date, Date, Date, Map, boolean, boolean)
*/
@Override
@Transactional(readOnly = true)
public List<Visit> getVisits(Collection<VisitType> visitTypes, Collection<Patient> patients,
Collection<Location> locations, Collection<Concept> indications, Date minStartDatetime, Date maxStartDatetime,
Date minEndDatetime, Date maxEndDatetime, Map<VisitAttributeType, Object> attributeValues,
boolean includeInactive, boolean includeVoided) throws APIException {
Map<VisitAttributeType, String> serializedAttributeValues = CustomDatatypeUtil.getValueReferences(attributeValues);
return dao.getVisits(visitTypes, patients, locations, indications, minStartDatetime, maxStartDatetime,
minEndDatetime, maxEndDatetime, serializedAttributeValues, includeInactive, includeVoided);
}
/**
* @see org.openmrs.api.VisitService#getVisitsByPatient(org.openmrs.Patient)
*/
@Override
@Transactional(readOnly = true)
public List<Visit> getVisitsByPatient(Patient patient) throws APIException {
//Don't bother to hit the database
if (patient == null || patient.getId() == null) {
return Collections.emptyList();
}
return Context.getVisitService().getVisits(null, Collections.singletonList(patient), null, null, null, null, null,
null, null, true, false);
}
/**
* @see org.openmrs.api.VisitService#getActiveVisitsByPatient(org.openmrs.Patient)
*/
@Override
@Transactional(readOnly = true)
public List<Visit> getActiveVisitsByPatient(Patient patient) throws APIException {
return Context.getVisitService().getVisitsByPatient(patient, false, false);
}
/**
* @see org.openmrs.api.VisitService#getVisitsByPatient(org.openmrs.Patient, boolean, boolean)
*/
@Override
@Transactional(readOnly = true)
public List<Visit> getVisitsByPatient(Patient patient, boolean includeInactive, boolean includeVoided)
throws APIException {
if (patient == null || patient.getId() == null) {
return Collections.emptyList();
}
return dao.getVisits(null, Collections.singletonList(patient), null, null, null, null, null, null, null,
includeInactive, includeVoided);
}
/**
* @see org.openmrs.api.VisitService#getAllVisitAttributeTypes()
*/
@Override
@Transactional(readOnly = true)
public List<VisitAttributeType> getAllVisitAttributeTypes() {
return dao.getAllVisitAttributeTypes();
}
/**
* @see org.openmrs.api.VisitService#getVisitAttributeType(java.lang.Integer)
*/
@Override
@Transactional(readOnly = true)
public VisitAttributeType getVisitAttributeType(Integer id) {
return dao.getVisitAttributeType(id);
}
/**
* @see org.openmrs.api.VisitService#getVisitAttributeTypeByUuid(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public VisitAttributeType getVisitAttributeTypeByUuid(String uuid) {
return dao.getVisitAttributeTypeByUuid(uuid);
}
/**
* @see org.openmrs.api.VisitService#saveVisitAttributeType(org.openmrs.VisitAttributeType)
*/
@Override
public VisitAttributeType saveVisitAttributeType(VisitAttributeType visitAttributeType) {
return dao.saveVisitAttributeType(visitAttributeType);
}
/**
* @see org.openmrs.api.VisitService#retireVisitAttributeType(org.openmrs.VisitAttributeType,
* java.lang.String)
*/
@Override
public VisitAttributeType retireVisitAttributeType(VisitAttributeType visitAttributeType, String reason) {
return dao.saveVisitAttributeType(visitAttributeType);
}
/**
* @see org.openmrs.api.VisitService#unretireVisitAttributeType(org.openmrs.VisitAttributeType)
*/
@Override
public VisitAttributeType unretireVisitAttributeType(VisitAttributeType visitAttributeType) {
return Context.getVisitService().saveVisitAttributeType(visitAttributeType);
}
/**
* @see org.openmrs.api.VisitService#purgeVisitAttributeType(org.openmrs.VisitAttributeType)
*/
@Override
public void purgeVisitAttributeType(VisitAttributeType visitAttributeType) {
dao.deleteVisitAttributeType(visitAttributeType);
}
/**
* @see org.openmrs.api.VisitService#getVisitAttributeByUuid(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public VisitAttribute getVisitAttributeByUuid(String uuid) {
return dao.getVisitAttributeByUuid(uuid);
}
/**
* @see org.openmrs.api.VisitService#stopVisits(Date)
*/
@Override
public void stopVisits(Date maximumStartDate) {
final List<VisitType> visitTypesToStop = getVisitTypesToStop();
if (maximumStartDate == null) {
maximumStartDate = new Date();
}
if (visitTypesToStop.isEmpty()) {
return;
}
int counter = 0;
Date stopDate = new Date();
Visit nextVisit = dao.getNextVisit(null, visitTypesToStop, maximumStartDate);
while (nextVisit != null) {
nextVisit.setStopDatetime(stopDate);
dao.saveVisit(nextVisit);
if (counter++ > 50) {
//ensure changes are persisted to DB before reclaiming memory
Context.flushSession();
Context.clearSession();
counter = 0;
}
nextVisit = dao.getNextVisit(nextVisit, visitTypesToStop, maximumStartDate);
}
}
private List<VisitType> getVisitTypesToStop() {
String gpValue = Context.getAdministrationService().getGlobalProperty(OpenmrsConstants.GP_VISIT_TYPES_TO_AUTO_CLOSE);
if (StringUtils.isBlank(gpValue)) {
return Collections.emptyList();
} else {
String[] visitTypeNames = getVisitTypeNamesFromGlobalPropertyValue(gpValue);
return getVisitTypesFromVisitTypeNames(visitTypeNames);
}
}
private String[] getVisitTypeNamesFromGlobalPropertyValue(String commaSeparatedNames) {
String[] result = StringUtils.split(commaSeparatedNames.trim(), ",");
for (int i = 0; i < result.length; i++) {
String currName = result[i];
result[i] = currName.trim().toLowerCase();
}
return result;
}
private List<VisitType> getVisitTypesFromVisitTypeNames(String[] visitTypeNames) {
List<VisitType> result = new ArrayList<VisitType>();
for (VisitType visitType : Context.getVisitService().getAllVisitTypes()) {
if (ArrayUtils.contains(visitTypeNames, visitType.getName().toLowerCase())) {
result.add(visitType);
}
}
return result;
}
}