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