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