001package ezvcard.property;
002
003import java.util.LinkedHashMap;
004import java.util.List;
005import java.util.Map;
006
007import ezvcard.SupportedVersions;
008import ezvcard.VCard;
009import ezvcard.VCardVersion;
010import ezvcard.ValidationWarning;
011import ezvcard.parameter.Pid;
012import ezvcard.parameter.RelatedType;
013import ezvcard.util.TelUri;
014
015/*
016 Copyright (c) 2012-2023, Michael Angstadt
017 All rights reserved.
018
019 Redistribution and use in source and binary forms, with or without
020 modification, are permitted provided that the following conditions are met: 
021
022 1. Redistributions of source code must retain the above copyright notice, this
023 list of conditions and the following disclaimer. 
024 2. Redistributions in binary form must reproduce the above copyright notice,
025 this list of conditions and the following disclaimer in the documentation
026 and/or other materials provided with the distribution. 
027
028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
029 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
030 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
032 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
034 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
037 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038
039 The views and conclusions contained in the software and documentation are those
040 of the authors and should not be interpreted as representing official policies, 
041 either expressed or implied, of the FreeBSD Project.
042 */
043
044/**
045 * <p>
046 * Defines someone that the person is related to.
047 * </p>
048 * 
049 * <p>
050 * <b>Code sample</b>
051 * </p>
052 * 
053 * <pre class="brush:java">
054 * VCard vcard = new VCard();
055 * 
056 * //static factory methods
057 * Related related = Related.email("bob.smith@example.com");
058 * related.getTypes().add(RelatedType.CO_WORKER);
059 * related.getTypes().add(RelatedType.FRIEND);
060 * vcard.addRelated(related);
061 * 
062 * //free-form text
063 * related = new Related();
064 * related.setText("Edna Smith");
065 * related.getTypes().add(RelatedType.SPOUSE);
066 * vcard.addRelated(related);
067 * 
068 * //reference another vCard by putting its UID property here
069 * related = new Related("urn:uuid:03a0e51f-d1aa-4385-8a53-e29025acd8af");
070 * related.getTypes().add(RelatedType.SIBLING);
071 * vcard.addRelated(related);
072 * </pre>
073 * 
074 * <p>
075 * <b>Property name:</b> {@code RELATED}
076 * </p>
077 * <p>
078 * <b>Supported versions:</b> {@code 4.0}
079 * </p>
080 * @author Michael Angstadt
081 * @see <a href="http://tools.ietf.org/html/rfc6350#page-42">RFC 6350 p.42</a>
082 */
083@SupportedVersions(VCardVersion.V4_0)
084public class Related extends VCardProperty implements HasAltId {
085        private String uri;
086        private String text;
087
088        /**
089         * Creates a related property
090         */
091        public Related() {
092                //empty
093        }
094
095        /**
096         * Creates a related property.
097         * @param uri the URI representing the person
098         */
099        public Related(String uri) {
100                setUri(uri);
101        }
102
103        /**
104         * Copy constructor.
105         * @param original the property to make a copy of
106         */
107        public Related(Related original) {
108                super(original);
109                uri = original.uri;
110                text = original.text;
111        }
112
113        /**
114         * Creates a related property whose value is an email address.
115         * @param email the email address
116         * @return the property
117         */
118        public static Related email(String email) {
119                return new Related("mailto:" + email);
120        }
121
122        /**
123         * Creates a related property whose value is an instant messenger handle.
124         * @param protocol the instant messenger protocol (e.g. "aim")
125         * @param handle the instant messenger handle (e.g. "johndoe")
126         * @return the property
127         */
128        public static Related im(String protocol, String handle) {
129                return new Related(protocol + ":" + handle);
130        }
131
132        /**
133         * Creates a related property whose value is a telephone number.
134         * @param telUri the telephone number
135         * @return the property
136         */
137        public static Related telephone(TelUri telUri) {
138                return new Related(telUri.toString());
139        }
140
141        /**
142         * Gets the URI value.
143         * @return the URI value or null if no URI value is set
144         */
145        public String getUri() {
146                return uri;
147        }
148
149        /**
150         * Sets the URI.
151         * @param uri the URI
152         */
153        public void setUri(String uri) {
154                this.uri = uri;
155                text = null;
156        }
157
158        /**
159         * Gets the text value.
160         * @return the text value or null if no text value is set
161         */
162        public String getText() {
163                return text;
164        }
165
166        /**
167         * Sets the value to free-form text instead of a URI.
168         * @param text the text
169         */
170        public void setText(String text) {
171                this.text = text;
172                uri = null;
173        }
174
175        /**
176         * Gets the list that stores this property's relationship types (TYPE
177         * parameters).
178         * @return the relationship types (e.g. "child", "co-worker") (this list is
179         * mutable)
180         */
181        public List<RelatedType> getTypes() {
182                return parameters.new TypeParameterList<RelatedType>() {
183                        @Override
184                        protected RelatedType _asObject(String value) {
185                                return RelatedType.get(value);
186                        }
187                };
188        }
189
190        @Override
191        public List<Pid> getPids() {
192                return super.getPids();
193        }
194
195        @Override
196        public Integer getPref() {
197                return super.getPref();
198        }
199
200        @Override
201        public void setPref(Integer pref) {
202                super.setPref(pref);
203        }
204
205        //@Override
206        public String getAltId() {
207                return parameters.getAltId();
208        }
209
210        //@Override
211        public void setAltId(String altId) {
212                parameters.setAltId(altId);
213        }
214
215        @Override
216        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
217                if (uri == null && text == null) {
218                        warnings.add(new ValidationWarning(8));
219                }
220        }
221
222        @Override
223        protected Map<String, Object> toStringValues() {
224                Map<String, Object> values = new LinkedHashMap<>();
225                values.put("uri", uri);
226                values.put("text", text);
227                return values;
228        }
229
230        @Override
231        public Related copy() {
232                return new Related(this);
233        }
234
235        @Override
236        public int hashCode() {
237                final int prime = 31;
238                int result = super.hashCode();
239                result = prime * result + ((text == null) ? 0 : text.hashCode());
240                result = prime * result + ((uri == null) ? 0 : uri.hashCode());
241                return result;
242        }
243
244        @Override
245        public boolean equals(Object obj) {
246                if (this == obj) return true;
247                if (!super.equals(obj)) return false;
248                Related other = (Related) obj;
249                if (text == null) {
250                        if (other.text != null) return false;
251                } else if (!text.equals(other.text)) return false;
252                if (uri == null) {
253                        if (other.uri != null) return false;
254                } else if (!uri.equals(other.uri)) return false;
255                return true;
256        }
257}