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.internal;
017
018import javax.money.CurrencyUnit;
019import javax.money.MonetaryRounding;
020import javax.money.Monetary;
021import javax.money.RoundingQuery;
022import javax.money.spi.RoundingProviderSpi;
023import java.math.MathContext;
024import java.math.RoundingMode;
025import java.util.*;
026
027/**
028 * Defaulr implementation of a {@link javax.money.spi.RoundingProviderSpi} that creates instances of {@link org
029 * .javamoney.moneta.format.DefaultRounding} that relies on the default fraction units defined by {@link java.util
030 * .Currency#getDefaultFractionDigits()}.
031 */
032public class DefaultRoundingProvider implements RoundingProviderSpi {
033
034    private static final String DEFAULT_ROUNDING_NAME = "default";
035    private Set<String> roundingsNames = new HashSet<>();
036
037    public DefaultRoundingProvider() {
038        roundingsNames.add(DEFAULT_ROUNDING_NAME);
039        roundingsNames = Collections.unmodifiableSet(roundingsNames);
040    }
041
042    @Override
043    public String getProviderName() {
044        return "default";
045    }
046
047    /**
048     * Evaluate the rounding that match the given query.
049     *
050     * @return the (shared) default rounding instances matching, never null.
051     */
052    public MonetaryRounding getRounding(RoundingQuery roundingQuery) {
053        if (roundingQuery.get(GregorianCalendar.class) != null || roundingQuery.get(Calendar.class) != null) {
054            return null;
055        }
056        CurrencyUnit currency = roundingQuery.getCurrency();
057        if (currency != null) {
058            RoundingMode roundingMode = roundingQuery.get(RoundingMode.class);
059            if (roundingMode == null) {
060                roundingMode = RoundingMode.HALF_EVEN;
061            }
062            if (Boolean.TRUE.equals(roundingQuery.getBoolean("cashRounding"))) {
063                if (currency.getCurrencyCode().equals("CHF")) {
064                    return new DefaultCashRounding(currency, RoundingMode.HALF_UP, 5);
065                } else {
066                    return new DefaultCashRounding(currency, 1);
067                }
068            }
069            return new DefaultRounding(currency, roundingMode);
070        }
071        Integer scale = roundingQuery.getScale();
072        if (scale == null) {
073            scale = 2;
074        }
075        MathContext mc = roundingQuery.get(MathContext.class);
076        RoundingMode roundingMode = roundingQuery.get(RoundingMode.class);
077        if (mc != null) {
078            return new DefaultRounding(scale, mc.getRoundingMode());
079        } else if (roundingMode != null) {
080            return new DefaultRounding(scale, roundingMode);
081        } else if (roundingQuery.getRoundingName() != null && DEFAULT_ROUNDING_NAME.equals(roundingQuery.getRoundingName())) {
082            return Monetary.getDefaultRounding();
083        }
084        return null;
085    }
086
087
088    @Override
089    public Set<String> getRoundingNames() {
090        return roundingsNames;
091    }
092
093}