001package ezvcard.property;
002
003import java.text.NumberFormat;
004import java.util.LinkedHashMap;
005import java.util.List;
006import java.util.Locale;
007import java.util.Map;
008
009import ezvcard.SupportedVersions;
010import ezvcard.VCard;
011import ezvcard.VCardVersion;
012import ezvcard.ValidationWarnings;
013import ezvcard.ValidationWarning;
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 information about the person's agent.
047 * </p>
048 * 
049 * <p>
050 * <b>Code sample (creating)</b>
051 * </p>
052 * 
053 * <pre class="brush:java">
054 * VCard vcard = new VCard();
055 * 
056 * //URL
057 * Agent agent = new Agent("http://www.linkedin.com/BobSmith");
058 * vcard.setAgent(agent);
059 * 
060 * //vCard
061 * VCard agentVCard = new VCard();
062 * agentVCard.setFormattedName("Bob Smith");
063 * agentVCard.addTelephoneNumber("(555) 123-4566");
064 * agentVCard.addUrl("http://www.linkedin.com/BobSmith");
065 * agent = new Agent(agentVCard);
066 * vcard.setAgent(agent);
067 * </pre>
068 * 
069 * <p>
070 * <b>Code sample (retrieving)</b>
071 * </p>
072 * 
073 * <pre class="brush:java">
074 * VCard vcard = ...
075 * Agent agent = vcard.getAgent();
076 * 
077 * String url = agent.getUrl();
078 * if (url != null) {
079 *   //property value is a URL
080 * }
081 * 
082 * VCard agentVCard = agent.getVCard();
083 * if (agentVCard != null) {
084 *   //property value is a vCard
085 * }
086 * </pre>
087 * 
088 * <p>
089 * <b>Property name:</b> {@code AGENT}
090 * </p>
091 * <p>
092 * <b>Supported versions:</b> {@code 2.1, 3.0}
093 * </p>
094 * 
095 * @author Michael Angstadt
096 * @see <a href="http://tools.ietf.org/html/rfc2426#page-19">RFC 2426 p.19</a>
097 * @see <a href="http://www.imc.org/pdi/vcard-21.doc">vCard 2.1 p.18</a>
098 */
099@SupportedVersions({ VCardVersion.V2_1, VCardVersion.V3_0 })
100public class Agent extends VCardProperty {
101        private String url;
102        private VCard vcard;
103
104        /**
105         * Creates an empty agent property.
106         */
107        public Agent() {
108                //empty
109        }
110
111        /**
112         * Creates an agent property.
113         * @param url a URL pointing to the agent's information
114         */
115        public Agent(String url) {
116                setUrl(url);
117        }
118
119        /**
120         * Creates an agent property.
121         * @param vcard a vCard containing the agent's information
122         */
123        public Agent(VCard vcard) {
124                setVCard(vcard);
125        }
126
127        /**
128         * Copy constructor.
129         * @param original the property to make a copy of
130         */
131        public Agent(Agent original) {
132                super(original);
133                url = original.url;
134                vcard = (original.vcard == null) ? null : new VCard(original.vcard);
135        }
136
137        /**
138         * Gets the URL to the agent's information.
139         * @return the URL or null if not set
140         */
141        public String getUrl() {
142                return url;
143        }
144
145        /**
146         * Sets the URL to the agent's information.
147         * @param url the URL
148         */
149        public void setUrl(String url) {
150                this.url = url;
151                vcard = null;
152        }
153
154        /**
155         * Gets an embedded vCard with the agent's information.
156         * @return the vCard or null if not set
157         */
158        public VCard getVCard() {
159                return vcard;
160        }
161
162        /**
163         * Sets an embedded vCard with the agent's information.
164         * @param vcard the vCard
165         */
166        public void setVCard(VCard vcard) {
167                this.vcard = vcard;
168                url = null;
169        }
170
171        @Override
172        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
173                if (url == null && this.vcard == null) {
174                        warnings.add(new ValidationWarning(8));
175                }
176
177                if (this.vcard != null) {
178                        NumberFormat nf = NumberFormat.getIntegerInstance(Locale.ROOT);
179                        nf.setMinimumIntegerDigits(2);
180
181                        ValidationWarnings validationWarnings = this.vcard.validate(version);
182                        for (Map.Entry<VCardProperty, List<ValidationWarning>> entry : validationWarnings) {
183                                VCardProperty property = entry.getKey();
184                                List<ValidationWarning> propViolations = entry.getValue();
185
186                                for (ValidationWarning propViolation : propViolations) {
187                                        String className = (property == null) ? "" : property.getClass().getSimpleName();
188
189                                        int code = propViolation.getCode();
190                                        String codeStr = (code >= 0) ? "W" + nf.format(code) : "";
191                                        String message = propViolation.getMessage();
192                                        warnings.add(new ValidationWarning(10, className, codeStr, message));
193                                }
194                        }
195                }
196        }
197
198        @Override
199        protected Map<String, Object> toStringValues() {
200                Map<String, Object> values = new LinkedHashMap<>();
201                values.put("url", url);
202                values.put("vcard", vcard);
203                return values;
204        }
205
206        @Override
207        public Agent copy() {
208                return new Agent(this);
209        }
210
211        @Override
212        public int hashCode() {
213                final int prime = 31;
214                int result = super.hashCode();
215                result = prime * result + ((url == null) ? 0 : url.hashCode());
216                result = prime * result + ((vcard == null) ? 0 : vcard.hashCode());
217                return result;
218        }
219
220        @Override
221        public boolean equals(Object obj) {
222                if (this == obj) return true;
223                if (!super.equals(obj)) return false;
224                Agent other = (Agent) obj;
225                if (url == null) {
226                        if (other.url != null) return false;
227                } else if (!url.equals(other.url)) return false;
228                if (vcard == null) {
229                        if (other.vcard != null) return false;
230                } else if (!vcard.equals(other.vcard)) return false;
231                return true;
232        }
233}