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 */
022import static ca.uhn.fhir.rest.param.ParameterUtil.escape;
023import static org.apache.commons.lang3.StringUtils.defaultString;
024
025import java.math.BigDecimal;
026import java.util.List;
027
028import org.apache.commons.lang3.StringUtils;
029import org.apache.commons.lang3.builder.ToStringBuilder;
030import org.apache.commons.lang3.builder.ToStringStyle;
031
032import ca.uhn.fhir.model.api.IQueryParameterType;
033import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
034import ca.uhn.fhir.model.primitive.BoundCodeDt;
035import ca.uhn.fhir.model.primitive.CodeDt;
036import ca.uhn.fhir.model.primitive.DecimalDt;
037import ca.uhn.fhir.model.primitive.StringDt;
038import ca.uhn.fhir.model.primitive.UriDt;
039
040public class QuantityParam extends BaseParam implements IQueryParameterType {
041
042        private boolean myApproximate;
043        private InternalQuantityDt myQuantity = new InternalQuantityDt();
044
045        /**
046         * Constructor
047         */
048        public QuantityParam() {
049        }
050
051        /**
052         * Constructor
053         * 
054         * @param theComparator
055         *            The comparator, or <code>null</code> for an equals comparator
056         * @param theValue
057         *            A quantity value
058         * @param theSystem
059         *            The unit system
060         * @param theUnits
061         *            The unit code
062         */
063        public QuantityParam(QuantityCompararatorEnum theComparator, BigDecimal theValue, String theSystem, String theUnits) {
064                setComparator(theComparator);
065                setValue(theValue);
066                setSystem(theSystem);
067                setUnits(theUnits);
068        }
069
070        /**
071         * Constructor
072         * 
073         * @param theComparator
074         *            The comparator, or <code>null</code> for an equals comparator
075         * @param theValue
076         *            A quantity value
077         * @param theSystem
078         *            The unit system
079         * @param theUnits
080         *            The unit code
081         */
082        public QuantityParam(QuantityCompararatorEnum theComparator, double theValue, String theSystem, String theUnits) {
083                setComparator(theComparator);
084                setValue(theValue);
085                setSystem(theSystem);
086                setUnits(theUnits);
087        }
088
089        /**
090         * Constructor
091         * 
092         * @param theComparator
093         *            The comparator, or <code>null</code> for an equals comparator
094         * @param theValue
095         *            A quantity value
096         * @param theSystem
097         *            The unit system
098         * @param theUnits
099         *            The unit code
100         */
101        public QuantityParam(QuantityCompararatorEnum theComparator, long theValue, String theSystem, String theUnits) {
102                setComparator(theComparator);
103                setValue(theValue);
104                setSystem(theSystem);
105                setUnits(theUnits);
106        }
107
108        /**
109         * Constructor
110         * 
111         * @param theQuantity
112         *            A quantity value (with no system or units), such as "100.0" or "&lt;=4"
113         */
114        public QuantityParam(String theQuantity) {
115                setValueAsQueryToken(null, theQuantity);
116        }
117
118        /**
119         * Constructor
120         * 
121         * @param theQuantity
122         *            A quantity value (with no system or units), such as <code>100</code>
123         */
124        public QuantityParam(long theQuantity) {
125                setValueAsQueryToken(null, Long.toString(theQuantity));
126        }
127
128        /**
129         * Constructor
130         * 
131         * @param theQuantity
132         *            A quantity value (with no system or units), such as "100.0" or "&lt;=4"
133         * @param theSystem
134         *            The unit system
135         * @param theUnits
136         *            The unit code
137         */
138        public QuantityParam(String theQuantity, String theSystem, String theUnits) {
139                setValueAsQueryToken(null, theQuantity);
140                setSystem(theSystem);
141                setUnits(theUnits);
142        }
143
144        private void clear() {
145                setMissing(null);
146                myQuantity.setComparator((BoundCodeDt<QuantityCompararatorEnum>) null);
147                myQuantity.setCode((CodeDt) null);
148                myQuantity.setSystem((UriDt) null);
149                myQuantity.setUnits((StringDt) null);
150                myQuantity.setValue((DecimalDt) null);
151                myApproximate = false;
152        }
153
154        @Override
155        String doGetQueryParameterQualifier() {
156                return null;
157        }
158
159        @Override
160        String doGetValueAsQueryToken() {
161                StringBuilder b = new StringBuilder();
162                if (myApproximate) {
163                        b.append('~');
164                } else {
165                        b.append(defaultString(escape(myQuantity.getComparatorElement().getValue())));
166                }
167
168                if (!myQuantity.getValueElement().isEmpty()) {
169                        b.append(defaultString(escape(myQuantity.getValueElement().getValueAsString())));
170                }
171                b.append('|');
172                if (!myQuantity.getSystemElement().isEmpty()) {
173                        b.append(defaultString(escape(myQuantity.getSystemElement().getValueAsString())));
174                }
175                b.append('|');
176                if (!myQuantity.getUnitsElement().isEmpty()) {
177                        b.append(defaultString(escape(myQuantity.getUnitsElement().getValueAsString())));
178                }
179
180                return b.toString();
181        }
182
183        @Override
184        void doSetValueAsQueryToken(String theQualifier, String theValue) {
185                clear();
186
187                if (theValue == null) {
188                        return;
189                }
190                List<String> parts = ParameterUtil.splitParameterString(theValue, '|', true);
191
192                if (parts.size() > 0 && StringUtils.isNotBlank(parts.get(0))) {
193                        if (parts.get(0).startsWith("~")) {
194                                myQuantity.setComparator((QuantityCompararatorEnum) null);
195                                myApproximate = true;
196                                myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
197                        } else if (parts.get(0).startsWith("<=")) {
198                                myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS);
199                                myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
200                        } else if (parts.get(0).startsWith("<")) {
201                                myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN);
202                                String valStr = parts.get(0).substring(1);
203                                myQuantity.setValue(new BigDecimal(valStr));
204                        } else if (parts.get(0).startsWith(">=")) {
205                                myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS);
206                                myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
207                        } else if (parts.get(0).startsWith(">")) {
208                                myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN);
209                                myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
210                        } else {
211                                myQuantity.setValue(new BigDecimal(parts.get(0)));
212                        }
213                }
214                if (parts.size() > 1 && StringUtils.isNotBlank(parts.get(1))) {
215                        myQuantity.setSystem(parts.get(1));
216                }
217                if (parts.size() > 2 && StringUtils.isNotBlank(parts.get(2))) {
218                        myQuantity.setUnits(parts.get(2));
219                }
220
221        }
222
223        public QuantityCompararatorEnum getComparator() {
224                return myQuantity.getComparatorElement().getValueAsEnum();
225        }
226
227        public UriDt getSystem() {
228                return myQuantity.getSystemElement();
229        }
230
231        public String getUnits() {
232                return myQuantity.getUnitsElement().getValue();
233        }
234
235        public DecimalDt getValue() {
236                return myQuantity.getValueElement();
237        }
238
239        public boolean isApproximate() {
240                return myApproximate;
241        }
242
243        public void setApproximate(boolean theApproximate) {
244                myApproximate = theApproximate;
245                if (theApproximate) {
246                        myQuantity.setComparator((QuantityCompararatorEnum) null);
247                }
248        }
249
250        public QuantityParam setComparator(QuantityCompararatorEnum theComparator) {
251                myQuantity.setComparator(theComparator);
252                return this;
253        }
254
255        public QuantityParam setComparator(String theComparator) {
256                if ("~".equals(theComparator)) {
257                        myApproximate = true;
258                        myQuantity.setComparator(((QuantityCompararatorEnum) null));
259                } else {
260                        myApproximate = false;
261                        myQuantity.setComparator(QuantityCompararatorEnum.VALUESET_BINDER.fromCodeString(theComparator));
262                }
263                return this;
264        }
265
266        public QuantityParam setSystem(String theSystem) {
267                myQuantity.setSystem(theSystem);
268                return this;
269        }
270
271        public QuantityParam setSystem(UriDt theSystem) {
272                myQuantity.setSystem(theSystem);
273                return this;
274        }
275
276        public QuantityParam setUnits(String theUnits) {
277                myQuantity.setUnits(theUnits);
278                return this;
279        }
280
281        public QuantityParam setValue(BigDecimal theValue) {
282                myQuantity.setValue(theValue);
283                return this;
284        }
285
286        public QuantityParam setValue(DecimalDt theValue) {
287                myQuantity.setValue(theValue);
288                return this;
289        }
290
291        public QuantityParam setValue(double theValue) {
292                myQuantity.setValue(theValue);
293                return this;
294        }
295
296        public QuantityParam setValue(long theValue) {
297                myQuantity.setValue(theValue);
298                return this;
299        }
300
301        @Override
302        public String toString() {
303                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
304                b.append("cmp", myQuantity.getComparatorElement().getValueAsString());
305                b.append("value", myQuantity.getValueElement().getValueAsString());
306                b.append("system", myQuantity.getSystemElement().getValueAsString());
307                b.append("units", myQuantity.getUnitsElement().getValueAsString());
308                if (getMissing() != null) {
309                        b.append("missing", getMissing());
310                }
311                return b.toString();
312        }
313
314}