001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2017 University Health Network
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import static org.apache.commons.lang3.StringUtils.isNotBlank;
024
025import java.util.*;
026
027import org.apache.commons.lang3.builder.ToStringBuilder;
028import org.apache.commons.lang3.builder.ToStringStyle;
029import org.hl7.fhir.instance.model.api.IPrimitiveType;
030
031import ca.uhn.fhir.context.FhirContext;
032import ca.uhn.fhir.model.api.IQueryParameterOr;
033import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
034import ca.uhn.fhir.model.primitive.*;
035import ca.uhn.fhir.rest.api.QualifiedParamList;
036import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
037import ca.uhn.fhir.util.ValidateUtil;
038
039public class DateParam extends BaseParamWithPrefix<DateParam> implements /*IQueryParameterType , */IQueryParameterOr<DateParam> {
040
041        private static final long serialVersionUID = 1L;
042        
043        private final DateParamDateTimeHolder myValue = new DateParamDateTimeHolder();
044
045        /**
046         * Constructor
047         */
048        public DateParam() {
049        }
050
051        /**
052         * Constructor
053         */
054        public DateParam(ParamPrefixEnum thePrefix, Date theDate) {
055                setPrefix(thePrefix);
056                setValue(theDate);
057        }
058
059        /**
060         * Constructor
061         */
062        public DateParam(ParamPrefixEnum thePrefix, DateTimeDt theDate) {
063                setPrefix(thePrefix);
064                myValue.setValueAsString(theDate != null ? theDate.getValueAsString() : null);
065        }
066
067        /**
068         * Constructor
069         */
070        public DateParam(ParamPrefixEnum thePrefix, IPrimitiveType<Date> theDate) {
071                setPrefix(thePrefix);
072                myValue.setValueAsString(theDate != null ? theDate.getValueAsString() : null);
073        }
074
075        /**
076         * Constructor
077         */
078        public DateParam(ParamPrefixEnum thePrefix, long theDate) {
079                ValidateUtil.isGreaterThan(theDate, 0, "theDate must not be 0 or negative");
080                setPrefix(thePrefix);
081                setValue(new Date(theDate));
082        }
083
084        /**
085         * Constructor
086         */
087        public DateParam(ParamPrefixEnum thePrefix, String theDate) {
088                setPrefix(thePrefix);
089                setValueAsString(theDate);
090        }
091
092
093        /**
094         * Constructor which takes a complete [qualifier]{date} string.
095         * 
096         * @param theString
097         *           The string
098         */
099        public DateParam(String theString) {
100                setValueAsQueryToken(null, null, null, theString);
101        }
102
103        @Override
104        String doGetQueryParameterQualifier() {
105                return null;
106        }
107
108        @Override
109        String doGetValueAsQueryToken(FhirContext theContext) {
110                StringBuilder b = new StringBuilder();
111                if (getPrefix() != null) {
112                        b.append(ParameterUtil.escapeWithDefault(getPrefix().getValue()));
113                }
114                
115                if (myValue != null) {
116                        b.append(ParameterUtil.escapeWithDefault(myValue.getValueAsString()));
117                }
118
119                return b.toString();
120        }
121
122        @Override
123        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
124                setValueAsString(theValue);
125        }
126
127        public TemporalPrecisionEnum getPrecision() {
128                if (myValue != null) {
129                        return myValue.getPrecision();
130                }
131                return null;
132        }
133
134        public Date getValue() {
135                if (myValue != null) {
136                        return myValue.getValue();
137                }
138                return null;
139        }
140
141        public DateTimeDt getValueAsDateTimeDt() {
142                if (myValue == null) {
143                        return null;
144                }
145                return new DateTimeDt(myValue.getValue());
146        }
147
148        public InstantDt getValueAsInstantDt() {
149                if (myValue == null) {
150                        return null;
151                }
152                return new InstantDt(myValue.getValue());
153        }
154
155        public String getValueAsString() {
156                if (myValue != null) {
157                        return myValue.getValueAsString();
158                }
159                return null;
160        }
161
162        @Override
163        public List<DateParam> getValuesAsQueryTokens() {
164                return Collections.singletonList(this);
165        }
166
167        /**
168         * Returns <code>true</code> if no date/time is specified. Note that this method does not check the comparator, so a
169         * QualifiedDateParam with only a comparator and no date/time is considered empty.
170         */
171        public boolean isEmpty() {
172                return myValue.isEmpty();
173        }
174
175        /**
176         * Sets the value of the param to the given date (sets to the {@link TemporalPrecisionEnum#MILLI millisecond}
177         * precision, and will be encoded using the system local time zone).
178         */
179        public DateParam setValue(Date theValue) {
180                myValue.setValue(theValue, TemporalPrecisionEnum.MILLI);
181                return this;
182        }
183
184        /**
185         * Sets the value using a FHIR Date type, such as a {@link DateDt}, or a DateTimeType.
186         */
187        public void setValue(IPrimitiveType<Date> theValue) {
188                if (theValue != null) {
189                        myValue.setValueAsString(theValue.getValueAsString());
190                } else {
191                        myValue.setValue(null);
192                }
193        }
194
195        /**
196         * Accepts values with or without a prefix (e.g. <code>gt2011-01-01</code> and <code>2011-01-01</code>).
197         * If no prefix is provided in the given value, the {@link #getPrefix() existing prefix} is preserved
198         */
199        public void setValueAsString(String theDate) {
200                if (isNotBlank(theDate)) {
201                        ParamPrefixEnum existingPrefix = getPrefix();
202                        myValue.setValueAsString(super.extractPrefixAndReturnRest(theDate));
203                        if (getPrefix() == null) {
204                                setPrefix(existingPrefix);
205                        }
206                } else {
207                        myValue.setValue(null);
208                }
209        }
210
211        @Override
212        public void  setValuesAsQueryTokens(FhirContext theContext, String theParamName, QualifiedParamList theParameters) {
213                setMissing(null);
214                setPrefix(null);
215                setValueAsString(null);
216                
217                if (theParameters.size() == 1) {
218                        setValueAsString(theParameters.get(0));
219                } else if (theParameters.size() > 1) {
220                        throw new InvalidRequestException("This server does not support multi-valued dates for this paramater: " + theParameters);
221                }
222                
223        }
224
225
226        @Override
227        public String toString() {
228                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
229                b.append("prefix", getPrefix());
230                b.append("value", getValueAsString());
231                return b.build();
232        }
233
234        public class DateParamDateTimeHolder extends BaseDateTimeDt {
235                @Override
236                protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
237                        return TemporalPrecisionEnum.SECOND;
238                }
239
240                @Override
241                protected boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
242                        return true;
243                }
244
245        }
246
247
248}