001/**
002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016package org.javamoney.moneta.spi;
017
018import java.math.BigDecimal;
019import java.math.MathContext;
020import java.util.Objects;
021
022import javax.money.NumberValue;
023
024/**
025 * Default implementation of {@link NumberValue} based on {@link BigDecimal}.
026 * 
027 * @author Anatole Tresch
028 * @author Werner Keil
029 */
030public final class DefaultNumberValue extends NumberValue {
031        
032        /**
033         * serialVersionUID.
034         */
035        private static final long serialVersionUID = 1L;
036        /** The numeric value. */
037        private final Number number;
038
039    /**
040     * The value 1, with a scale of 0.<br>
041     * Backed by {@link BigDecimal#ONE}
042     *
043     * @since  0.8
044     */
045        public static final NumberValue ONE = new DefaultNumberValue(BigDecimal.ONE);
046        
047        public DefaultNumberValue(Number number) {
048        this.number = Objects.requireNonNull(number, "Number required");
049    }
050        
051        /**
052         * Creates a new instance of {@link NumberValue}, using the given number.
053         * 
054         * @param number
055         *            The numeric part, not null.
056         * @return A new instance of {@link NumberValue}.
057         */
058        public static NumberValue of(Number number) {
059                return new DefaultNumberValue(number);
060        }
061
062        /*
063         * (non-Javadoc)
064         * @see javax.money.NumberValue#getNumberType()
065         */
066        @Override
067        public Class<?> getNumberType() {
068                return this.number.getClass();
069        }
070
071        /*
072         * (non-Javadoc)
073         * @see javax.money.NumberValue#getPrecision()
074         */
075        @Override
076        public int getPrecision() {
077                return numberValue(BigDecimal.class).precision();
078        }
079
080        /*
081         * (non-Javadoc)
082         * @see javax.money.NumberValue#getScale()
083         */
084        @Override
085        public int getScale() {
086                return ConvertBigDecimal.of(number).scale();
087        }
088
089        /*
090         * (non-Javadoc)
091         * @see javax.money.NumberValue#getIntValue()
092         */
093        @Override
094        public int intValue() {
095                return this.number.intValue();
096        }
097
098        /*
099         * (non-Javadoc)
100         * @see javax.money.NumberValue#getIntValueExact()
101         */
102        @Override
103        public int intValueExact() {
104                return ConvertBigDecimal.of(number).intValueExact();
105        }
106
107        /*
108         * (non-Javadoc)
109         * @see javax.money.NumberValue#getLongValue()
110         */
111        @Override
112        public long longValue() {
113                return this.number.longValue();
114        }
115
116        /*
117         * (non-Javadoc)
118         * @see javax.money.NumberValue#getLongValueExact()
119         */
120        @Override
121        public long longValueExact() {
122                return ConvertBigDecimal.of(number).longValueExact();
123        }
124
125        /*
126         * (non-Javadoc)
127         * @see javax.money.NumberValue#getFloatValue()
128         */
129        @Override
130        public float floatValue() {
131                return this.number.floatValue();
132        }
133
134        /*
135         * (non-Javadoc)
136         * @see javax.money.NumberValue#getDoubleValue()
137         */
138        @Override
139        public double doubleValue() {
140                return this.number.doubleValue();
141        }
142
143        /*
144         * (non-Javadoc)
145         * @see javax.money.NumberValue#getDoubleValueExact()
146         */
147        @Override
148        public double doubleValueExact() {
149                double d = this.number.doubleValue();
150                if (d == Double.NEGATIVE_INFINITY || d == Double.POSITIVE_INFINITY) {
151                        throw new ArithmeticException("Unable to convert to double: "
152                                        + this.number);
153                }
154                return d;
155        }
156
157    /*
158     * (non-Javadoc)
159         * @see javax.money.NumberValue#getAmountFractionNumerator()
160     */
161    @Override
162    public long getAmountFractionNumerator(){
163        BigDecimal bd = ConvertBigDecimal.of(number).remainder(BigDecimal.ONE);
164        return bd.movePointRight(getScale()).longValueExact();
165    }
166
167    /*
168     * (non-Javadoc)
169         * @see javax.money.NumberValue#getAmountFractionDenominator()
170     */
171    @Override
172    public long getAmountFractionDenominator(){
173        return BigDecimal.valueOf(10).pow(getScale()).longValueExact();
174    }
175
176        /*
177         * (non-Javadoc)
178         * @see javax.money.NumberValue#getNumberValue(java.lang.Class)
179         */
180        @Override
181        public <T extends Number> T numberValue(Class<T> numberType) {
182                return ConvertNumberValue.of(numberType, number);
183        }
184
185    /*
186     * (non-Javadoc)
187         * @see javax.money.NumberValue#round(java.math.MathContext)
188         */
189    @Override
190    public NumberValue round(MathContext mathContext) {
191        if (this.number instanceof BigDecimal) {
192            return new DefaultNumberValue(((BigDecimal) this.number).round(mathContext));
193        }
194        return new DefaultNumberValue(new BigDecimal(this.number.toString()).round(mathContext));
195    }
196
197    /*
198     * (non-Javadoc)
199     * @see javax.money.NumberValue#numberValueExact(java.lang.Class)
200     */
201    @Override
202        public <T extends Number> T numberValueExact(Class<T> numberType) {
203                return ConvertNumberValue.ofExact(numberType, number);
204        }
205
206        /*
207         * (non-Javadoc)
208         * @see java.lang.Object#toString()
209         */
210        @Override
211        public String toString() {
212                return String.valueOf(number);
213        }
214
215}