001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
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.math.BigDecimal;
024import java.util.List;
025
026import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
027import org.apache.commons.lang3.StringUtils;
028import org.apache.commons.lang3.builder.ToStringBuilder;
029import org.apache.commons.lang3.builder.ToStringStyle;
030import org.hl7.fhir.instance.model.api.IPrimitiveType;
031
032import ca.uhn.fhir.context.FhirContext;
033import ca.uhn.fhir.model.api.IQueryParameterType;
034import ca.uhn.fhir.model.primitive.DecimalDt;
035import ca.uhn.fhir.model.primitive.UriDt;
036import ca.uhn.fhir.util.CoverageIgnore;
037
038public class QuantityParam extends BaseParamWithPrefix<QuantityParam> implements IQueryParameterType {
039
040        private static final long serialVersionUID = 1L;
041        private BigDecimal myValue;
042        private String mySystem;
043        private String myUnits;
044
045        /**
046         * Constructor
047         */
048        public QuantityParam() {
049                super();
050        }
051
052        /**
053         * Constructor
054         * 
055         * @param thePrefix
056         *           The comparator, or <code>null</code> for an equals comparator
057         * @param theValue
058         *           A quantity value
059         * @param theSystem
060         *           The unit system
061         * @param theUnits
062         *           The unit code
063         */
064        public QuantityParam(ParamPrefixEnum thePrefix, BigDecimal theValue, String theSystem, String theUnits) {
065                setPrefix(thePrefix);
066                setValue(theValue);
067                setSystem(theSystem);
068                setUnits(theUnits);
069        }
070
071        /**
072         * Constructor
073         * 
074         * @param thePrefix
075         *           The comparator, or <code>null</code> for an equals comparator
076         * @param theValue
077         *           A quantity value
078         * @param theSystem
079         *           The unit system
080         * @param theUnits
081         *           The unit code
082         */
083        public QuantityParam(ParamPrefixEnum thePrefix, double theValue, String theSystem, String theUnits) {
084                setPrefix(thePrefix);
085                setValue(theValue);
086                setSystem(theSystem);
087                setUnits(theUnits);
088        }
089
090        /**
091         * Constructor
092         * 
093         * @param thePrefix
094         *           The comparator, or <code>null</code> for an equals comparator
095         * @param theValue
096         *           A quantity value
097         * @param theSystem
098         *           The unit system
099         * @param theUnits
100         *           The unit code
101         */
102        public QuantityParam(ParamPrefixEnum thePrefix, long theValue, String theSystem, String theUnits) {
103                setPrefix(thePrefix);
104                setValue(theValue);
105                setSystem(theSystem);
106                setUnits(theUnits);
107        }
108
109        /**
110         * Constructor
111         * 
112         * @param theQuantity
113         *           A quantity value (with no system or units), such as "100.0" or "gt4"
114         */
115        public QuantityParam(String theQuantity) {
116                setValueAsQueryToken(null, null, null, theQuantity);
117        }
118
119        /**
120         * Constructor
121         * 
122         * @param theQuantity
123         *           A quantity value (with no system or units), such as <code>100</code>
124         */
125        public QuantityParam(long theQuantity) {
126                setValueAsQueryToken(null, null, null, Long.toString(theQuantity));
127        }
128
129        /**
130         * Constructor
131         * 
132         * @param theQuantity
133         *           A quantity value (with no system or units), such as "100.0" or "&lt;=4"
134         * @param theSystem
135         *           The unit system
136         * @param theUnits
137         *           The unit code
138         */
139        public QuantityParam(String theQuantity, String theSystem, String theUnits) {
140                setValueAsQueryToken(null, null, null, theQuantity);
141                setSystem(theSystem);
142                setUnits(theUnits);
143        }
144
145        private void clear() {
146                setPrefix(null);
147                setSystem((String) null);
148                setUnits(null);
149                setValue((BigDecimal) null);
150        }
151
152        @Override
153        String doGetQueryParameterQualifier() {
154                return null;
155        }
156
157        @Override
158        String doGetValueAsQueryToken(FhirContext theContext) {
159                StringBuilder b = new StringBuilder();
160                if (getPrefix() != null) {
161                        b.append(ParameterUtil.escapeWithDefault(getPrefix().getValue()));
162                }
163
164                b.append(ParameterUtil.escapeWithDefault(getValueAsString()));
165                b.append('|');
166                b.append(ParameterUtil.escapeWithDefault(mySystem));
167                b.append('|');
168                b.append(ParameterUtil.escapeWithDefault(myUnits));
169
170                return b.toString();
171        }
172
173        public String getValueAsString() {
174                if (myValue != null) {
175                        return myValue.toPlainString();
176                }
177                return null;
178        }
179
180        @Override
181        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
182                clear();
183
184                if (theValue == null) {
185                        return;
186                }
187                List<String> parts = ParameterUtil.splitParameterString(theValue, '|', true);
188
189                if (parts.size() > 0 && StringUtils.isNotBlank(parts.get(0))) {
190                        String value = super.extractPrefixAndReturnRest(parts.get(0));
191                        setValue(value);
192                }
193                if (parts.size() > 1 && StringUtils.isNotBlank(parts.get(1))) {
194                        setSystem(parts.get(1));
195                }
196                if (parts.size() > 2 && StringUtils.isNotBlank(parts.get(2))) {
197                        setUnits(parts.get(2));
198                }
199
200        }
201
202        /**
203         * Returns the system, or null if none was provided
204         * <p>
205         * Note that prior to HAPI FHIR 1.5, this method returned a {@link UriDt}
206         * </p>
207         * 
208         * @since 1.5
209         */
210        public String getSystem() {
211                return mySystem;
212        }
213
214        /**
215         * @deprecated Use {{@link #getSystem()}} instead
216         */
217        @Deprecated
218        @CoverageIgnore
219        public UriDt getSystemAsUriDt() {
220                return new UriDt(mySystem);
221        }
222
223        public String getUnits() {
224                return myUnits;
225        }
226
227        /**
228         * Returns the quantity/value, or null if none was provided
229         * <p>
230         * Note that prior to HAPI FHIR 1.5, this method returned a {@link DecimalDt}
231         * </p>
232         * 
233         * @since 1.5
234         */
235        public BigDecimal getValue() {
236                return myValue;
237        }
238
239        public QuantityParam setSystem(String theSystem) {
240                mySystem = theSystem;
241                return this;
242        }
243
244        public QuantityParam setSystem(IPrimitiveType<String> theSystem) {
245                mySystem = null;
246                if (theSystem != null) {
247                        mySystem = theSystem.getValue();
248                }
249                return this;
250        }
251
252        public QuantityParam setUnits(String theUnits) {
253                myUnits = theUnits;
254                return this;
255        }
256
257        public QuantityParam setValue(BigDecimal theValue) {
258                myValue = theValue;
259                return this;
260        }
261
262        public QuantityParam setValue(IPrimitiveType<BigDecimal> theValue) {
263                myValue = null;
264                if (theValue != null) {
265                        myValue = theValue.getValue();
266                }
267                return this;
268        }
269
270        public QuantityParam setValue(String theValue) {
271                myValue = null;
272                if (theValue != null) {
273                        myValue = new BigDecimal(theValue);
274                }
275                return this;
276        }
277
278        public QuantityParam setValue(double theValue) {
279                // Use the valueOf here because the constructor gives crazy precision
280                // changes due to the floating point conversion
281                myValue = BigDecimal.valueOf(theValue);
282                return this;
283        }
284
285        public QuantityParam setValue(long theValue) {
286                // Use the valueOf here because the constructor gives crazy precision
287                // changes due to the floating point conversion
288                myValue = BigDecimal.valueOf(theValue);
289                return this;
290        }
291
292        @Override
293        public String toString() {
294                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
295                b.append("prefix", getPrefix());
296                b.append("value", myValue);
297                b.append("system", mySystem);
298                b.append("units", myUnits);
299                if (getMissing() != null) {
300                        b.append("missing", getMissing());
301                }
302                return b.toString();
303        }
304
305    public static QuantityParam toQuantityParam(IQueryParameterType theParam) {
306        if (theParam instanceof BaseQuantityDt) {
307            BaseQuantityDt param = (BaseQuantityDt) theParam;
308            String systemValue = param.getSystemElement().getValueAsString();
309            String unitsValue = param.getUnitsElement().getValueAsString();
310            ParamPrefixEnum cmpValue = ParamPrefixEnum.forValue(param.getComparatorElement().getValueAsString());
311            BigDecimal valueValue = param.getValueElement().getValue();
312            return new QuantityParam()
313                .setSystem(systemValue)
314                .setUnits(unitsValue)
315                .setPrefix(cmpValue)
316                .setValue(valueValue);
317        } else if (theParam instanceof QuantityParam) {
318            return (QuantityParam) theParam;
319        } else {
320            throw new IllegalArgumentException("Invalid quantity type: " + theParam.getClass());
321        }
322    }
323}