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 javax.money.CurrencyUnit; 019import javax.money.MonetaryAmount; 020import javax.money.MonetaryContext; 021import javax.money.MonetaryException; 022import java.math.BigDecimal; 023import java.math.MathContext; 024import java.math.RoundingMode; 025import java.util.Objects; 026 027/** 028 * Platform RI: This utility class simplifies implementing {@link MonetaryAmount}, 029 * by providing the common functionality. The different explicitly typed methods 030 * are all reduced to methods using {@link BigDecimal} as input, hereby 031 * performing any conversion to {@link BigDecimal} as needed. Obviosly this 032 * takes some time, so implementors that want to avoid this overhead should 033 * implement {@link MonetaryAmount} directly. 034 * 035 * @author Anatole Tresch 036 */ 037public final class MoneyUtils{ 038 039 040 private MoneyUtils(){ 041 } 042 043 044 // Supporting methods 045 046 /** 047 * Creates a {@link BigDecimal} from the given {@link Number} doing the 048 * valid conversion depending the type given. 049 * 050 * @param num the number type 051 * @return the corresponding {@link BigDecimal} 052 */ 053 public static BigDecimal getBigDecimal(long num){ 054 return BigDecimal.valueOf(num); 055 } 056 057 /** 058 * Creates a {@link BigDecimal} from the given {@link Number} doing the 059 * valid conversion depending the type given. 060 * 061 * @param num the number type 062 * @return the corresponding {@link BigDecimal} 063 */ 064 public static BigDecimal getBigDecimal(double num){ 065 return new BigDecimal(String.valueOf(num)); 066 } 067 068 /** 069 * Creates a {@link BigDecimal} from the given {@link Number} doing the 070 * valid conversion depending the type given. 071 * 072 * @param num the number type 073 * @return the corresponding {@link BigDecimal} 074 */ 075 public static BigDecimal getBigDecimal(Number num){ 076 return ConvertBigDecimal.of(num); 077 } 078 079 /** 080 * Creates a {@link BigDecimal} from the given {@link Number} doing the 081 * valid conversion depending the type given, if a {@link MonetaryContext} 082 * is given, it is applied to the number returned. 083 * 084 * @param num the number type 085 * @return the corresponding {@link BigDecimal} 086 */ 087 public static BigDecimal getBigDecimal(Number num, MonetaryContext moneyContext){ 088 BigDecimal bd = getBigDecimal(num); 089 if(Objects.nonNull(moneyContext)){ 090 return new BigDecimal(bd.toString(), getMathContext(moneyContext, RoundingMode.HALF_EVEN)); 091 } 092 return bd; 093 } 094 095 /** 096 * Evaluates the {@link MathContext} from the given {@link MonetaryContext}. 097 * 098 * @param monetaryContext the {@link MonetaryContext} 099 * @param defaultMode the default {@link RoundingMode}, to be used if no one is set 100 * in {@link MonetaryContext}. 101 * @return the corresponding {@link MathContext} 102 */ 103 public static MathContext getMathContext(MonetaryContext monetaryContext, RoundingMode defaultMode){ 104 MathContext ctx = monetaryContext.get(MathContext.class); 105 if(Objects.nonNull(ctx)){ 106 return ctx; 107 } 108 if(Objects.nonNull(defaultMode)){ 109 return new MathContext(monetaryContext.getPrecision(), 110 monetaryContext.get(RoundingMode.class, defaultMode) 111 ); 112 } 113 return new MathContext(monetaryContext.getPrecision(), 114 monetaryContext.get(RoundingMode.class, RoundingMode.HALF_EVEN) 115 ); 116 } 117 118 /** 119 * Method to check if a currency is compatible with this amount instance. 120 * 121 * @param amount The monetary amount to be compared to, never null. 122 * @param currencyUnit the currency unit to compare, never null. 123 * @throws MonetaryException If the amount is null, or the amount's {@link CurrencyUnit} is not 124 * compatible, meaning has a different value of 125 * {@link CurrencyUnit#getCurrencyCode()}). 126 */ 127 public static void checkAmountParameter(MonetaryAmount amount, CurrencyUnit currencyUnit){ 128 Objects.requireNonNull(amount, "Amount must not be null."); 129 final CurrencyUnit amountCurrency = amount.getCurrency(); 130 if(!(currencyUnit.getCurrencyCode().equals(amountCurrency.getCurrencyCode()))){ 131 throw new MonetaryException("Currency mismatch: " + currencyUnit + '/' + amountCurrency); 132 } 133 } 134 135 /** 136 * Internal method to check for correct number parameter. 137 * 138 * @param number the number to be checked. 139 * @throws IllegalArgumentException If the number is null 140 */ 141 public static void checkNumberParameter(Number number){ 142 Objects.requireNonNull(number, "Number is required."); 143 } 144 145}