001package ezvcard.property; 002 003import java.net.URI; 004import java.net.URISyntaxException; 005import java.util.LinkedHashMap; 006import java.util.List; 007import java.util.Map; 008 009import ezvcard.SupportedVersions; 010import ezvcard.VCard; 011import ezvcard.VCardVersion; 012import ezvcard.ValidationWarning; 013import ezvcard.parameter.ImppType; 014import ezvcard.parameter.Pid; 015 016/* 017 Copyright (c) 2012-2023, Michael Angstadt 018 All rights reserved. 019 020 Redistribution and use in source and binary forms, with or without 021 modification, are permitted provided that the following conditions are met: 022 023 1. Redistributions of source code must retain the above copyright notice, this 024 list of conditions and the following disclaimer. 025 2. Redistributions in binary form must reproduce the above copyright notice, 026 this list of conditions and the following disclaimer in the documentation 027 and/or other materials provided with the distribution. 028 029 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 030 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 031 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 032 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 033 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 034 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 035 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 036 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 038 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 039 040 The views and conclusions contained in the software and documentation are those 041 of the authors and should not be interpreted as representing official policies, 042 either expressed or implied, of the FreeBSD Project. 043 */ 044 045/** 046 * <p> 047 * Defines an instant messenger handle. The handle is represented as a URI in 048 * the format "{@code <PROTOCOL>:<HANDLE>}". For example, a Yahoo! Messenger 049 * handle of "johndoe@yahoo.com" would look like this: 050 * "ymsgr:johndoe@yahoo.com". 051 * </p> 052 * 053 * <p> 054 * <b>Code sample</b> 055 * </p> 056 * 057 * <pre class="brush:java"> 058 * VCard vcard = new VCard(); 059 * 060 * //URI 061 * Impp impp = new Impp("aim:johndoe@aol.com"); 062 * vcard.addImpp(impp); 063 * 064 * //static factory methods 065 * impp = Impp.msn("janedoe@msn.com"); 066 * vcard.addImpp(impp); 067 * </pre> 068 * 069 * <p> 070 * <b>Property name:</b> {@code IMPP} 071 * </p> 072 * <p> 073 * <b>Supported versions:</b> {@code 3.0, 4.0} 074 * </p> 075 * @author Michael Angstadt 076 * @see <a href="http://tools.ietf.org/html/rfc6350#page-36">RFC 6350 p.36</a> 077 * @see <a href="http://tools.ietf.org/html/rfc4770">RFC 4770</a> 078 */ 079@SupportedVersions({ VCardVersion.V3_0, VCardVersion.V4_0 }) 080public class Impp extends VCardProperty implements HasAltId { 081 private static final String AIM = "aim"; 082 private static final String ICQ = "icq"; 083 private static final String IRC = "irc"; 084 private static final String MSN = "msnim"; 085 private static final String SIP = "sip"; 086 private static final String SKYPE = "skype"; 087 private static final String XMPP = "xmpp"; 088 private static final String YAHOO = "ymsgr"; 089 090 private URI uri; 091 092 /** 093 * Creates an IMPP property. Note that this class has static factory methods 094 * for creating IMPP properties of common IM protocols. 095 * @param uri the IM URI (e.g. "aim:johndoe@aol.com") 096 * @throws IllegalArgumentException if the URI is not a valid URI 097 */ 098 public Impp(String uri) { 099 setUri(uri); 100 } 101 102 /** 103 * Creates an IMPP property. Note that this class has static factory methods 104 * for creating IMPP properties of common IM protocols. 105 * @param uri the IM URI (e.g. "aim:johndoe@aol.com") 106 */ 107 public Impp(URI uri) { 108 setUri(uri); 109 } 110 111 /** 112 * Creates an IMPP property. Note that this class has static factory methods 113 * for creating IMPP properties of common IM protocols. 114 * @param protocol the IM protocol (e.g. "aim") 115 * @param handle the IM handle (e.g. "johndoe@aol.com") 116 */ 117 public Impp(String protocol, String handle) { 118 setUri(protocol, handle); 119 } 120 121 /** 122 * Copy constructor. 123 * @param original the property to make a copy of 124 */ 125 public Impp(Impp original) { 126 super(original); 127 uri = original.uri; 128 } 129 130 /** 131 * Creates an IMPP property that contains a AOL Instant Messenger handle. 132 * @param handle the IM handle 133 * @return the IMPP property instance 134 */ 135 public static Impp aim(String handle) { 136 return new Impp(AIM, handle); 137 } 138 139 /** 140 * Determines if this IMPP property contains an AOL Instant Messenger 141 * handle. 142 * @return true if it contains an AOL Instant Messenger handle, false if not 143 */ 144 public boolean isAim() { 145 return isProtocol(AIM); 146 } 147 148 /** 149 * Creates an IMPP property that contains a Yahoo! Messenger handle. 150 * @param handle the IM handle 151 * @return the IMPP property instance 152 */ 153 public static Impp yahoo(String handle) { 154 return new Impp(YAHOO, handle); 155 } 156 157 /** 158 * Determines if this IMPP property contains a Yahoo! Messenger handle. 159 * @return true if it contains a Yahoo! Messenger handle, false if not 160 */ 161 public boolean isYahoo() { 162 return isProtocol(YAHOO); 163 } 164 165 /** 166 * Creates an IMPP property that contains an MSN IMPP property. 167 * @param handle the IM handle 168 * @return the IMPP property instance 169 */ 170 public static Impp msn(String handle) { 171 return new Impp(MSN, handle); 172 } 173 174 /** 175 * Determines if this IMPP property contains an MSN handle. 176 * @return true if it contains an MSN handle, false if not 177 */ 178 public boolean isMsn() { 179 return isProtocol(MSN); 180 } 181 182 /** 183 * Creates an IMPP property that contains an ICQ handle. 184 * @param handle the IM handle 185 * @return the IMPP property instance 186 */ 187 public static Impp icq(String handle) { 188 return new Impp(ICQ, handle); 189 } 190 191 /** 192 * Determines if this IMPP property contains an ICQ handle. 193 * @return true if it contains an ICQ handle, false if not 194 */ 195 public boolean isIcq() { 196 return isProtocol(ICQ); 197 } 198 199 /** 200 * Creates an IMPP property that contains an IRC handle. 201 * @param handle the IM handle 202 * @return the IMPP property instance 203 */ 204 public static Impp irc(String handle) { 205 return new Impp(IRC, handle); 206 } 207 208 /** 209 * Determines if this IMPP property contains an IRC handle. 210 * @return true if it contains an IRC handle, false if not 211 */ 212 public boolean isIrc() { 213 return isProtocol(IRC); 214 } 215 216 /** 217 * Creates an IMPP property that contains a Session Initiation Protocol 218 * handle. 219 * @param handle the IM handle 220 * @return the IMPP property instance 221 */ 222 public static Impp sip(String handle) { 223 return new Impp(SIP, handle); 224 } 225 226 /** 227 * Determines if this IMPP property contains a Session Initiation Protocol 228 * handle. 229 * @return true if it contains a SIP handle, false if not 230 */ 231 public boolean isSip() { 232 return isProtocol(SIP); 233 } 234 235 /** 236 * Creates an IMPP property that contains a Skype handle. 237 * @param handle the IM handle 238 * @return the IMPP property instance 239 */ 240 public static Impp skype(String handle) { 241 return new Impp(SKYPE, handle); 242 } 243 244 /** 245 * Determines if this IMPP property contains a Skype handle. 246 * @return true if it contains a Skype handle, false if not 247 */ 248 public boolean isSkype() { 249 return isProtocol(SKYPE); 250 } 251 252 /** 253 * Creates an IMPP property that contains an Extensible Messaging and 254 * Presence Protocol handle. 255 * @param handle the IM handle 256 * @return the IMPP property instance 257 */ 258 public static Impp xmpp(String handle) { 259 return new Impp(XMPP, handle); 260 } 261 262 /** 263 * Determines if this IMPP property contains an Extensible Messaging and 264 * Presence Protocol handle. 265 * @return true if it contains an XMPP handle, false if not 266 */ 267 public boolean isXmpp() { 268 return isProtocol(XMPP); 269 } 270 271 private boolean isProtocol(String protocol) { 272 return uri != null && protocol.equalsIgnoreCase(uri.getScheme()); 273 } 274 275 /** 276 * Gets the IM URI. 277 * @return the IM URI 278 */ 279 public URI getUri() { 280 return uri; 281 } 282 283 /** 284 * Sets the IM URI. 285 * @param uri the IM URI (e.g. "aim:theuser@aol.com") 286 * @throws IllegalArgumentException if the URI is not a valid URI 287 */ 288 public void setUri(String uri) { 289 setUri((uri == null) ? null : URI.create(uri)); 290 } 291 292 /** 293 * Sets the IM URI. 294 * @param uri the IM URI (e.g. "aim:theuser@aol.com") 295 */ 296 public void setUri(URI uri) { 297 this.uri = uri; 298 } 299 300 /** 301 * Sets the IM URI. 302 * @param protocol the IM protocol (e.g. "aim") 303 * @param handle the IM handle (e.g. "theuser@aol.com") 304 */ 305 public void setUri(String protocol, String handle) { 306 try { 307 this.uri = new URI(protocol, handle, null); 308 } catch (URISyntaxException e) { 309 throw new IllegalArgumentException(e); 310 } 311 } 312 313 /** 314 * Gets the IM protocol. Use {@link #setUri(String, String)} to set the 315 * protocol. 316 * @return the IM protocol (e.g. "aim") or null if not set 317 */ 318 public String getProtocol() { 319 if (uri == null) { 320 return null; 321 } 322 return uri.getScheme(); 323 } 324 325 /** 326 * Gets the IM handle. Use {@link #setUri(String, String)} to set the 327 * handle. 328 * @return the IM handle (e.g. "johndoe@aol.com") or null if not set 329 */ 330 public String getHandle() { 331 if (uri == null) { 332 return null; 333 } 334 return uri.getSchemeSpecificPart(); 335 } 336 337 /** 338 * Gets the list that stores this property's IMPP types (TYPE parameters). 339 * @return the IMPP types (e.g. "HOME", "WORK") (this list is mutable) 340 */ 341 public List<ImppType> getTypes() { 342 return parameters.new TypeParameterList<ImppType>() { 343 @Override 344 protected ImppType _asObject(String value) { 345 return ImppType.get(value); 346 } 347 }; 348 } 349 350 /** 351 * Gets the MEDIATYPE parameter. 352 * <p> 353 * <b>Supported versions:</b> {@code 4.0} 354 * </p> 355 * @return the media type or null if not set 356 */ 357 public String getMediaType() { 358 return parameters.getMediaType(); 359 } 360 361 /** 362 * Sets the MEDIATYPE parameter. 363 * <p> 364 * <b>Supported versions:</b> {@code 4.0} 365 * </p> 366 * @param mediaType the media type or null to remove 367 */ 368 public void setMediaType(String mediaType) { 369 parameters.setMediaType(mediaType); 370 } 371 372 @Override 373 public List<Pid> getPids() { 374 return super.getPids(); 375 } 376 377 @Override 378 public Integer getPref() { 379 return super.getPref(); 380 } 381 382 @Override 383 public void setPref(Integer pref) { 384 super.setPref(pref); 385 } 386 387 //@Override 388 public String getAltId() { 389 return parameters.getAltId(); 390 } 391 392 //@Override 393 public void setAltId(String altId) { 394 parameters.setAltId(altId); 395 } 396 397 @Override 398 protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) { 399 if (uri == null) { 400 warnings.add(new ValidationWarning(8)); 401 } 402 } 403 404 @Override 405 protected Map<String, Object> toStringValues() { 406 Map<String, Object> values = new LinkedHashMap<>(); 407 values.put("uri", uri); 408 return values; 409 } 410 411 @Override 412 public Impp copy() { 413 return new Impp(this); 414 } 415 416 @Override 417 public int hashCode() { 418 final int prime = 31; 419 int result = super.hashCode(); 420 result = prime * result + ((uri == null) ? 0 : uri.hashCode()); 421 return result; 422 } 423 424 @Override 425 public boolean equals(Object obj) { 426 if (this == obj) return true; 427 if (!super.equals(obj)) return false; 428 Impp other = (Impp) obj; 429 if (uri == null) { 430 if (other.uri != null) return false; 431 } else if (!uri.equals(other.uri)) return false; 432 return true; 433 } 434}