/** * 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.Date; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.openmrs.Address; import org.openmrs.Location; import org.openmrs.LocationAttribute; import org.openmrs.LocationAttributeType; import org.openmrs.LocationTag; import org.openmrs.api.APIException; import org.openmrs.api.LocationService; import org.openmrs.api.context.Context; import org.openmrs.api.db.LocationDAO; import org.openmrs.customdatatype.CustomDatatypeUtil; import org.openmrs.util.OpenmrsConstants; import org.openmrs.util.OpenmrsUtil; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; /** * Default implementation of the {@link LocationService} * <p> * This class should not be instantiated alone, get a service class from the Context: * Context.getLocationService(); * * @see org.openmrs.api.context.Context * @see org.openmrs.api.LocationService * @see org.openmrs.Location */ @Transactional public class LocationServiceImpl extends BaseOpenmrsService implements LocationService { private LocationDAO dao; /** * @see org.openmrs.api.LocationService#setLocationDAO(org.openmrs.api.db.LocationDAO) */ @Override public void setLocationDAO(LocationDAO dao) { this.dao = dao; } /** * @see org.openmrs.api.LocationService#saveLocation(org.openmrs.Location) */ @Override public Location saveLocation(Location location) throws APIException { if (location.getName() == null) { throw new APIException("Location.name.required", (Object[]) null); } // Check for transient tags. If found, try to match by name and overwrite, otherwise throw exception. if (location.getTags() != null) { for (LocationTag tag : location.getTags()) { // only check transient (aka non-precreated) location tags if (tag.getLocationTagId() == null) { if (!StringUtils.hasLength(tag.getName())) { throw new APIException("Location.tag.name.required", (Object[]) null); } LocationTag existing = Context.getLocationService().getLocationTagByName(tag.getName()); if (existing != null) { location.removeTag(tag); location.addTag(existing); } else { throw new APIException("Location.cannot.add.transient.tags", (Object[]) null); } } } } CustomDatatypeUtil.saveAttributesIfNecessary(location); return dao.saveLocation(location); } /** * @see org.openmrs.api.LocationService#getLocation(java.lang.Integer) */ @Override @Transactional(readOnly = true) public Location getLocation(Integer locationId) throws APIException { return dao.getLocation(locationId); } /** * @see org.openmrs.api.LocationService#getLocation(java.lang.String) */ @Override @Transactional(readOnly = true) public Location getLocation(String name) throws APIException { return dao.getLocation(name); } /** * @see org.openmrs.api.LocationService#getDefaultLocation() */ @Override @Transactional(readOnly = true) public Location getDefaultLocation() throws APIException { Location location = null; String locationGP = Context.getAdministrationService().getGlobalProperty( OpenmrsConstants.GLOBAL_PROPERTY_DEFAULT_LOCATION_NAME); if (StringUtils.hasText(locationGP)) { location = Context.getLocationService().getLocation(locationGP); } //Try to look up 'Unknown Location' in case the global property is something else if (location == null && (!StringUtils.hasText(locationGP) || !"Unknown Location".equalsIgnoreCase(locationGP))) { location = Context.getLocationService().getLocation("Unknown Location"); } // If Unknown Location does not exist, try Unknown if the global property was different if (location == null && (!StringUtils.hasText(locationGP) || !"Unknown".equalsIgnoreCase(locationGP))) { location = Context.getLocationService().getLocation("Unknown"); } // If neither exist, get the first available location if (location == null) { location = Context.getLocationService().getLocation(Integer.valueOf(1)); } return location; } /** * @see org.openmrs.api.LocationService#getLocationByUuid(java.lang.String) */ @Override @Transactional(readOnly = true) public Location getLocationByUuid(String uuid) throws APIException { return dao.getLocationByUuid(uuid); } /** * @see org.openmrs.api.LocationService#getLocationTagByUuid(java.lang.String) */ @Override @Transactional(readOnly = true) public LocationTag getLocationTagByUuid(String uuid) throws APIException { return dao.getLocationTagByUuid(uuid); } /** * @see org.openmrs.api.LocationService#getAllLocations() */ @Override @Transactional(readOnly = true) public List<Location> getAllLocations() throws APIException { return dao.getAllLocations(true); } /** * @see org.openmrs.api.LocationService#getAllLocations(boolean) */ @Override @Transactional(readOnly = true) public List<Location> getAllLocations(boolean includeRetired) throws APIException { return dao.getAllLocations(includeRetired); } /** * @see org.openmrs.api.LocationService#getLocations(java.lang.String) */ @Override @Transactional(readOnly = true) public List<Location> getLocations(String nameFragment) throws APIException { return Context.getLocationService().getLocations(nameFragment, null, null, false, null, null); } /** * @see org.openmrs.api.LocationService#getLocationsByTag(LocationTag) */ @Override @Transactional(readOnly = true) public List<Location> getLocationsByTag(LocationTag tag) throws APIException { List<Location> locations = new ArrayList<Location>(); for (Location l : dao.getAllLocations(false)) { if (l.getTags().contains(tag)) { locations.add(l); } } return locations; } /** * @see org.openmrs.api.LocationService#getLocationsHavingAllTags(List) */ @Override @Transactional(readOnly = true) public List<Location> getLocationsHavingAllTags(List<LocationTag> tags) throws APIException { return CollectionUtils.isEmpty(tags) ? getAllLocations(false) : dao.getLocationsHavingAllTags(tags); } /** * @see org.openmrs.api.LocationService#getLocationsHavingAnyTag(List) */ @Override @Transactional(readOnly = true) public List<Location> getLocationsHavingAnyTag(List<LocationTag> tags) throws APIException { List<Location> locations = new ArrayList<Location>(); for (Location loc : dao.getAllLocations(false)) { for (LocationTag t : tags) { if (loc.getTags().contains(t) && !locations.contains(loc)) { locations.add(loc); } } } return locations; } /** * @see org.openmrs.api.LocationService#retireLocation(Location, String) */ @Override public Location retireLocation(Location location, String reason) throws APIException { location.setRetired(true); location.setRetireReason(reason); return Context.getLocationService().saveLocation(location); } /** * @see org.openmrs.api.LocationService#unretireLocation(org.openmrs.Location) */ @Override public Location unretireLocation(Location location) throws APIException { location.setRetired(false); return Context.getLocationService().saveLocation(location); } /** * @see org.openmrs.api.LocationService#purgeLocation(org.openmrs.Location) */ @Override public void purgeLocation(Location location) throws APIException { dao.deleteLocation(location); } /** * @see org.openmrs.api.LocationService#saveLocationTag(org.openmrs.LocationTag) */ @Override public LocationTag saveLocationTag(LocationTag tag) throws APIException { return dao.saveLocationTag(tag); } /** * @see org.openmrs.api.LocationService#getLocationTag(java.lang.Integer) */ @Override @Transactional(readOnly = true) public LocationTag getLocationTag(Integer locationTagId) throws APIException { return dao.getLocationTag(locationTagId); } /** * @see org.openmrs.api.LocationService#getLocationTagByName(java.lang.String) */ @Override @Transactional(readOnly = true) public LocationTag getLocationTagByName(String tag) throws APIException { return dao.getLocationTagByName(tag); } /** * @see org.openmrs.api.LocationService#getAllLocationTags() */ @Override @Transactional(readOnly = true) public List<LocationTag> getAllLocationTags() throws APIException { return dao.getAllLocationTags(true); } /** * @see org.openmrs.api.LocationService#getAllLocationTags(boolean) */ @Override @Transactional(readOnly = true) public List<LocationTag> getAllLocationTags(boolean includeRetired) throws APIException { return dao.getAllLocationTags(includeRetired); } /** * @see org.openmrs.api.LocationService#getLocationTags(java.lang.String) */ @Override @Transactional(readOnly = true) public List<LocationTag> getLocationTags(String search) throws APIException { if (StringUtils.isEmpty(search)) { return Context.getLocationService().getAllLocationTags(true); } return dao.getLocationTags(search); } /** * @see org.openmrs.api.LocationService#retireLocationTag(LocationTag, String) */ @Override public LocationTag retireLocationTag(LocationTag tag, String reason) throws APIException { if (tag.getRetired()) { return tag; } else { if (reason == null) { throw new APIException("Location.retired.reason.required", (Object[]) null); } tag.setRetired(true); tag.setRetireReason(reason); tag.setRetiredBy(Context.getAuthenticatedUser()); tag.setDateRetired(new Date()); return Context.getLocationService().saveLocationTag(tag); } } /** * @see org.openmrs.api.LocationService#unretireLocationTag(org.openmrs.LocationTag) */ @Override public LocationTag unretireLocationTag(LocationTag tag) throws APIException { tag.setRetired(false); tag.setRetireReason(null); tag.setRetiredBy(null); tag.setDateRetired(null); return Context.getLocationService().saveLocationTag(tag); } /** * @see org.openmrs.api.LocationService#purgeLocationTag(org.openmrs.LocationTag) */ @Override public void purgeLocationTag(LocationTag tag) throws APIException { dao.deleteLocationTag(tag); } /** * @see org.openmrs.api.LocationService#getCountOfLocations(String, Boolean) */ @Override @Transactional(readOnly = true) public Integer getCountOfLocations(String nameFragment, Boolean includeRetired) { return OpenmrsUtil.convertToInteger(dao.getCountOfLocations(nameFragment, includeRetired)); } /** * @see LocationService#getLocations(String, org.openmrs.Location, java.util.Map, boolean, * Integer, Integer) */ @Override public List<Location> getLocations(String nameFragment, Location parent, Map<LocationAttributeType, Object> attributeValues, boolean includeRetired, Integer start, Integer length) { Map<LocationAttributeType, String> serializedAttributeValues = CustomDatatypeUtil .getValueReferences(attributeValues); return dao.getLocations(nameFragment, parent, serializedAttributeValues, includeRetired, start, length); } /** * @see LocationService#getRootLocations(boolean) */ @Override @Transactional(readOnly = true) public List<Location> getRootLocations(boolean includeRetired) throws APIException { return dao.getRootLocations(includeRetired); } /** * @see org.openmrs.api.LocationService#getPossibleAddressValues(Address, String) */ @Override public List<String> getPossibleAddressValues(Address incomplete, String fieldName) throws APIException { // not implemented by default return null; } /** * @see org.openmrs.api.LocationService#getAllLocationAttributeTypes() */ @Override @Transactional(readOnly = true) public List<LocationAttributeType> getAllLocationAttributeTypes() { return dao.getAllLocationAttributeTypes(); } /** * @see org.openmrs.api.LocationService#getLocationAttributeType(java.lang.Integer) */ @Override @Transactional(readOnly = true) public LocationAttributeType getLocationAttributeType(Integer id) { return dao.getLocationAttributeType(id); } /** * @see org.openmrs.api.LocationService#getLocationAttributeTypeByUuid(java.lang.String) */ @Override @Transactional(readOnly = true) public LocationAttributeType getLocationAttributeTypeByUuid(String uuid) { return dao.getLocationAttributeTypeByUuid(uuid); } /** * @see org.openmrs.api.LocationService#saveLocationAttributeType(org.openmrs.LocationAttributeType) */ @Override public LocationAttributeType saveLocationAttributeType(LocationAttributeType locationAttributeType) { return dao.saveLocationAttributeType(locationAttributeType); } /** * @see org.openmrs.api.LocationService#retireLocationAttributeType(org.openmrs.LocationAttributeType, * java.lang.String) */ @Override public LocationAttributeType retireLocationAttributeType(LocationAttributeType locationAttributeType, String reason) { return dao.saveLocationAttributeType(locationAttributeType); } /** * @see org.openmrs.api.LocationService#unretireLocationAttributeType(org.openmrs.LocationAttributeType) */ @Override public LocationAttributeType unretireLocationAttributeType(LocationAttributeType locationAttributeType) { return Context.getLocationService().saveLocationAttributeType(locationAttributeType); } /** * @see org.openmrs.api.LocationService#purgeLocationAttributeType(org.openmrs.LocationAttributeType) */ @Override public void purgeLocationAttributeType(LocationAttributeType locationAttributeType) { dao.deleteLocationAttributeType(locationAttributeType); } /** * @see org.openmrs.api.LocationService#getLocationAttributeByUuid(java.lang.String) */ @Override @Transactional(readOnly = true) public LocationAttribute getLocationAttributeByUuid(String uuid) { return dao.getLocationAttributeByUuid(uuid); } /** * @see org.openmrs.api.LocationService#getAddressTemplate() */ @Override @Transactional(readOnly = true) public String getAddressTemplate() throws APIException { String addressTemplate = Context.getAdministrationService().getGlobalProperty( OpenmrsConstants.GLOBAL_PROPERTY_ADDRESS_TEMPLATE); if (!StringUtils.hasLength(addressTemplate)) { addressTemplate = OpenmrsConstants.DEFAULT_ADDRESS_TEMPLATE; } return addressTemplate; } /** * @see org.openmrs.api.LocationService#saveAddressTemplate(String) */ @Override public void saveAddressTemplate(String xml) throws APIException { Context.getAdministrationService().setGlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_ADDRESS_TEMPLATE, xml); } /** * @see org.openmrs.api.LocationService#getLocationAttributeTypeByName(java.lang.String) */ @Override @Transactional(readOnly = true) public LocationAttributeType getLocationAttributeTypeByName(String name) { return dao.getLocationAttributeTypeByName(name); } }