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