001package ezvcard.property;
002
003import java.util.Date;
004import java.util.LinkedHashMap;
005import java.util.List;
006import java.util.Map;
007
008import ezvcard.VCard;
009import ezvcard.VCardVersion;
010import ezvcard.ValidationWarning;
011import ezvcard.parameter.Calscale;
012import ezvcard.parameter.VCardParameters;
013import ezvcard.util.PartialDate;
014
015/*
016 Copyright (c) 2012-2018, 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 * Represents a property with a date and/or time value.
046 * @author Michael Angstadt
047 */
048public class DateOrTimeProperty extends VCardProperty implements HasAltId {
049        private String text;
050        private Date date;
051        private PartialDate partialDate;
052        private boolean dateHasTime;
053
054        /**
055         * Creates a date-and-or-time property.
056         * @param date the date value
057         */
058        public DateOrTimeProperty(Date date) {
059                this(date, false);
060        }
061
062        /**
063         * Creates a date-and-or-time property.
064         * @param date the date value
065         * @param hasTime true to include the date's time component, false if it's
066         * strictly a date
067         */
068        public DateOrTimeProperty(Date date, boolean hasTime) {
069                setDate(date, hasTime);
070        }
071
072        /**
073         * Creates a date-and-or-time property.
074         * @param partialDate the partial date value (vCard 4.0 only)
075         */
076        public DateOrTimeProperty(PartialDate partialDate) {
077                setPartialDate(partialDate);
078        }
079
080        /**
081         * Creates a date-and-or-time property.
082         * @param text the text value (vCard 4.0 only)
083         */
084        public DateOrTimeProperty(String text) {
085                setText(text);
086        }
087
088        /**
089         * Copy constructor.
090         * @param original the property to make a copy of
091         */
092        public DateOrTimeProperty(DateOrTimeProperty original) {
093                super(original);
094                text = original.text;
095                date = (original.date == null) ? null : new Date(original.date.getTime());
096                partialDate = original.partialDate;
097                dateHasTime = original.dateHasTime;
098        }
099
100        /**
101         * Gets the date value.
102         * @return the date value or null if not set
103         */
104        public Date getDate() {
105                return date;
106        }
107
108        /**
109         * Sets the value of this property to a complete date.
110         * @param date the date
111         * @param hasTime true to include the date's time component, false if it's
112         * strictly a date
113         */
114        public void setDate(Date date, boolean hasTime) {
115                this.date = date;
116                this.dateHasTime = (date == null) ? false : hasTime;
117                text = null;
118                partialDate = null;
119        }
120
121        /**
122         * Gets the reduced accuracy or truncated date. This is only supported by
123         * vCard 4.0.
124         * @return the reduced accuracy or truncated date or null if not set
125         * @see <a href="http://tools.ietf.org/html/rfc6350">RFC 6350 p.12-14</a>
126         */
127        public PartialDate getPartialDate() {
128                return partialDate;
129        }
130
131        /**
132         * <p>
133         * Sets the value of this property to a reduced accuracy or truncated date.
134         * This is only supported by vCard 4.0.
135         * </p>
136         * 
137         * <pre class="brush:java">
138         * Birthday bday = new Birthday();
139         * bday.setPartialDate(PartialDate.date(null, 4, 20)); //April 20
140         * </pre>
141         * @param partialDate the reduced accuracy or truncated date
142         * @see <a href="http://tools.ietf.org/html/rfc6350">RFC 6350 p.12-14</a>
143         */
144        public void setPartialDate(PartialDate partialDate) {
145                this.partialDate = partialDate;
146                dateHasTime = (partialDate == null) ? false : partialDate.hasTimeComponent();
147                text = null;
148                date = null;
149        }
150
151        /**
152         * Gets the text value of this type. This is only supported by vCard 4.0.
153         * @return the text value or null if not set
154         */
155        public String getText() {
156                return text;
157        }
158
159        /**
160         * Sets the value of this property to a text string. This is only supported
161         * by vCard 4.0.
162         * @param text the text value
163         */
164        public void setText(String text) {
165                this.text = text;
166                date = null;
167                partialDate = null;
168                dateHasTime = false;
169        }
170
171        /**
172         * Determines whether the "date" or "partialDate" fields have a time
173         * component.
174         * @return true if the date has a time component, false if it's strictly a
175         * date, and false if a text value is defined
176         */
177        public boolean hasTime() {
178                return dateHasTime;
179        }
180
181        /**
182         * <p>
183         * Gets the type of calendar that is used for a date or date-time property
184         * value.
185         * </p>
186         * <p>
187         * <b>Supported versions:</b> {@code 4.0}
188         * </p>
189         * @return the type of calendar or null if not found
190         * @see VCardParameters#getCalscale
191         */
192        public Calscale getCalscale() {
193                return parameters.getCalscale();
194        }
195
196        /**
197         * <p>
198         * Sets the type of calendar that is used for a date or date-time property
199         * value.
200         * </p>
201         * <p>
202         * <b>Supported versions:</b> {@code 4.0}
203         * </p>
204         * @param calscale the type of calendar or null to remove
205         * @see VCardParameters#setCalscale
206         */
207        public void setCalscale(Calscale calscale) {
208                parameters.setCalscale(calscale);
209        }
210
211        @Override
212        public String getLanguage() {
213                return super.getLanguage();
214        }
215
216        @Override
217        public void setLanguage(String language) {
218                super.setLanguage(language);
219        }
220
221        //@Override
222        public String getAltId() {
223                return parameters.getAltId();
224        }
225
226        //@Override
227        public void setAltId(String altId) {
228                parameters.setAltId(altId);
229        }
230
231        @Override
232        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
233                if (date == null && partialDate == null && text == null) {
234                        warnings.add(new ValidationWarning(8));
235                }
236
237                if (version == VCardVersion.V2_1 || version == VCardVersion.V3_0) {
238                        if (text != null) {
239                                warnings.add(new ValidationWarning(11));
240                        }
241                        if (partialDate != null) {
242                                warnings.add(new ValidationWarning(12));
243                        }
244                }
245        }
246
247        @Override
248        protected Map<String, Object> toStringValues() {
249                Map<String, Object> values = new LinkedHashMap<String, Object>();
250                values.put("text", text);
251                values.put("date", date);
252                values.put("dateHasTime", dateHasTime);
253                values.put("partialDate", partialDate);
254                return values;
255        }
256
257        @Override
258        public int hashCode() {
259                final int prime = 31;
260                int result = super.hashCode();
261                result = prime * result + ((date == null) ? 0 : date.hashCode());
262                result = prime * result + (dateHasTime ? 1231 : 1237);
263                result = prime * result + ((partialDate == null) ? 0 : partialDate.hashCode());
264                result = prime * result + ((text == null) ? 0 : text.hashCode());
265                return result;
266        }
267
268        @Override
269        public boolean equals(Object obj) {
270                if (this == obj) return true;
271                if (!super.equals(obj)) return false;
272                DateOrTimeProperty other = (DateOrTimeProperty) obj;
273                if (date == null) {
274                        if (other.date != null) return false;
275                } else if (!date.equals(other.date)) return false;
276                if (dateHasTime != other.dateHasTime) return false;
277                if (partialDate == null) {
278                        if (other.partialDate != null) return false;
279                } else if (!partialDate.equals(other.partialDate)) return false;
280                if (text == null) {
281                        if (other.text != null) return false;
282                } else if (!text.equals(other.text)) return false;
283                return true;
284        }
285}