001package ezvcard.property; 002 003import java.util.LinkedHashMap; 004import java.util.List; 005import java.util.Map; 006import java.util.Objects; 007 008import ezvcard.VCard; 009import ezvcard.VCardVersion; 010import ezvcard.ValidationWarning; 011import ezvcard.parameter.Pid; 012import ezvcard.util.GeoUri; 013 014/* 015 Copyright (c) 2012-2026, Michael Angstadt 016 All rights reserved. 017 018 Redistribution and use in source and binary forms, with or without 019 modification, are permitted provided that the following conditions are met: 020 021 1. Redistributions of source code must retain the above copyright notice, this 022 list of conditions and the following disclaimer. 023 2. Redistributions in binary form must reproduce the above copyright notice, 024 this list of conditions and the following disclaimer in the documentation 025 and/or other materials provided with the distribution. 026 027 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 028 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 029 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 030 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 031 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 032 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 033 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 034 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 035 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 036 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 037 038 The views and conclusions contained in the software and documentation are those 039 of the authors and should not be interpreted as representing official policies, 040 either expressed or implied, of the FreeBSD Project. 041 */ 042 043/** 044 * <p> 045 * Defines a set of latitude/longitude coordinates. There is no rule as to what 046 * these coordinates represent, but their meaning could vary depending on the 047 * value of the vCard's {@link Kind} property: 048 * </p> 049 * 050 * <table class="simpleTable"> 051 * <caption>{@link Geo} meanings by {@link Kind} value</caption> 052 * <tr> 053 * <th>{@link Kind} value</th> 054 * <th>{@link Geo} meaning</th> 055 * </tr> 056 * <tr> 057 * <td>"individual"</td> 058 * <td>The location of the person's home or workplace.</td> 059 * </tr> 060 * <tr> 061 * <td>"group"</td> 062 * <td>The location of the group's meeting place.</td> 063 * </tr> 064 * <tr> 065 * <td>"org"</td> 066 * <td>The coordinates of the organization's headquarters.</td> 067 * </tr> 068 * <tr> 069 * <td>"location"</td> 070 * <td>The coordinates of the location itself.</td> 071 * </tr> 072 * </table> 073 * 074 * <p> 075 * <b>Code sample</b> 076 * </p> 077 * 078 * <pre class="brush:java"> 079 * VCard vcard = new VCard(); 080 * 081 * Geo geo = new Geo(40.7127, -74.0059); 082 * vcard.setGeo(geo); 083 * </pre> 084 * 085 * <p> 086 * <b>Property name:</b> {@code GEO} 087 * </p> 088 * <p> 089 * <b>Supported versions:</b> {@code 2.1, 3.0, 4.0} 090 * </p> 091 * @author Michael Angstadt 092 * @see <a href="http://tools.ietf.org/html/rfc6350#page-38">RFC 6350 p.38</a> 093 * @see <a href="http://tools.ietf.org/html/rfc2426#page-16">RFC 2426 p.16</a> 094 * @see <a href="http://www.imc.org/pdi/vcard-21.doc">vCard 2.1 p.16</a> 095 */ 096public class Geo extends VCardProperty implements HasAltId { 097 private GeoUri uri; 098 099 /** 100 * Creates a geo property. 101 * @param latitude the latitude 102 * @param longitude the longitude 103 */ 104 public Geo(Double latitude, Double longitude) { 105 this(new GeoUri.Builder(latitude, longitude).build()); 106 } 107 108 /** 109 * Creates a geo property. 110 * @param uri the geo URI 111 */ 112 public Geo(GeoUri uri) { 113 this.uri = uri; 114 } 115 116 /** 117 * Copy constructor. 118 * @param original the property to make a copy of 119 */ 120 public Geo(Geo original) { 121 super(original); 122 uri = original.uri; 123 } 124 125 /** 126 * Gets the latitude. 127 * @return the latitude 128 */ 129 public Double getLatitude() { 130 return (uri == null) ? null : uri.getCoordA(); 131 } 132 133 /** 134 * Sets the latitude. 135 * @param latitude the latitude 136 */ 137 public void setLatitude(Double latitude) { 138 if (uri == null) { 139 uri = new GeoUri.Builder(latitude, null).build(); 140 } else { 141 uri = new GeoUri.Builder(uri).coordA(latitude).build(); 142 } 143 } 144 145 /** 146 * Gets the longitude. 147 * @return the longitude 148 */ 149 public Double getLongitude() { 150 return (uri == null) ? null : uri.getCoordB(); 151 } 152 153 /** 154 * Sets the longitude. 155 * @param longitude the longitude 156 */ 157 public void setLongitude(Double longitude) { 158 if (uri == null) { 159 uri = new GeoUri.Builder(null, longitude).build(); 160 } else { 161 uri = new GeoUri.Builder(uri).coordB(longitude).build(); 162 } 163 } 164 165 /** 166 * Gets the raw object used for storing the GEO information. This can be 167 * used to supplement the GEO value with additional information (such as 168 * altitude or level of accuracy). Geo URIs are only supported by vCard 169 * version 4.0. Only latitude and longitude values are used when marshalling 170 * to earlier vCard versions. 171 * @return the geo URI object or null if not set 172 * @see <a href="http://tools.ietf.org/html/rfc5870">RFC 5870</a> 173 */ 174 public GeoUri getGeoUri() { 175 return uri; 176 } 177 178 /** 179 * Sets the raw object used for storing the GEO information. This can be 180 * used to supplement the GEO value with additional information (such as 181 * altitude or level of accuracy). Geo URIs are only supported by vCard 182 * version 4.0. Only latitude and longitude values are used when marshalling 183 * to earlier vCard versions. 184 * @param uri the geo URI object 185 * @see <a href="http://tools.ietf.org/html/rfc5870">RFC 5870</a> 186 */ 187 public void setGeoUri(GeoUri uri) { 188 this.uri = uri; 189 } 190 191 /** 192 * Gets the TYPE parameter. 193 * <p> 194 * <b>Supported versions:</b> {@code 4.0} 195 * </p> 196 * @return the TYPE value (typically, this will be either "work" or "home") 197 * or null if it doesn't exist 198 */ 199 public String getType() { 200 return parameters.getType(); 201 } 202 203 /** 204 * Sets the TYPE parameter. 205 * <p> 206 * <b>Supported versions:</b> {@code 4.0} 207 * </p> 208 * @param type the TYPE value (this should be either "work" or "home") or 209 * null to remove 210 */ 211 public void setType(String type) { 212 parameters.setType(type); 213 } 214 215 /** 216 * Gets the MEDIATYPE parameter. 217 * <p> 218 * <b>Supported versions:</b> {@code 4.0} 219 * </p> 220 * @return the media type or null if not set 221 */ 222 public String getMediaType() { 223 return parameters.getMediaType(); 224 } 225 226 /** 227 * Sets the MEDIATYPE parameter. 228 * <p> 229 * <b>Supported versions:</b> {@code 4.0} 230 * </p> 231 * @param mediaType the media type or null to remove 232 */ 233 public void setMediaType(String mediaType) { 234 parameters.setMediaType(mediaType); 235 } 236 237 @Override 238 public List<Pid> getPids() { 239 return super.getPids(); 240 } 241 242 @Override 243 public Integer getPref() { 244 return super.getPref(); 245 } 246 247 @Override 248 public void setPref(Integer pref) { 249 super.setPref(pref); 250 } 251 252 //@Override 253 public String getAltId() { 254 return parameters.getAltId(); 255 } 256 257 //@Override 258 public void setAltId(String altId) { 259 parameters.setAltId(altId); 260 } 261 262 @Override 263 protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) { 264 if (getLatitude() == null) { 265 warnings.add(new ValidationWarning(13)); 266 } 267 if (getLongitude() == null) { 268 warnings.add(new ValidationWarning(14)); 269 } 270 } 271 272 @Override 273 protected Map<String, Object> toStringValues() { 274 Map<String, Object> values = new LinkedHashMap<>(); 275 values.put("uri", uri); 276 return values; 277 } 278 279 @Override 280 public Geo copy() { 281 return new Geo(this); 282 } 283 284 @Override 285 public int hashCode() { 286 final int prime = 31; 287 int result = super.hashCode(); 288 result = prime * result + Objects.hash(uri); 289 return result; 290 } 291 292 @Override 293 public boolean equals(Object obj) { 294 if (this == obj) return true; 295 if (!super.equals(obj)) return false; 296 if (getClass() != obj.getClass()) return false; 297 Geo other = (Geo) obj; 298 return Objects.equals(uri, other.uri); 299 } 300}