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.util.Objects;
020
021import javax.money.NumberValue;
022
023/**
024 * Default implementation of {@link NumberValue} based on {@link BigDecimal}.
025 * 
026 * @author Anatole Tresch
027 * @author Werner Keil
028 */
029public final class DefaultNumberValue extends NumberValue {
030        
031        /**
032         * serialVersionUID.
033         */
034        private static final long serialVersionUID = 1L;
035        /** The numeric value. */
036        private final Number number;
037
038    /**
039     * The value 1, with a scale of 0.<br>
040     * Backed by {@link BigDecimal#ONE}
041     *
042     * @since  0.8
043     */
044        public static final NumberValue ONE = new DefaultNumberValue(BigDecimal.ONE);
045        
046        public DefaultNumberValue(Number number) {
047                Objects.requireNonNull(number, "Number required");
048                this.number = number;
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 getBigDecimal(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 getBigDecimal(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 getBigDecimal(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 = getBigDecimal(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#numberValueExact(java.lang.Class)
188         */
189        @Override
190        public <T extends Number> T numberValueExact(Class<T> numberType) {
191                return ConvertNumberValue.ofExact(numberType, number);
192        }
193
194        /*
195         * (non-Javadoc)
196         * @see java.lang.Object#toString()
197         */
198        @Override
199        public String toString() {
200                return String.valueOf(number);
201        }
202
203        /**
204         * Creates a {@link BigDecimal} from the given {@link Number} doing the valid conversion
205         * depending the type given.
206         * 
207         * @param num
208         *            the number type
209         * @return the corresponding {@link BigDecimal}
210         */
211        protected static BigDecimal getBigDecimal(Number num) {
212                return ConvertBigDecimal.of(num);
213        }
214
215}