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}