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.Collections;
026import java.util.Date;
027import java.util.List;
028
029import org.apache.commons.lang3.builder.ToStringBuilder;
030import org.apache.commons.lang3.builder.ToStringStyle;
031import org.hl7.fhir.instance.model.api.IPrimitiveType;
032
033import ca.uhn.fhir.context.FhirContext;
034import ca.uhn.fhir.model.api.IQueryParameterOr;
035import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
036import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
037import ca.uhn.fhir.model.primitive.DateDt;
038import ca.uhn.fhir.model.primitive.DateTimeDt;
039import ca.uhn.fhir.model.primitive.InstantDt;
040import ca.uhn.fhir.rest.method.QualifiedParamList;
041import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
042import ca.uhn.fhir.util.ValidateUtil;
043
044@SuppressWarnings("deprecation")
045public class DateParam extends BaseParamWithPrefix<DateParam> implements /*IQueryParameterType , */IQueryParameterOr<DateParam> {
046
047        private final DateTimeDt myValue = new DateTimeDt();
048
049        /**
050         * Constructor
051         */
052        public DateParam() {
053        }
054
055        /**
056         * Constructor
057         */
058        public DateParam(ParamPrefixEnum thePrefix, Date theDate) {
059                setPrefix(thePrefix);
060                setValue(theDate);
061        }
062
063        /**
064         * Constructor
065         */
066        public DateParam(ParamPrefixEnum thePrefix, DateTimeDt theDate) {
067                setPrefix(thePrefix);
068                myValue.setValueAsString(theDate != null ? theDate.getValueAsString() : null);
069        }
070
071        /**
072         * Constructor
073         */
074        public DateParam(ParamPrefixEnum thePrefix, IPrimitiveType<Date> theDate) {
075                setPrefix(thePrefix);
076                myValue.setValueAsString(theDate != null ? theDate.getValueAsString() : null);
077        }
078
079        /**
080         * Constructor
081         */
082        public DateParam(ParamPrefixEnum thePrefix, long theDate) {
083                ValidateUtil.isGreaterThan(theDate, 0, "theDate must not be 0 or negative");
084                setPrefix(thePrefix);
085                setValue(new Date(theDate));
086        }
087
088        /**
089         * Constructor
090         */
091        public DateParam(ParamPrefixEnum thePrefix, String theDate) {
092                setPrefix(thePrefix);
093                setValueAsString(theDate);
094        }
095
096        /**
097         * Constructor
098         * 
099         * @deprecated Use constructors with {@link ParamPrefixEnum} parameter instead, as {@link QuantityCompararatorEnum}
100         *             is deprecated
101         */
102        @Deprecated
103        public DateParam(QuantityCompararatorEnum theComparator, Date theDate) {
104                setPrefix(toPrefix(theComparator));
105                setValue(theDate);
106        }
107
108        /**
109         * Constructor
110         * 
111         * @deprecated Use constructors with {@link ParamPrefixEnum} parameter instead, as {@link QuantityCompararatorEnum}
112         *             is deprecated
113         */
114        @Deprecated
115        public DateParam(QuantityCompararatorEnum theComparator, DateTimeDt theDate) {
116                setPrefix(toPrefix(theComparator));
117                setValue(theDate);
118        }
119
120        /**
121         * Constructor
122         * 
123         * @deprecated Use constructors with {@link ParamPrefixEnum} parameter instead, as {@link QuantityCompararatorEnum}
124         *             is deprecated
125         */
126        @Deprecated
127        public DateParam(QuantityCompararatorEnum theComparator, IPrimitiveType<Date> theDate) {
128                setPrefix(toPrefix(theComparator));
129                setValue(theDate);
130        }
131
132        /**
133         * Constructor
134         * 
135         * @deprecated Use constructors with {@link ParamPrefixEnum} parameter instead, as {@link QuantityCompararatorEnum}
136         *             is deprecated
137         */
138        @Deprecated
139        public DateParam(QuantityCompararatorEnum theComparator, long theDate) {
140                ValidateUtil.isGreaterThan(theDate, 0, "theDate must not be 0 or negative");
141                setPrefix(toPrefix(theComparator));
142                setValue(new Date(theDate));
143        }
144
145        /**
146         * Constructor
147         * 
148         * @deprecated Use constructors with {@link ParamPrefixEnum} parameter instead, as {@link QuantityCompararatorEnum}
149         *             is deprecated
150         */
151        @Deprecated
152        public DateParam(QuantityCompararatorEnum theComparator, String theDate) {
153                setPrefix(toPrefix(theComparator));
154                setValueAsString(theDate);
155        }
156
157        /**
158         * Constructor which takes a complete [qualifier]{date} string.
159         * 
160         * @param theString
161         *           The string
162         */
163        public DateParam(String theString) {
164                setValueAsQueryToken(null, null, null, theString);
165        }
166
167        @Override
168        String doGetQueryParameterQualifier() {
169                return null;
170        }
171
172        @Override
173        String doGetValueAsQueryToken(FhirContext theContext) {
174                StringBuilder b = new StringBuilder();
175                if (getPrefix() != null) {
176                        b.append(ParameterUtil.escapeWithDefault(getPrefix().getValueForContext(theContext)));
177                }
178                
179                if (myValue != null) {
180                        b.append(ParameterUtil.escapeWithDefault(myValue.getValueAsString()));
181                }
182
183                return b.toString();
184        }
185
186        @Override
187        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
188                setValueAsString(theValue);
189        }
190
191        public TemporalPrecisionEnum getPrecision() {
192                if (myValue != null) {
193                        return myValue.getPrecision();
194                }
195                return null;
196        }
197
198        public Date getValue() {
199                if (myValue != null) {
200                        return myValue.getValue();
201                }
202                return null;
203        }
204
205        public DateTimeDt getValueAsDateTimeDt() {
206                if (myValue == null) {
207                        return null;
208                }
209                return new DateTimeDt(myValue.getValue());
210        }
211
212        public InstantDt getValueAsInstantDt() {
213                if (myValue == null) {
214                        return null;
215                }
216                return new InstantDt(myValue.getValue());
217        }
218
219        public String getValueAsString() {
220                if (myValue != null) {
221                        return myValue.getValueAsString();
222                }
223                return null;
224        }
225
226        /**
227         * Returns <code>true</code> if no date/time is specified. Note that this method does not check the comparator, so a
228         * QualifiedDateParam with only a comparator and no date/time is considered empty.
229         */
230        public boolean isEmpty() {
231                return myValue.isEmpty();
232        }
233
234        /**
235         * Sets the value of the param to the given date (sets to the {@link TemporalPrecisionEnum#MILLI millisecond}
236         * precision, and will be encoded using the system local time zone).
237         */
238        public DateParam setValue(Date theValue) {
239                myValue.setValue(theValue, TemporalPrecisionEnum.MILLI);
240                return this;
241        }
242
243        /**
244         * Sets the value using a FHIR Date type, such as a {@link DateDt}, or a DateTimeType.
245         */
246        public void setValue(IPrimitiveType<Date> theValue) {
247                if (theValue != null) {
248                        myValue.setValueAsString(theValue.getValueAsString());
249                } else {
250                        myValue.setValue(null);
251                }
252        }
253
254        /**
255         * Accepts values with or without a prefix (e.g. <code>gt2011-01-01</code> and <code>2011-01-01</code>).
256         * If no prefix is provided in the given value, the {@link #getPrefix() existing prefix} is preserved
257         */
258        public void setValueAsString(String theDate) {
259                if (isNotBlank(theDate)) {
260                        ParamPrefixEnum existingPrefix = getPrefix();
261                        myValue.setValueAsString(super.extractPrefixAndReturnRest(theDate));
262                        if (getPrefix() == null) {
263                                setPrefix(existingPrefix);
264                        }
265                } else {
266                        myValue.setValue(null);
267                }
268        }
269
270        private ParamPrefixEnum toPrefix(QuantityCompararatorEnum theComparator) {
271                if (theComparator != null) {
272                        return ParamPrefixEnum.forDstu1Value(theComparator.getCode());
273                }
274                return null;
275        }
276
277        @Override
278        public String toString() {
279                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
280                b.append("prefix", getPrefix());
281                b.append("value", getValueAsString());
282                return b.build();
283        }
284
285        @Override
286        public void  setValuesAsQueryTokens(FhirContext theContext, String theParamName, QualifiedParamList theParameters) {
287                setMissing(null);
288                setPrefix(null);
289                setValueAsString(null);
290                
291                if (theParameters.size() == 1) {
292                        setValueAsString(theParameters.get(0));
293                } else if (theParameters.size() > 1) {
294                        throw new InvalidRequestException("This server does not support multi-valued dates for this paramater: " + theParameters);
295                }
296                
297        }
298
299        @Override
300        public List<DateParam> getValuesAsQueryTokens() {
301                return Collections.singletonList(this);
302        }
303
304
305}