001/*
002 * #%L
003 * HAPI FHIR - Core Library
004 * %%
005 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.model.primitive;
021
022import java.math.BigDecimal;
023import java.math.MathContext;
024import java.math.RoundingMode;
025
026import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
027
028import ca.uhn.fhir.model.api.BasePrimitive;
029import ca.uhn.fhir.model.api.annotation.DatatypeDef;
030import ca.uhn.fhir.model.api.annotation.SimpleSetter;
031
032@DatatypeDef(name = "decimal")
033public class DecimalDt extends BasePrimitive<BigDecimal> implements Comparable<DecimalDt>, IBaseDecimalDatatype {
034
035        /**
036         * Constructor
037         */
038        public DecimalDt() {
039                super();
040        }
041
042        /**
043         * Constructor
044         */
045        @SimpleSetter
046        public DecimalDt(@SimpleSetter.Parameter(name = "theValue") BigDecimal theValue) {
047                setValue(theValue);
048        }
049
050        /**
051         * Constructor
052         */
053        @SimpleSetter
054        public DecimalDt(@SimpleSetter.Parameter(name = "theValue") double theValue) {
055                // Use the valueOf here because the constructor gives crazy precision
056                // changes due to the floating point conversion
057                setValue(BigDecimal.valueOf(theValue));
058        }
059
060        /**
061         * Constructor
062         */
063        @SimpleSetter
064        public DecimalDt(@SimpleSetter.Parameter(name = "theValue") long theValue) {
065                setValue(new BigDecimal(theValue));
066        }
067
068        /**
069         * Constructor
070         */
071        public DecimalDt(String theValue) {
072                setValue(new BigDecimal(theValue));
073        }
074
075        @Override
076        public int compareTo(DecimalDt theObj) {
077                if (getValue() == null && theObj.getValue() == null) {
078                        return 0;
079                }
080                if (getValue() != null && (theObj == null || theObj.getValue() == null)) {
081                        return 1;
082                }
083                if (getValue() == null && theObj.getValue() != null) {
084                        return -1;
085                }
086                return getValue().compareTo(theObj.getValue());
087        }
088
089        @Override
090        protected String encode(BigDecimal theValue) {
091                return getValue().toPlainString();
092        }
093
094        /**
095         * Gets the value as an integer, using {@link BigDecimal#intValue()}
096         */
097        public int getValueAsInteger() {
098                return getValue().intValue();
099        }
100
101        public Number getValueAsNumber() {
102                return getValue();
103        }
104
105        @Override
106        protected BigDecimal parse(String theValue) {
107                return new BigDecimal(theValue);
108        }
109
110        /**
111         * Rounds the value to the given prevision
112         * 
113         * @see MathContext#getPrecision()
114         */
115        public void round(int thePrecision) {
116                if (getValue() != null) {
117                        BigDecimal newValue = getValue().round(new MathContext(thePrecision));
118                        setValue(newValue);
119                }
120        }
121
122        /**
123         * Rounds the value to the given prevision
124         * 
125         * @see MathContext#getPrecision()
126         * @see MathContext#getRoundingMode()
127         */
128        public void round(int thePrecision, RoundingMode theRoundingMode) {
129                if (getValue() != null) {
130                        BigDecimal newValue = getValue().round(new MathContext(thePrecision, theRoundingMode));
131                        setValue(newValue);
132                }
133        }
134
135        /**
136         * Sets a new value using an integer
137         */
138        public void setValueAsInteger(int theValue) {
139                setValue(new BigDecimal(theValue));
140        }
141
142}