001package ezvcard.property;
002
003import java.time.Instant;
004import java.time.LocalDate;
005import java.time.LocalDateTime;
006import java.time.OffsetDateTime;
007import java.time.temporal.Temporal;
008import java.util.LinkedHashMap;
009import java.util.List;
010import java.util.Map;
011import java.util.Objects;
012
013import ezvcard.VCard;
014import ezvcard.VCardVersion;
015import ezvcard.ValidationWarning;
016import ezvcard.parameter.Calscale;
017import ezvcard.parameter.VCardParameters;
018import ezvcard.util.PartialDate;
019
020/*
021 Copyright (c) 2012-2023, Michael Angstadt
022 All rights reserved.
023
024 Redistribution and use in source and binary forms, with or without
025 modification, are permitted provided that the following conditions are met: 
026
027 1. Redistributions of source code must retain the above copyright notice, this
028 list of conditions and the following disclaimer. 
029 2. Redistributions in binary form must reproduce the above copyright notice,
030 this list of conditions and the following disclaimer in the documentation
031 and/or other materials provided with the distribution. 
032
033 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
034 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
035 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
037 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
039 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
040 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
041 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
042 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
043
044 The views and conclusions contained in the software and documentation are those
045 of the authors and should not be interpreted as representing official policies, 
046 either expressed or implied, of the FreeBSD Project.
047 */
048
049/**
050 * Represents a property that typically contains a date/time value, but can also
051 * contain a partial date or free-text value.
052 * @author Michael Angstadt
053 */
054public class DateOrTimeProperty extends VCardProperty implements HasAltId {
055        private String text;
056        private Temporal date;
057        private PartialDate partialDate;
058
059        /**
060         * Creates a date-and-or-time property.
061         * @param date the date value (should be one of the following:
062         * {@link LocalDate}, {@link LocalDateTime}, {@link OffsetDateTime},
063         * {@link Instant})
064         */
065        public DateOrTimeProperty(Temporal date) {
066                this.date = date;
067        }
068
069        /**
070         * Creates a date-and-or-time property.
071         * @param partialDate the partial date value (vCard 4.0 only)
072         */
073        public DateOrTimeProperty(PartialDate partialDate) {
074                setPartialDate(partialDate);
075        }
076
077        /**
078         * Creates a date-and-or-time property.
079         * @param text the text value (vCard 4.0 only)
080         */
081        public DateOrTimeProperty(String text) {
082                setText(text);
083        }
084
085        /**
086         * Copy constructor.
087         * @param original the property to make a copy of
088         */
089        public DateOrTimeProperty(DateOrTimeProperty original) {
090                super(original);
091                text = original.text;
092                date = original.date;
093                partialDate = original.partialDate;
094        }
095
096        /**
097         * Gets the date value. It should be an instance of one of the following
098         * classes: {@link LocalDate}, {@link LocalDateTime},
099         * {@link OffsetDateTime}, {@link Instant}.
100         * @return the date value or null if not set
101         */
102        public Temporal getDate() {
103                return date;
104        }
105
106        /**
107         * Sets the value of this property to a date. It should be an instance of
108         * one of the following classes: {@link LocalDate}, {@link LocalDateTime},
109         * {@link OffsetDateTime}, {@link Instant}.
110         * @param date the date
111         */
112        public void setDate(Temporal date) {
113                this.date = date;
114                text = null;
115                partialDate = null;
116        }
117
118        /**
119         * Gets the reduced accuracy or truncated date. This is only supported by
120         * vCard 4.0.
121         * @return the reduced accuracy or truncated date or null if not set
122         * @see <a href="http://tools.ietf.org/html/rfc6350">RFC 6350 p.12-14</a>
123         */
124        public PartialDate getPartialDate() {
125                return partialDate;
126        }
127
128        /**
129         * <p>
130         * Sets the value of this property to a reduced accuracy or truncated date.
131         * This is only supported by vCard 4.0.
132         * </p>
133         * 
134         * <pre class="brush:java">
135         * Birthday bday = new Birthday();
136         * bday.setPartialDate(PartialDate.date(null, 4, 20)); //April 20
137         * </pre>
138         * 
139         * @param partialDate the reduced accuracy or truncated date
140         * @see <a href="http://tools.ietf.org/html/rfc6350">RFC 6350 p.12-14</a>
141         */
142        public void setPartialDate(PartialDate partialDate) {
143                this.partialDate = partialDate;
144                text = null;
145                date = null;
146        }
147
148        /**
149         * Gets the text value of this type. This is only supported by vCard 4.0.
150         * @return the text value or null if not set
151         */
152        public String getText() {
153                return text;
154        }
155
156        /**
157         * Sets the value of this property to a text string. This is only supported
158         * by vCard 4.0.
159         * @param text the text value or null if not set
160         */
161        public void setText(String text) {
162                this.text = text;
163                date = null;
164                partialDate = null;
165        }
166
167        /**
168         * <p>
169         * Gets the type of calendar that is used for a date or date-time property
170         * value.
171         * </p>
172         * <p>
173         * <b>Supported versions:</b> {@code 4.0}
174         * </p>
175         * @return the type of calendar or null if not found
176         * @see VCardParameters#getCalscale
177         */
178        public Calscale getCalscale() {
179                return parameters.getCalscale();
180        }
181
182        /**
183         * <p>
184         * Sets the type of calendar that is used for a date or date-time property
185         * value.
186         * </p>
187         * <p>
188         * <b>Supported versions:</b> {@code 4.0}
189         * </p>
190         * @param calscale the type of calendar or null to remove
191         * @see VCardParameters#setCalscale
192         */
193        public void setCalscale(Calscale calscale) {
194                parameters.setCalscale(calscale);
195        }
196
197        @Override
198        public String getLanguage() {
199                return super.getLanguage();
200        }
201
202        @Override
203        public void setLanguage(String language) {
204                super.setLanguage(language);
205        }
206
207        //@Override
208        public String getAltId() {
209                return parameters.getAltId();
210        }
211
212        //@Override
213        public void setAltId(String altId) {
214                parameters.setAltId(altId);
215        }
216
217        @Override
218        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
219                if (date == null && partialDate == null && text == null) {
220                        warnings.add(new ValidationWarning(8));
221                }
222
223                if (version == VCardVersion.V2_1 || version == VCardVersion.V3_0) {
224                        if (text != null) {
225                                warnings.add(new ValidationWarning(11));
226                        }
227                        if (partialDate != null) {
228                                warnings.add(new ValidationWarning(12));
229                        }
230                }
231        }
232
233        @Override
234        protected Map<String, Object> toStringValues() {
235                Map<String, Object> values = new LinkedHashMap<>();
236                values.put("text", text);
237                values.put("date", date);
238                values.put("partialDate", partialDate);
239                return values;
240        }
241
242        @Override
243        public int hashCode() {
244                final int prime = 31;
245                int result = super.hashCode();
246                result = prime * result + Objects.hash(date, partialDate, text);
247                return result;
248        }
249
250        @Override
251        public boolean equals(Object obj) {
252                if (this == obj) return true;
253                if (!super.equals(obj)) return false;
254                if (getClass() != obj.getClass()) return false;
255                DateOrTimeProperty other = (DateOrTimeProperty) obj;
256                return Objects.equals(date, other.date) && Objects.equals(partialDate, other.partialDate) && Objects.equals(text, other.text);
257        }
258}