001/*
002Copyright (c) 2011+, HL7, Inc
003All rights reserved.
004
005Redistribution and use in source and binary forms, with or without modification, 
006are permitted provided that the following conditions are met:
007
008 * Redistributions of source code must retain the above copyright notice, this 
009   list of conditions and the following disclaimer.
010 * Redistributions in binary form must reproduce the above copyright notice, 
011   this list of conditions and the following disclaimer in the documentation 
012   and/or other materials provided with the distribution.
013 * Neither the name of HL7 nor the names of its contributors may be used to 
014   endorse or promote products derived from this software without specific 
015   prior written permission.
016
017THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
018ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
019WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
020IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
021INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
022NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
023PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
024WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
025ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
026POSSIBILITY OF SUCH DAMAGE.
027
028*/
029/**
030 * 
031 */
032package org.hl7.fhir.instance.model;
033
034import java.util.*;
035import java.util.zip.DataFormatException;
036
037import ca.uhn.fhir.model.api.annotation.DatatypeDef;
038
039/**
040 * Represents a FHIR instant datatype. Valid precisions values for this type are:
041 * <ul>
042 * <li>{@link TemporalPrecisionEnum#SECOND}
043 * <li>{@link TemporalPrecisionEnum#MILLI}
044 * </ul>
045 */
046@DatatypeDef(name="instant")
047public class InstantType extends BaseDateTimeType {
048
049        private static final long serialVersionUID = 3L;
050        
051        /**
052         * The default precision for this type
053         */
054        public static final TemporalPrecisionEnum DEFAULT_PRECISION = TemporalPrecisionEnum.MILLI;
055
056        /**
057         * Constructor which creates an InstantDt with <b>no timne value</b>. Note
058         * that unlike the default constructor for the Java {@link Date} or
059         * {@link Calendar} objects, this constructor does not initialize the object
060         * with the current time.
061         * 
062         * @see #withCurrentTime() to create a new object that has been initialized
063         *      with the current time.
064         */
065        public InstantType() {
066                super();
067        }
068
069        /**
070         * Create a new DateTimeDt
071         */
072        public InstantType(Calendar theCalendar) {
073                super(theCalendar.getTime(), DEFAULT_PRECISION, theCalendar.getTimeZone());
074        }
075
076        /**
077         * Create a new instance using the given date, precision level, and time zone
078         * 
079         * @throws DataFormatException
080         *             If the specified precision is not allowed for this type
081         */
082        public InstantType(Date theDate, TemporalPrecisionEnum thePrecision, TimeZone theTimezone) {
083                super(theDate, thePrecision, theTimezone);
084        }
085
086
087        /**
088         * Create a new DateTimeDt using an existing value. <b>Use this constructor with caution</b>,
089         * as it may create more precision than warranted (since for example it is possible to pass in
090         * a DateTime with only a year, and this constructor will convert to an InstantDt with 
091         * milliseconds precision).
092         */
093        public InstantType(BaseDateTimeType theDateTime) {
094                // Do not call super(foo) here, we don't want to trigger a DataFormatException
095                setValue(theDateTime.getValue());
096                setPrecision(DEFAULT_PRECISION);
097                setTimeZone(theDateTime.getTimeZone());
098        }
099
100        /**
101         * Create a new DateTimeDt with the given date/time and {@link TemporalPrecisionEnum#MILLI} precision
102         */
103        public InstantType(Date theDate) {
104                super(theDate, DEFAULT_PRECISION, TimeZone.getDefault());
105        }
106
107        /**
108         * Constructor which accepts a date value and a precision value. Valid
109         * precisions values for this type are:
110         * <ul>
111         * <li>{@link TemporalPrecisionEnum#SECOND}
112         * <li>{@link TemporalPrecisionEnum#MILLI}
113         * </ul>
114         */
115        public InstantType(Date theDate, TemporalPrecisionEnum thePrecision) {
116                setValue(theDate);
117                setPrecision(thePrecision);
118                setTimeZone(TimeZone.getDefault());
119        }
120
121        /**
122         * Create a new InstantDt from a string value
123         * 
124         * @param theString
125         *            The string representation of the string. Must be in a valid
126         *            format according to the FHIR specification
127         * @throws DataFormatException
128         */
129        public InstantType(String theString) {
130                super(theString);
131        }
132
133        /**
134         * Invokes {@link Date#after(Date)} on the contained Date against the given
135         * date
136         * 
137         * @throws NullPointerException
138         *             If the {@link #getValue() contained Date} is null
139         */
140        public boolean after(Date theDate) {
141                return getValue().after(theDate);
142        }
143
144        /**
145         * Invokes {@link Date#before(Date)} on the contained Date against the given
146         * date
147         * 
148         * @throws NullPointerException
149         *             If the {@link #getValue() contained Date} is null
150         */
151        public boolean before(Date theDate) {
152                return getValue().before(theDate);
153        }
154
155        /**
156         * Sets the value of this instant to the current time (from the system
157         * clock) and the local/default timezone (as retrieved using
158         * {@link TimeZone#getDefault()}. This TimeZone is generally obtained from
159         * the underlying OS.
160         */
161        public void setToCurrentTimeInLocalTimeZone() {
162                setValue(new Date());
163                setTimeZone(TimeZone.getDefault());
164        }
165
166        @Override
167        boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
168                switch (thePrecision) {
169                case SECOND:
170                case MILLI:
171                        return true;
172                default:
173                        return false;
174                }
175        }
176
177        /**
178         * Factory method which creates a new InstantDt with millisecond precision and initializes it with the
179         * current time and the system local timezone.
180         */
181        public static InstantType withCurrentTime() {
182                return new InstantType(new Date(), TemporalPrecisionEnum.MILLI, TimeZone.getDefault());
183        }
184
185        /**
186         * Returns the default precision for this datatype
187         * 
188         * @see #DEFAULT_PRECISION
189         */
190        @Override
191        protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
192                return DEFAULT_PRECISION;
193        }
194
195
196        @Override
197        public InstantType copy() {
198                return new InstantType(getValueAsString());
199        }
200
201        /**
202         * Returns a new instance of DateTimeType with the current system time and MILLI precision and the system local time
203         * zone
204         */
205        public static InstantType now() {
206                return new InstantType(new Date(), TemporalPrecisionEnum.MILLI, TimeZone.getDefault());
207        }
208
209        /**
210         * Creates a new instance by parsing an HL7 v3 format date time string
211         */
212        public static InstantType parseV3(String theV3String) {
213                InstantType retVal = new InstantType();
214                retVal.setValueAsV3String(theV3String);
215                return retVal;
216        }
217
218        public String fhirType() {
219                return "instant";
220        }
221}