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
025import static java.util.Objects.requireNonNull;
026
027/**
028 * <p>This implementation uses a scale and {@link RoundingMode} and precision to does the rounding operations. The implementation will use both the <b>scale</b> and <b>precision</b>, in other words, the number of digits to the right of the decimal point and the number of digits.</p>
029 * <p>The derived class will implements the {@link RoundedMoney} with this rounding monetary operator</p>
030 *  <pre>
031 *   {@code
032 *     int scale = 3;
033 *     int precision = 5;
034 *     MathContext mathContext = new MathContext(precision, RoundingMode.HALF_EVEN);
035 *     MonetaryOperator monetaryOperator = PrecisionScaleRoundedOperator.of(scale, 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.346
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 PrecisionScaleRoundedOperator#of(int, MathContext)}
045 * @see {@link RoundedMoney}
046 * @see {@link MonetaryOperator}
047 * @see {@link BigDecimal#scale()}
048 * @see {@link MathContext}
049 * @see {@link BigDecimal#precision()}
050 * @since 1.0.1
051 * @deprecated Do not use, access is only provided for backward compatibility and will be removed.
052 */
053@Deprecated
054public final class PrecisionScaleRoundedOperator implements MonetaryOperator {
055
056        private final PrecisionContextRoundedOperator mathContextOperator;
057
058        private final ScaleRoundedOperator scaleRoundedOperator;
059
060        private final int scale;
061
062        private final MathContext mathContext;
063
064        private PrecisionScaleRoundedOperator(int scale, MathContext mathContext) {
065                this.scale = scale;
066                this.mathContext = mathContext;
067                this.mathContextOperator = PrecisionContextRoundedOperator.of(mathContext);
068                this.scaleRoundedOperator = ScaleRoundedOperator.of(scale, mathContext.getRoundingMode());
069        }
070
071        /**
072         * Creates the rounded Operator from scale and roundingMode
073         * @param mathContext
074         * @return the {@link MonetaryOperator} using the scale and {@link RoundingMode} used in parameter
075         * @throws NullPointerException when the {@link MathContext} is null
076         * @throws IllegalArgumentException if {@link MathContext#getPrecision()} is lesser than zero
077         * @throws IllegalArgumentException if {@link MathContext#getRoundingMode()} is {@link RoundingMode#UNNECESSARY}
078         * @see {@linkplain RoundingMode}
079         */
080        public static PrecisionScaleRoundedOperator of(int scale, MathContext mathContext) {
081
082                Objects.requireNonNull(mathContext);
083
084                if(RoundingMode.UNNECESSARY.equals(mathContext.getRoundingMode())) {
085                   throw new IllegalArgumentException("To create the ScaleRoundedOperator you cannot use the RoundingMode.UNNECESSARY on MathContext");
086                }
087
088                if(mathContext.getPrecision() <= 0) {
089                        throw new IllegalArgumentException("To create the ScaleRoundedOperator you cannot use the zero precision on MathContext");
090                }
091                return new PrecisionScaleRoundedOperator(scale, mathContext);
092        }
093
094        @Override
095        public MonetaryAmount apply(MonetaryAmount amount) {
096                return scaleRoundedOperator.apply(requireNonNull(amount)).with(mathContextOperator);
097        }
098
099        public int getScale() {
100                return scale;
101        }
102
103        public MathContext getMathContext() {
104                return mathContext;
105        }
106
107        @Override
108        public String toString() {
109                StringBuilder sb = new StringBuilder();
110                sb.append(PrecisionScaleRoundedOperator.class.getName()).append('{')
111                .append("scale:").append(Integer.toString(scale)).append(',')
112                .append("mathContext:").append(mathContext).append('}');
113                return sb.toString();
114        }
115
116}