001    package ezvcard.types;
002    
003    import java.util.List;
004    
005    import ezvcard.VCard;
006    import ezvcard.VCardSubTypes;
007    import ezvcard.VCardVersion;
008    import ezvcard.io.CompatibilityMode;
009    import ezvcard.io.SkipMeException;
010    import ezvcard.parameters.RelatedTypeParameter;
011    import ezvcard.parameters.ValueParameter;
012    import ezvcard.util.VCardStringUtils;
013    import ezvcard.util.XCardElement;
014    
015    /*
016     Copyright (c) 2012, 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     * Someone that the person is related to. It can contain either a URI or a plain
046     * text value.
047     * 
048     * <pre>
049     * VCard vcard = new VCard();
050     * 
051     * RelatedType related = new RelatedType();
052     * related.addType(RelatedTypeParameter.FRIEND);
053     * related.setUri(&quot;urn:uuid:03a0e51f-d1aa-4385-8a53-e29025acd8af&quot;);
054     * vcard.addRelated(related);
055     * 
056     * related = new RelatedType();
057     * related.addType(RelatedTypeParameter.CO_WORKER);
058     * related.addType(RelatedTypeParameter.FRIEND);
059     * related.setUri(&quot;http://joesmoe.name/vcard.vcf&quot;);
060     * vcard.addRelated(related);
061     * 
062     * related = new RelatedType();
063     * related.addType(RelatedTypeParameter.SPOUSE);
064     * related.setText(&quot;My wife's name is Edna Smith&quot;);
065     * vcard.addRelated(related);
066     * </pre>
067     * 
068     * <p>
069     * vCard property name: RELATED
070     * </p>
071     * <p>
072     * vCard versions: 4.0
073     * </p>
074     * @author Michael Angstadt
075     */
076    public class RelatedType extends MultiValuedTypeParameterType<RelatedTypeParameter> {
077            public static final String NAME = "RELATED";
078    
079            private String uri;
080            private String text;
081    
082            public RelatedType() {
083                    super(NAME);
084            }
085    
086            /**
087             * Gets the URI value.
088             * @return the URI value or null if no URI value is set
089             */
090            public String getUri() {
091                    return uri;
092            }
093    
094            /**
095             * Sets the URI to an email address.
096             * @param email the email address
097             */
098            public void setUriEmail(String email) {
099                    setUri("mailto:" + email);
100            }
101    
102            /**
103             * Sets the URI to an instant messaging handle.
104             * @param protocol the IM protocol (e.g. "aim")
105             * @param handle the handle
106             */
107            public void setUriIM(String protocol, String handle) {
108                    setUri(protocol + ":" + handle);
109            }
110    
111            /**
112             * Sets the URI to a telephone number.
113             * @param telephone the telephone number
114             */
115            public void setUriTelephone(String telephone) {
116                    setUri("tel:" + telephone);
117            }
118    
119            /**
120             * Sets the URI.
121             * @param uri the URI
122             */
123            public void setUri(String uri) {
124                    this.uri = uri;
125                    text = null;
126            }
127    
128            /**
129             * Gets the text value.
130             * @return the text value or null if no text value is set
131             */
132            public String getText() {
133                    return text;
134            }
135    
136            /**
137             * Sets the value to free-form text instead of a URI.
138             * @param text the text
139             */
140            public void setText(String text) {
141                    this.text = text;
142                    uri = null;
143            }
144    
145            /**
146             * Gets all PID parameter values.
147             * <p>
148             * vCard versions: 4.0
149             * </p>
150             * @return the PID values or empty set if there are none
151             * @see VCardSubTypes#getPids
152             */
153            public List<Integer[]> getPids() {
154                    return subTypes.getPids();
155            }
156    
157            /**
158             * Adds a PID value.
159             * <p>
160             * vCard versions: 4.0
161             * </p>
162             * @param localId the local ID
163             * @param clientPidMapRef the ID used to reference the property's globally
164             * unique identifier in the CLIENTPIDMAP property.
165             * @see VCardSubTypes#addPid(int, int)
166             */
167            public void addPid(int localId, int clientPidMapRef) {
168                    subTypes.addPid(localId, clientPidMapRef);
169            }
170    
171            /**
172             * Removes all PID values.
173             * <p>
174             * vCard versions: 4.0
175             * </p>
176             * @see VCardSubTypes#removePids
177             */
178            public void removePids() {
179                    subTypes.removePids();
180            }
181    
182            /**
183             * Gets the preference value.
184             * <p>
185             * vCard versions: 4.0
186             * </p>
187             * @return the preference value or null if it doesn't exist
188             * @see VCardSubTypes#getPref
189             */
190            public Integer getPref() {
191                    return subTypes.getPref();
192            }
193    
194            /**
195             * Sets the preference value.
196             * <p>
197             * vCard versions: 4.0
198             * </p>
199             * @param pref the preference value or null to remove
200             * @see VCardSubTypes#setPref
201             */
202            public void setPref(Integer pref) {
203                    subTypes.setPref(pref);
204            }
205    
206            /**
207             * Gets the ALTID.
208             * <p>
209             * vCard versions: 4.0
210             * </p>
211             * @return the ALTID or null if it doesn't exist
212             * @see VCardSubTypes#getAltId
213             */
214            public String getAltId() {
215                    return subTypes.getAltId();
216            }
217    
218            /**
219             * Sets the ALTID.
220             * <p>
221             * vCard versions: 4.0
222             * </p>
223             * @param altId the ALTID or null to remove
224             * @see VCardSubTypes#setAltId
225             */
226            public void setAltId(String altId) {
227                    subTypes.setAltId(altId);
228            }
229    
230            @Override
231            public VCardVersion[] getSupportedVersions() {
232                    return new VCardVersion[] { VCardVersion.V4_0 };
233            }
234    
235            @Override
236            protected RelatedTypeParameter buildTypeObj(String type) {
237                    RelatedTypeParameter param = RelatedTypeParameter.valueOf(type);
238                    if (param == null) {
239                            param = new RelatedTypeParameter(type);
240                    }
241                    return param;
242            }
243    
244            @Override
245            protected void doMarshalSubTypes(VCardSubTypes copy, VCardVersion version, List<String> warnings, CompatibilityMode compatibilityMode, VCard vcard) {
246                    if (uri != null) {
247                            copy.setValue(ValueParameter.URI);
248                    } else if (text != null) {
249                            copy.setValue(ValueParameter.TEXT);
250                    }
251            }
252    
253            @Override
254            protected void doMarshalText(StringBuilder sb, VCardVersion version, List<String> warnings, CompatibilityMode compatibilityMode) {
255                    if (uri != null) {
256                            sb.append(VCardStringUtils.escape(uri));
257                    } else if (text != null) {
258                            sb.append(VCardStringUtils.escape(text));
259                    } else {
260                            throw new SkipMeException("Property has neither a URI nor a text value associated with it.");
261                    }
262            }
263    
264            @Override
265            protected void doUnmarshalText(String value, VCardVersion version, List<String> warnings, CompatibilityMode compatibilityMode) {
266                    value = VCardStringUtils.unescape(value);
267                    if (subTypes.getValue() == ValueParameter.URI) {
268                            setUri(value);
269                    } else if (subTypes.getValue() == ValueParameter.TEXT) {
270                            setText(value);
271                    } else {
272                            warnings.add("No valid VALUE parameter specified for " + NAME + " type.  Assuming it's text.");
273                            setText(value);
274                    }
275            }
276    
277            @Override
278            protected void doMarshalXml(XCardElement parent, List<String> warnings, CompatibilityMode compatibilityMode) {
279                    if (uri != null) {
280                            parent.uri(uri);
281                    } else if (text != null) {
282                            parent.text(text);
283                    } else {
284                            throw new SkipMeException("Property has neither a URI nor a text value associated with it.");
285                    }
286            }
287    
288            @Override
289            protected void doUnmarshalXml(XCardElement element, List<String> warnings, CompatibilityMode compatibilityMode) {
290                    String value = element.uri();
291                    if (value != null) {
292                            setUri(value);
293                    } else {
294                            setText(element.text());
295                    }
296            }
297    }