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.MonetaryAmount; 023import javax.money.NumberValue; 024 025/** 026 * Default implementation of {@link NumberValue} based on {@link BigDecimal}. 027 * 028 * @author Anatole Tresch 029 * @author Werner Keil 030 */ 031public final class DefaultNumberValue extends NumberValue { 032 033 /** 034 * serialVersionUID. 035 */ 036 private static final long serialVersionUID = 1L; 037 /** The numeric value. */ 038 private final Number number; 039 040 /** 041 * The value 1, with a scale of 0.<br> 042 * Backed by {@link BigDecimal#ONE} 043 * 044 * @since 0.8 045 */ 046 public static final NumberValue ONE = new DefaultNumberValue(BigDecimal.ONE); 047 048 public DefaultNumberValue(Number number) { 049 this.number = Objects.requireNonNull(number, "Number required"); 050 } 051 052 /** 053 * Creates a new instance of {@link NumberValue}, using the given number. 054 * 055 * @param number 056 * The numeric part, not null. 057 * @return A new instance of {@link NumberValue}. 058 */ 059 public static NumberValue of(Number number) { 060 return new DefaultNumberValue(number); 061 } 062 063 /* 064 * (non-Javadoc) 065 * @see javax.money.NumberValue#getNumberType() 066 */ 067 @Override 068 public Class<?> getNumberType() { 069 return this.number.getClass(); 070 } 071 072 /* 073 * (non-Javadoc) 074 * @see javax.money.NumberValue#getPrecision() 075 */ 076 @Override 077 public int getPrecision() { 078 return numberValue(BigDecimal.class).precision(); 079 } 080 081 /* 082 * (non-Javadoc) 083 * @see javax.money.NumberValue#getScale() 084 */ 085 @Override 086 public int getScale() { 087 return getBigDecimal(number).scale(); 088 } 089 090 /* 091 * (non-Javadoc) 092 * @see javax.money.NumberValue#getIntValue() 093 */ 094 @Override 095 public int intValue() { 096 return this.number.intValue(); 097 } 098 099 /* 100 * (non-Javadoc) 101 * @see javax.money.NumberValue#getIntValueExact() 102 */ 103 @Override 104 public int intValueExact() { 105 return getBigDecimal(number).intValueExact(); 106 } 107 108 /* 109 * (non-Javadoc) 110 * @see javax.money.NumberValue#getLongValue() 111 */ 112 @Override 113 public long longValue() { 114 return this.number.longValue(); 115 } 116 117 /* 118 * (non-Javadoc) 119 * @see javax.money.NumberValue#getLongValueExact() 120 */ 121 @Override 122 public long longValueExact() { 123 return getBigDecimal(number).longValueExact(); 124 } 125 126 /* 127 * (non-Javadoc) 128 * @see javax.money.NumberValue#getFloatValue() 129 */ 130 @Override 131 public float floatValue() { 132 return this.number.floatValue(); 133 } 134 135 /* 136 * (non-Javadoc) 137 * @see javax.money.NumberValue#getDoubleValue() 138 */ 139 @Override 140 public double doubleValue() { 141 return this.number.doubleValue(); 142 } 143 144 /* 145 * (non-Javadoc) 146 * @see javax.money.NumberValue#getDoubleValueExact() 147 */ 148 @Override 149 public double doubleValueExact() { 150 double d = this.number.doubleValue(); 151 if (d == Double.NEGATIVE_INFINITY || d == Double.POSITIVE_INFINITY) { 152 throw new ArithmeticException("Unable to convert to double: " 153 + this.number); 154 } 155 return d; 156 } 157 158 /* 159 * (non-Javadoc) 160 * @see javax.money.NumberValue#getAmountFractionNumerator() 161 */ 162 @Override 163 public long getAmountFractionNumerator(){ 164 BigDecimal bd = getBigDecimal(number).remainder(BigDecimal.ONE); 165 return bd.movePointRight(getScale()).longValueExact(); 166 } 167 168 /* 169 * (non-Javadoc) 170 * @see javax.money.NumberValue#getAmountFractionDenominator() 171 */ 172 @Override 173 public long getAmountFractionDenominator(){ 174 return BigDecimal.valueOf(10).pow(getScale()).longValueExact(); 175 } 176 177 /* 178 * (non-Javadoc) 179 * @see javax.money.NumberValue#getNumberValue(java.lang.Class) 180 */ 181 @Override 182 public <T extends Number> T numberValue(Class<T> numberType) { 183 return ConvertNumberValue.of(numberType, number); 184 } 185 186 /* 187 * (non-Javadoc) 188 * @see javax.money.NumberValue#round(java.math.MathContext) 189 */ 190 @Override 191 public NumberValue round(MathContext mathContext) { 192 if (this.number instanceof BigDecimal) { 193 return new DefaultNumberValue(((BigDecimal) this.number).round(mathContext)); 194 } 195 return new DefaultNumberValue(new BigDecimal(this.number.toString()).round(mathContext)); 196 } 197 198 /* 199 * (non-Javadoc) 200 * @see javax.money.NumberValue#numberValueExact(java.lang.Class) 201 */ 202 @Override 203 public <T extends Number> T numberValueExact(Class<T> numberType) { 204 return ConvertNumberValue.ofExact(numberType, number); 205 } 206 207 /* 208 * (non-Javadoc) 209 * @see java.lang.Object#toString() 210 */ 211 @Override 212 public String toString() { 213 return String.valueOf(number); 214 } 215 216 /** 217 * Creates a {@link BigDecimal} from the given {@link Number} doing the valid conversion 218 * depending the type given. 219 * 220 * @param num 221 * the number type 222 * @return the corresponding {@link BigDecimal} 223 */ 224 protected static BigDecimal getBigDecimal(Number num) { 225 return ConvertBigDecimal.of(num); 226 } 227 228}