/** * 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; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.openmrs.api.APIException; import org.openmrs.api.context.Context; /** * A Location is a physical place, such as a hospital, a room, a clinic, or a district. Locations * support a single hierarchy, such that each location may have one parent location. A * non-geographical grouping of locations, such as "All Community Health Centers" is not a location, * and should be modeled using {@link LocationTag}s. */ public class Location extends BaseOpenmrsMetadata implements java.io.Serializable, Attributable<Location> { public static final long serialVersionUID = 455634L; public static final int LOCATION_UNKNOWN = 1; // Fields private Integer locationId; private String address1; private String address2; private String cityVillage; private String stateProvince; private String country; private String postalCode; private String latitude; private String longitude; private String countyDistrict; private String address3; private String address4; private String address6; private String address5; private Location parentLocation; private Set<Location> childLocations; private Set<LocationTag> tags; // Constructors /** default constructor */ public Location() { } /** constructor with id */ public Location(Integer locationId) { this.locationId = locationId; } /** * Compares two objects for similarity * * @param obj * @return boolean true/false whether or not they are the same objects */ @Override public boolean equals(Object obj) { if (obj instanceof Location) { Location loc = (Location) obj; if (this.getLocationId() != null && loc.getLocationId() != null) return (this.getLocationId().equals(loc.getLocationId())); } return obj == this; } @Override public int hashCode() { if (this.getLocationId() == null) return super.hashCode(); return this.getLocationId().hashCode(); } // Property accessors /** * @return Returns the address1. */ public String getAddress1() { return address1; } /** * @param address1 The address1 to set. */ public void setAddress1(String address1) { this.address1 = address1; } /** * @return Returns the address2. */ public String getAddress2() { return address2; } /** * @param address2 The address2 to set. */ public void setAddress2(String address2) { this.address2 = address2; } /** * @return Returns the cityVillage. */ public String getCityVillage() { return cityVillage; } /** * @param cityVillage The cityVillage to set. */ public void setCityVillage(String cityVillage) { this.cityVillage = cityVillage; } /** * @return Returns the country. */ public String getCountry() { return country; } /** * @param country The country to set. */ public void setCountry(String country) { this.country = country; } /** * @return Returns the latitude. */ public String getLatitude() { return latitude; } /** * @param latitude The latitude to set. */ public void setLatitude(String latitude) { this.latitude = latitude; } /** * @return Returns the locationId. */ public Integer getLocationId() { return locationId; } /** * @param locationId The locationId to set. */ public void setLocationId(Integer locationId) { this.locationId = locationId; } /** * @return Returns the longitude. */ public String getLongitude() { return longitude; } /** * @param longitude The longitude to set. */ public void setLongitude(String longitude) { this.longitude = longitude; } /** * @return Returns the postalCode. */ public String getPostalCode() { return postalCode; } /** * @param postalCode The postalCode to set. */ public void setPostalCode(String postalCode) { this.postalCode = postalCode; } /** * @return Returns the stateProvince. */ public String getStateProvince() { return stateProvince; } /** * @param stateProvince The stateProvince to set. */ public void setStateProvince(String stateProvince) { this.stateProvince = stateProvince; } @Override public String toString() { return getName(); } /** * @return Returns the countyDistrict. */ public String getCountyDistrict() { return countyDistrict; } /** * @param countyDistrict The countyDistrict to set. */ public void setCountyDistrict(String countyDistrict) { this.countyDistrict = countyDistrict; } /** * @deprecated As of 1.8, replaced by {@link #getAddress3()} * @return Returns the neighborhoodCell. */ @Deprecated public String getNeighborhoodCell() { return getAddress3(); } /** * @deprecated As of 1.8, replaced by {@link #setAddress3(String)} * @param address3 The neighborhoodCell to set. */ @Deprecated public void setNeighborhoodCell(String address3) { this.setAddress3(address3); } /** * @see org.openmrs.Attributable#findPossibleValues(java.lang.String) */ public List<Location> findPossibleValues(String searchText) { try { return Context.getLocationService().getLocations(searchText); } catch (Exception e) { return Collections.emptyList(); } } /** * @see org.openmrs.Attributable#getPossibleValues() */ public List<Location> getPossibleValues() { try { return Context.getLocationService().getAllLocations(); } catch (Exception e) { return Collections.emptyList(); } } /** * @see org.openmrs.Attributable#hydrate(java.lang.String) */ public Location hydrate(String locationId) { try { return Context.getLocationService().getLocation(Integer.valueOf(locationId)); } catch (Exception e) { return new Location(); } } /** * @see org.openmrs.Attributable#serialize() */ public String serialize() { if (getLocationId() != null) return "" + getLocationId(); else return ""; } /** * @see org.openmrs.Attributable#getDisplayString() */ public String getDisplayString() { return getName(); } /** * @deprecated As of 1.8, replaced by {@link #getAddress6()} * @return the region */ @Deprecated public String getRegion() { return getAddress6(); } /** * @deprecated As of 1.8, replaced by {@link #setAddress6(String)} * @param address6 the region to set */ @Deprecated public void setRegion(String address6) { this.setAddress6(address6); } /** * @deprecated As of 1.8, replaced by {@link #getAddress5()} * @return the subregion */ @Deprecated public String getSubregion() { return getAddress5(); } /** * @deprecated As of 1.8, replaced by {@link #setAddress5(String)} * @param address5 the subregion to set */ @Deprecated public void setSubregion(String address5) { this.setAddress5(address5); } /** * @deprecated As of 1.8, replaced by {@link #getAddress4()} * @return the townshipDivision */ @Deprecated public String getTownshipDivision() { return getAddress4(); } /** * @deprecated As of 1.8, replaced by {@link #setAddress4(String)} * @param address4 the townshipDivision to set */ @Deprecated public void setTownshipDivision(String address4) { this.setAddress4(address4); } /** * @return Returns the parentLocation. * @since 1.5 */ public Location getParentLocation() { return parentLocation; } /** * @param parentLocationId The parentLocation to set. * @since 1.5 */ public void setParentLocation(Location parentLocationId) { this.parentLocation = parentLocationId; } /** * @return Returns the childLocations. * @since 1.5 */ public Set<Location> getChildLocations() { return childLocations; } /** * Returns all childLocations where child.locationId = this.locationId. * * @param includeRetired specifies whether or not to include voided childLocations * @return Returns a Set<Location> of all the childLocations. * @since 1.5 * @should return a set of locations */ public Set<Location> getChildLocations(boolean includeRetired) { Set<Location> ret = new HashSet<Location>(); if (includeRetired) ret = getChildLocations(); else if (getChildLocations() != null) { for (Location l : getChildLocations()) { if (!l.isRetired()) ret.add(l); } } return ret; } /** * @param childLocations The childLocations to set. * @since 1.5 */ public void setChildLocations(Set<Location> childLocations) { this.childLocations = childLocations; } /** * @param child The child location to add. * @since 1.5 * @should return null given null parameter * @should throw APIException given same object as child * @should throw APIException if child already in hierarchy */ public void addChildLocation(Location child) { if (child == null) return; if (getChildLocations() == null) childLocations = new HashSet<Location>(); if (child.equals(this)) throw new APIException("A location cannot be its own child!"); // Traverse all the way up (down?) to the root, then check whether the child is already // anywhere in the tree Location root = this; while (root.getParentLocation() != null) root = root.getParentLocation(); if (isInHierarchy(child, root)) throw new APIException("Location hierarchy loop detected! You cannot add: '" + child + "' to the parent: '" + this + "' because it is in the parent hierarchy somewhere already and a location cannot be its own parent."); child.setParentLocation(this); childLocations.add(child); } /** * Checks whether 'location' is a member of the tree starting at 'root'. * * @param location The location to be tested. * @param root Location node from which to start the testing (down in the hierarchy). * @since 1.5 * @should return false given any null parameter * @should return true given same object in both parameters * @should return true given location that is already somewhere in hierarchy * @should return false given location that is not in hierarchy * @should should find location in hierarchy */ public static Boolean isInHierarchy(Location location, Location root) { if (location == null || root == null) return false; if (root.equals(location)) return true; if (root.getChildLocations() != null) { for (Location l : root.getChildLocations()) return isInHierarchy(location, l); } return false; } /** * @param child The child location to remove. * @since 1.5 */ public void removeChildLocation(Location child) { if (getChildLocations() != null) childLocations.remove(child); } /** * @return Returns the tags which have been attached to this Location. * @since 1.5 */ public Set<LocationTag> getTags() { return tags; } /** * Set the tags which are attached to this Location. * * @param tags The tags to set. * @since 1.5 */ public void setTags(Set<LocationTag> tags) { this.tags = tags; } /** * Attaches a tag to the Location. * * @param tag The tag to add. * @since 1.5 */ public void addTag(LocationTag tag) { if (getTags() == null) tags = new HashSet<LocationTag>(); if (tag != null && !tags.contains(tag)) tags.add(tag); } /** * Remove the tag from the Location. * * @param tag The tag to remove. * @since 1.5 */ public void removeTag(LocationTag tag) { if (getTags() != null) tags.remove(tag); } /** * Checks whether the Location has a particular tag. * * @param tagToFind the string of the tag for which to check * @return true if the tags include the specified tag, false otherwise * @since 1.5 * @should not fail given null parameter * @should return false given empty string parameter */ public Boolean hasTag(String tagToFind) { if (tagToFind != null && getTags() != null) { for (LocationTag locTag : getTags()) { if (locTag.getName().equals(tagToFind)) { return true; } } } return false; } /** * @since 1.8 * @return the address3 */ public String getAddress3() { return address3; } /** * @since 1.8 * @param address3 the address3 to set */ public void setAddress3(String address3) { this.address3 = address3; } /** * @since 1.8 * @return the address4 */ public String getAddress4() { return address4; } /** * @since 1.8 * @param address4 the address4 to set */ public void setAddress4(String address4) { this.address4 = address4; } /** * @since 1.8 * @return the address6 */ public String getAddress6() { return address6; } /** * @since 1.8 * @param address6 the address6 to set */ public void setAddress6(String address6) { this.address6 = address6; } /** * @since 1.8 * @return the address5 */ public String getAddress5() { return address5; } /** * @since 1.8 * @param address5 the address5 to set */ public void setAddress5(String address5) { this.address5 = address5; } /** * @since 1.5 * @see org.openmrs.OpenmrsObject#getId() */ public Integer getId() { return getLocationId(); } /** * @since 1.5 * @see org.openmrs.OpenmrsObject#setId(java.lang.Integer) */ public void setId(Integer id) { setLocationId(id); } }