001package ezvcard.property;
002
003import java.text.NumberFormat;
004import java.util.LinkedHashMap;
005import java.util.List;
006import java.util.Map;
007
008import ezvcard.SupportedVersions;
009import ezvcard.VCard;
010import ezvcard.VCardVersion;
011import ezvcard.ValidationWarnings;
012import ezvcard.ValidationWarning;
013
014/*
015 Copyright (c) 2012-2018, Michael Angstadt
016 All rights reserved.
017
018 Redistribution and use in source and binary forms, with or without
019 modification, are permitted provided that the following conditions are met: 
020
021 1. Redistributions of source code must retain the above copyright notice, this
022 list of conditions and the following disclaimer. 
023 2. Redistributions in binary form must reproduce the above copyright notice,
024 this list of conditions and the following disclaimer in the documentation
025 and/or other materials provided with the distribution. 
026
027 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
028 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
029 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
030 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
031 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
032 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
033 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
034 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
035 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
036 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037
038 The views and conclusions contained in the software and documentation are those
039 of the authors and should not be interpreted as representing official policies, 
040 either expressed or implied, of the FreeBSD Project.
041 */
042
043/**
044 * <p>
045 * Defines information about the person's agent.
046 * </p>
047 * 
048 * <p>
049 * <b>Code sample (creating)</b>
050 * </p>
051 * 
052 * <pre class="brush:java">
053 * VCard vcard = new VCard();
054 * 
055 * //URL
056 * Agent agent = new Agent("http://www.linkedin.com/BobSmith");
057 * vcard.setAgent(agent);
058 * 
059 * //vCard
060 * VCard agentVCard = new VCard();
061 * agentVCard.setFormattedName("Bob Smith");
062 * agentVCard.addTelephoneNumber("(555) 123-4566");
063 * agentVCard.addUrl("http://www.linkedin.com/BobSmith");
064 * agent = new Agent(agentVCard);
065 * vcard.setAgent(agent);
066 * </pre>
067 * 
068 * <p>
069 * <b>Code sample (retrieving)</b>
070 * </p>
071 * 
072 * <pre class="brush:java">
073 * VCard vcard = ...
074 * Agent agent = vcard.getAgent();
075 * 
076 * String url = agent.getUrl();
077 * if (url != null) {
078 *   //property value is a URL
079 * }
080 * 
081 * VCard agentVCard = agent.getVCard();
082 * if (agentVCard != null) {
083 *   //property value is a vCard
084 * }
085 * </pre>
086 * 
087 * <p>
088 * <b>Property name:</b> {@code AGENT}
089 * </p>
090 * <p>
091 * <b>Supported versions:</b> {@code 2.1, 3.0}
092 * </p>
093 * 
094 * @author Michael Angstadt
095 * @see <a href="http://tools.ietf.org/html/rfc2426#page-19">RFC 2426 p.19</a>
096 * @see <a href="http://www.imc.org/pdi/vcard-21.doc">vCard 2.1 p.18</a>
097 */
098@SupportedVersions({ VCardVersion.V2_1, VCardVersion.V3_0 })
099public class Agent extends VCardProperty {
100        private String url;
101        private VCard vcard;
102
103        /**
104         * Creates an empty agent property.
105         */
106        public Agent() {
107                //empty
108        }
109
110        /**
111         * Creates an agent property.
112         * @param url a URL pointing to the agent's information
113         */
114        public Agent(String url) {
115                setUrl(url);
116        }
117
118        /**
119         * Creates an agent property.
120         * @param vcard a vCard containing the agent's information
121         */
122        public Agent(VCard vcard) {
123                setVCard(vcard);
124        }
125
126        /**
127         * Copy constructor.
128         * @param original the property to make a copy of
129         */
130        public Agent(Agent original) {
131                super(original);
132                url = original.url;
133                vcard = (original.vcard == null) ? null : new VCard(original.vcard);
134        }
135
136        /**
137         * Gets the URL to the agent's information.
138         * @return the URL or null if not set
139         */
140        public String getUrl() {
141                return url;
142        }
143
144        /**
145         * Sets the URL to the agent's information.
146         * @param url the URL
147         */
148        public void setUrl(String url) {
149                this.url = url;
150                vcard = null;
151        }
152
153        /**
154         * Gets an embedded vCard with the agent's information.
155         * @return the vCard or null if not set
156         */
157        public VCard getVCard() {
158                return vcard;
159        }
160
161        /**
162         * Sets an embedded vCard with the agent's information.
163         * @param vcard the vCard
164         */
165        public void setVCard(VCard vcard) {
166                this.vcard = vcard;
167                url = null;
168        }
169
170        @Override
171        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
172                if (url == null && this.vcard == null) {
173                        warnings.add(new ValidationWarning(8));
174                }
175
176                if (this.vcard != null) {
177                        NumberFormat nf = NumberFormat.getIntegerInstance();
178                        nf.setMinimumIntegerDigits(2);
179
180                        ValidationWarnings validationWarnings = this.vcard.validate(version);
181                        for (Map.Entry<VCardProperty, List<ValidationWarning>> entry : validationWarnings) {
182                                VCardProperty property = entry.getKey();
183                                List<ValidationWarning> propViolations = entry.getValue();
184
185                                for (ValidationWarning propViolation : propViolations) {
186                                        String className = (property == null) ? "" : property.getClass().getSimpleName();
187
188                                        int code = propViolation.getCode();
189                                        String codeStr = (code >= 0) ? "W" + nf.format(code) : "";
190                                        String message = propViolation.getMessage();
191                                        warnings.add(new ValidationWarning(10, className, codeStr, message));
192                                }
193                        }
194                }
195        }
196
197        @Override
198        protected Map<String, Object> toStringValues() {
199                Map<String, Object> values = new LinkedHashMap<String, Object>();
200                values.put("url", url);
201                values.put("vcard", vcard);
202                return values;
203        }
204
205        @Override
206        public Agent copy() {
207                return new Agent(this);
208        }
209
210        @Override
211        public int hashCode() {
212                final int prime = 31;
213                int result = super.hashCode();
214                result = prime * result + ((url == null) ? 0 : url.hashCode());
215                result = prime * result + ((vcard == null) ? 0 : vcard.hashCode());
216                return result;
217        }
218
219        @Override
220        public boolean equals(Object obj) {
221                if (this == obj) return true;
222                if (!super.equals(obj)) return false;
223                Agent other = (Agent) obj;
224                if (url == null) {
225                        if (other.url != null) return false;
226                } else if (!url.equals(other.url)) return false;
227                if (vcard == null) {
228                        if (other.vcard != null) return false;
229                } else if (!vcard.equals(other.vcard)) return false;
230                return true;
231        }
232}