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.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 * This implementation uses a scale and {@link RoundingMode} to does the rounding operations. The implementation will use the <b>scale</b>, in other words, the number of digits to the right of the decimal point 030 * The derived class will implements the {@link RoundedMoney} with this rounding monetary operator 031 * <pre> 032 * {@code 033 * 034 * MonetaryOperator monetaryOperator = ScaleRoundedOperator.of(scale, RoundingMode.HALF_EVEN); 035 * CurrencyUnit real = Monetary.getCurrency("BRL"); 036 * MonetaryAmount money = Money.of(BigDecimal.valueOf(35.34567), real); 037 * MonetaryAmount result = monetaryOperator.apply(money); // BRL 35.3457 038 * 039 * } 040* </pre> 041 * Case the parameter in {@link MonetaryOperator#apply(MonetaryAmount)} be null, the apply will return a {@link NullPointerException} 042 * @author Otavio Santana 043 * @see #ScaleRoundedOperator(int, RoundingMode) 044 * @see RoundedMoney 045 * @see MonetaryOperator 046 * @see BigDecimal#scale() 047 */ 048public final class ScaleRoundedOperator implements MonetaryOperator { 049 050 private final int scale; 051 052 private final RoundingMode roundingMode; 053 054 private ScaleRoundedOperator(int scale, RoundingMode roundingMode) { 055 this.scale = scale; 056 this.roundingMode = roundingMode; 057 } 058 059 /** 060 * Creates the rounded Operator from scale and roundingMode 061 * @param scale the scale to be used 062 * @param roundingMode the rounding mode to be used 063 * @return the {@link MonetaryOperator} using the scale and {@link RoundingMode} used in parameter 064 * @throws NullPointerException when the {@link MathContext} is null 065 * @see RoundingMode 066 */ 067 public static ScaleRoundedOperator of(int scale, RoundingMode roundingMode) { 068 069 Objects.requireNonNull(roundingMode); 070 071 if(RoundingMode.UNNECESSARY.equals(roundingMode)) { 072 throw new IllegalStateException("To create the ScaleRoundedOperator you cannot use the RoundingMode.UNNECESSARY"); 073 } 074 return new ScaleRoundedOperator(scale, roundingMode); 075 } 076 077 @Override 078 public MonetaryAmount apply(MonetaryAmount amount) { 079 RoundedMoney roundedMoney = RoundedMoney.from(Objects.requireNonNull(amount)); 080 BigDecimal numberValue = roundedMoney.getNumber().numberValue(BigDecimal.class); 081 BigDecimal numberRounded = numberValue.setScale(scale, roundingMode); 082 return RoundedMoney.of(numberRounded, roundedMoney.getCurrency(), this); 083 } 084 085 public int getScale() { 086 return scale; 087 } 088 089 public RoundingMode getRoundingMode() { 090 return roundingMode; 091 } 092 093 @Override 094 public String toString() { 095 return ScaleRoundedOperator.class.getName() + '{' + 096 "scale:" + Integer.toString(scale) + ',' + 097 "roundingMode:" + roundingMode + '}'; 098 } 099 100}