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.BigInteger; 020import java.util.Arrays; 021import java.util.List; 022import java.util.Objects; 023import java.util.Optional; 024import java.util.concurrent.atomic.AtomicInteger; 025import java.util.concurrent.atomic.AtomicLong; 026 027import javax.money.NumberValue; 028 029/** 030 * This enumeration provides general utility functions supporting conversion of number types to BigDecimal. 031 */ 032public enum ConvertBigDecimal { 033 /** Conversion from integral numeric types, short, int, long. */ 034 INTEGER { 035 @Override 036 BigDecimal getDecimal(Number num) { 037 return BigDecimal.valueOf(num.longValue()); 038 } 039 }, 040 /** Conversion for floating point numbers. */ 041 FLUCTUAGE { 042 @Override 043 BigDecimal getDecimal(Number num) { 044 return new BigDecimal(num.toString()); 045 } 046 }, 047 /** Conversion from BigInteger. */ 048 BIGINTEGER { 049 @Override 050 BigDecimal getDecimal(Number num) { 051 return new BigDecimal((BigInteger) num); 052 } 053 }, 054 /** Conversion from NumberValue. */ 055 NUMBERVALUE { 056 @Override 057 BigDecimal getDecimal(Number num) { 058 BigDecimal result = ((NumberValue)num).numberValue(BigDecimal.class); 059 return isScaleZero(result); 060 } 061 }, 062 /** Conversion from BigDecimal. */ 063 BIGDECIMAL { 064 @Override 065 BigDecimal getDecimal(Number num) { 066 BigDecimal result = ((BigDecimal)num); 067 return isScaleZero(result); 068 } 069 }, 070 /** COnversion from BigDecimal, extended. */ 071 BIGDECIMAL_EXTENDS { 072 @Override 073 BigDecimal getDecimal(Number num) { 074 BigDecimal result = ((BigDecimal)num).stripTrailingZeros(); 075 return isScaleZero(result); 076 } 077 }, 078 /** Default conversion based on String, if everything else ffailed. */ 079 DEFAULT { 080 @Override 081 BigDecimal getDecimal(Number num) { 082 BigDecimal result = null; 083 try { 084 result = new BigDecimal(num.toString()); 085 } catch (NumberFormatException ignored) { 086 } 087 result = Optional.ofNullable(result).orElse( 088 BigDecimal.valueOf(num.doubleValue())); 089 return isScaleZero(result); 090 } 091 }; 092 093 094 abstract BigDecimal getDecimal(Number num); 095 096 static BigDecimal of(Number num) { 097 Objects.requireNonNull(num, "Number is required."); 098 return factory(num).getDecimal(num); 099 } 100 101 private static ConvertBigDecimal factory(Number num) { 102 if (INSTEGERS.contains(num.getClass())) { 103 return INTEGER; 104 } 105 if (FLOATINGS.contains(num.getClass())) { 106 return FLUCTUAGE; 107 } 108 if (num instanceof NumberValue) { 109 return NUMBERVALUE; 110 } 111 if (BigDecimal.class.equals(num.getClass())) { 112 return BIGDECIMAL; 113 } 114 if (num instanceof BigInteger) { 115 return BIGINTEGER; 116 } 117 if (num instanceof BigDecimal) { 118 return BIGDECIMAL_EXTENDS; 119 } 120 return DEFAULT; 121 } 122 123 private static List<Class<? extends Number>> INSTEGERS = Arrays.asList( 124 Long.class, Integer.class, Short.class, Byte.class, 125 AtomicLong.class, AtomicInteger.class); 126 127 private static List<Class<? extends Number>> FLOATINGS = Arrays.asList( 128 Float.class, Double.class); 129 130 private static BigDecimal isScaleZero(BigDecimal result) { 131 if (result.signum() == 0) { 132 return BigDecimal.ZERO; 133 } 134 if (result.scale() > 0) { 135 return result.stripTrailingZeros(); 136 } 137 return result; 138 } 139}