001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2016 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 java.util.Collections;
024import java.util.Date;
025import java.util.List;
026
027import org.apache.commons.lang3.Validate;
028import org.hl7.fhir.instance.model.api.IPrimitiveType;
029
030import ca.uhn.fhir.model.api.IQueryParameterOr;
031import ca.uhn.fhir.model.api.IQueryParameterType;
032import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
033import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
034import ca.uhn.fhir.model.primitive.DateTimeDt;
035import ca.uhn.fhir.model.primitive.InstantDt;
036import ca.uhn.fhir.parser.DataFormatException;
037import ca.uhn.fhir.rest.method.QualifiedParamList;
038import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
039
040public class DateParam extends DateTimeDt implements IQueryParameterType, IQueryParameterOr<DateParam> {
041
042        private BaseParam myBase=new BaseParam.ComposableBaseParam();
043        private QuantityCompararatorEnum myComparator;
044
045        /**
046         * Constructor
047         */
048        public DateParam() {
049        }
050
051        /**
052         * Constructor
053         */
054        public DateParam(QuantityCompararatorEnum theComparator, Date theDate) {
055                myComparator = theComparator;
056                setValue(theDate);
057        }
058
059        /**
060         * Constructor
061         */
062        public DateParam(QuantityCompararatorEnum theComparator, DateTimeDt theDate) {
063                myComparator = theComparator;
064                setValueAsString(theDate != null ? theDate.getValueAsString() : null);
065        }
066
067        /**
068         * Constructor
069         */
070        public DateParam(QuantityCompararatorEnum theComparator, IPrimitiveType<Date> theDate) {
071                myComparator = theComparator;
072                setValueAsString(theDate != null ? theDate.getValueAsString() : null);
073        }
074
075        /**
076         * Constructor
077         */
078        public DateParam(QuantityCompararatorEnum theComparator, long theDate) {
079                Validate.inclusiveBetween(1, Long.MAX_VALUE, theDate, "theDate must not be 0 or negative");
080                myComparator = theComparator;
081                setValue(new Date(theDate));
082        }
083
084        /**
085         * Constructor
086         */
087        public DateParam(QuantityCompararatorEnum theComparator, String theDate) {
088                myComparator = theComparator;
089                setValueAsString(theDate);
090        }
091
092        /**
093         * Constructor which takes a complete [qualifier]{date} string.
094         * 
095         * @param theString
096         *            The string
097         */
098        public DateParam(String theString) {
099                setValueAsQueryToken(null, theString);
100        }
101
102        /**
103         * Returns the comparator, or <code>null</code> if none has been set
104         */
105        public QuantityCompararatorEnum getComparator() {
106                return myComparator;
107        }
108
109        @Override
110        public Boolean getMissing() {
111                return myBase.getMissing();
112        }
113
114        @Override
115        public String getQueryParameterQualifier() {
116                if (myBase.getMissing()!=null) {
117                        return myBase.getQueryParameterQualifier();
118                }
119                return null;
120        }
121
122        public DateTimeDt getValueAsDateTimeDt() {
123                return new DateTimeDt(getValueAsString());
124        }
125
126        public InstantDt getValueAsInstantDt() {
127                return new InstantDt(getValue());
128        }
129
130        @Override
131        public String getValueAsQueryToken() {
132                if (myBase.getMissing()!=null) {
133                        return myBase.getValueAsQueryToken();
134                }
135                if (myComparator != null && getValue() != null) {
136                        return myComparator.getCode() + getValueAsString();
137                } else if (myComparator == null && getValue() != null) {
138                        return getValueAsString();
139                }
140                return "";
141        }
142
143        @Override
144        public List<DateParam> getValuesAsQueryTokens() {
145                return Collections.singletonList(this);
146        }
147
148        /**
149         * Returns <code>true</code> if no date/time is specified. Note that this method does not check the comparator, so a
150         * QualifiedDateParam with only a comparator and no date/time is considered empty.
151         */
152        @Override
153        public boolean isEmpty() {
154                // Just here to provide a javadoc
155                return super.isEmpty();
156        }
157
158        public void setComparator(QuantityCompararatorEnum theComparator) {
159                myComparator = theComparator;
160        }
161
162        @Override
163        public void setMissing(Boolean theMissing) {
164                myBase.setMissing(theMissing);
165        }
166
167        @Override
168        public DateParam setValue(Date theValue) {
169                super.setValue(theValue, TemporalPrecisionEnum.MILLI);
170                return this;
171        }
172
173        @Override
174        public void setValueAsQueryToken(String theQualifier, String theValue) {
175                myBase.setValueAsQueryToken(theQualifier, theValue);
176                if (myBase.getMissing()!=null) {
177                        setValue(null);
178                        myComparator=null;
179                        return;
180                }
181
182                if (theValue.length() < 2) {
183                        throw new DataFormatException("Invalid qualified date parameter: " + theValue);
184                }
185
186                char char0 = theValue.charAt(0);
187                char char1 = theValue.charAt(1);
188                if (Character.isDigit(char0)) {
189                        setValueAsString(theValue);
190                } else {
191                        int dateStart = 2;
192                        if (Character.isDigit(char1)) {
193                                dateStart = 1;
194                        }
195
196                        String comparatorString = theValue.substring(0, dateStart);
197                        QuantityCompararatorEnum comparator = QuantityCompararatorEnum.VALUESET_BINDER.fromCodeString(comparatorString);
198                        if (comparator == null) {
199                                throw new DataFormatException("Invalid date qualifier: " + comparatorString);
200                        }
201
202                        String dateString = theValue.substring(dateStart);
203                        setValueAsString(dateString);
204                        setComparator(comparator);
205                }
206
207        }
208
209        @Override
210        public void  setValuesAsQueryTokens(QualifiedParamList theParameters) {
211                myBase.setMissing(null);
212                myComparator = null;
213                setValueAsString(null);
214                
215                if (theParameters.size() == 1) {
216                        setValueAsString(theParameters.get(0));
217                } else if (theParameters.size() > 1) {
218                        throw new InvalidRequestException("This server does not support multi-valued dates for this paramater: " + theParameters);
219                }
220                
221        }
222
223        @Override
224        public String toString() {
225                StringBuilder b = new StringBuilder();
226                b.append(getClass().getSimpleName());
227                b.append("[");
228                if (myComparator!=null) {
229                        b.append(myComparator.getCode());
230                }
231                b.append(getValueAsString());
232                if (myBase.getMissing()!=null) {
233                        b.append(" missing=").append(myBase.getMissing());
234                }
235                b.append("]");
236                return b.toString();
237        }
238
239}