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