001/** 002 * Copyright (c) 2012, 2015, 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.function; 017 018import java.math.BigDecimal; 019import java.math.MathContext; 020import java.math.RoundingMode; 021import java.util.Objects; 022 023import javax.money.MonetaryAmount; 024import javax.money.MonetaryOperator; 025 026import org.javamoney.moneta.RoundedMoney; 027 028/** 029 * <p>This implementation uses a {@link MathContext} to does the rounding operations. The implementation will use the <b>precision</b>, in other words, the total number of digits in a number</p> 030 * <p>The derived class will implements the {@link RoundedMoney} with this rounding monetary operator</p> 031 * <pre> 032 * {@code 033 * 034 * MathContext mathContext = new MathContext(4, RoundingMode.HALF_EVEN); 035 * MonetaryOperator monetaryOperator = PrecisionContextRoundedOperator.of(mathContext); 036 * CurrencyUnit real = Monetary.getCurrency("BRL"); 037 * MonetaryAmount money = Money.of(BigDecimal.valueOf(35.34567), real); 038 * MonetaryAmount result = monetaryOperator.apply(money); // BRL 35.35 039 * 040 * } 041* </pre> 042* <p>Case the parameter in {@link MonetaryOperator#apply(MonetaryAmount)} be null, the apply will return a {@link NullPointerException}</p> 043 * @author Otavio Santana 044 * @see {@link PrecisionContextRoundedOperator#of(MathContext)} 045 * @see {@link RoundedMoney} 046 * @see {@link MonetaryOperator} 047 * @see {@link BigDecimal#precision()} 048 * @since 1.0.1 049 */ 050public final class PrecisionContextRoundedOperator implements MonetaryOperator { 051 052 private final MathContext mathContext; 053 054 private PrecisionContextRoundedOperator(MathContext mathContext) { 055 this.mathContext = mathContext; 056 } 057 058 /** 059 * Creates the rounded Operator from mathContext 060 * @param mathContext 061 * @return the {@link MonetaryOperator} using the {@link MathContext} used in parameter 062 * @throws NullPointerException when the {@link MathContext} is null 063 * @throws IllegalArgumentException when the {@link MathContext#getPrecision()} is lesser than zero 064 * @throws IllegalArgumentException when the mathContext is {@link MathContext#getRoundingMode()} is {@link RoundingMode#UNNECESSARY} 065 * @see {@linkplain MathContext} 066 */ 067 public static PrecisionContextRoundedOperator of(MathContext mathContext) { 068 069 Objects.requireNonNull(mathContext); 070 071 if(RoundingMode.UNNECESSARY.equals(mathContext.getRoundingMode())) { 072 throw new IllegalArgumentException("To create the MathContextRoundedOperator you cannot use the RoundingMode.UNNECESSARY on MathContext"); 073 } 074 075 if(mathContext.getPrecision() <= 0) { 076 throw new IllegalArgumentException("To create the MathContextRoundedOperator you cannot use the zero precision on MathContext"); 077 } 078 079 return new PrecisionContextRoundedOperator(mathContext); 080 } 081 082 @Override 083 public MonetaryAmount apply(MonetaryAmount amount) { 084 RoundedMoney roundedMoney = RoundedMoney.from(Objects.requireNonNull(amount)); 085 BigDecimal numberValue = roundedMoney.getNumber().numberValue(BigDecimal.class); 086 BigDecimal numberRounded = numberValue.round(mathContext); 087 return RoundedMoney.of(numberRounded, roundedMoney.getCurrency(), this); 088 } 089 090 public MathContext getMathContext() { 091 return mathContext; 092 } 093 094 @Override 095 public String toString() { 096 StringBuilder sb = new StringBuilder(); 097 sb.append(PrecisionContextRoundedOperator.class.getName()).append('{') 098 .append("mathContext:").append(mathContext).append('}'); 099 return sb.toString(); 100 } 101 102}