001/*
002 * CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE
003 * CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT.
004 * PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY
005 * DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE
006 * AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE"
007 * BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency
008 * API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights
009 * reserved.
010 */
011package org.javamoney.moneta.spi.base;
012
013import javax.money.CurrencyUnit;
014import javax.money.MonetaryException;
015import javax.money.MonetaryRounding;
016import javax.money.RoundingQuery;
017import javax.money.RoundingQueryBuilder;
018import javax.money.spi.MonetaryRoundingsSingletonSpi;
019import java.util.Collection;
020
021/**
022 * This class models the accessor for rounding instances, modeled as
023 * {@link javax.money.MonetaryOperator}.
024 * <p>
025 * This class is thread-safe.
026 *
027 * @author Anatole Tresch
028 * @author Werner Keil
029 */
030public abstract class BaseMonetaryRoundingsSingletonSpi implements MonetaryRoundingsSingletonSpi {
031
032    /**
033     * Access a {@link javax.money.MonetaryRounding} for rounding {@link javax.money.MonetaryAmount}
034     * instances given a currency.
035     *
036     * @param currencyUnit The currency, which determines the required precision. As
037     *                     {@link java.math.RoundingMode}, by default, {@link java.math.RoundingMode#HALF_UP}
038     *                     is sued.
039     * @param providers    the optional provider list and ordering to be used
040     * @return a new instance {@link javax.money.MonetaryOperator} implementing the
041     * rounding, never {@code null}.
042     * @throws javax.money.MonetaryException if no such rounding could be provided.
043     */
044    public MonetaryRounding getRounding(CurrencyUnit currencyUnit, String... providers) {
045        MonetaryRounding op =
046                getRounding(RoundingQueryBuilder.of().setProviderNames(providers).setCurrency(currencyUnit).build());
047        if(op==null) {
048            throw new MonetaryException(
049                    "No rounding provided for CurrencyUnit: " + currencyUnit.getCurrencyCode());
050        }
051        return op;
052    }
053
054
055    /**
056     * Access a {@link javax.money.MonetaryRounding} using the rounding name.
057     *
058     * @param roundingName The rounding name, not null.
059     * @param providers    the optional provider list and ordering to be used
060     * @return the corresponding {@link javax.money.MonetaryOperator} implementing the
061     * rounding, never {@code null}.
062     * @throws IllegalArgumentException if no such rounding is registered using a
063     *                                  {@link javax.money.spi.RoundingProviderSpi} instance.
064     */
065    public MonetaryRounding getRounding(String roundingName, String... providers) {
066        MonetaryRounding op =
067                getRounding(RoundingQueryBuilder.of().setProviderNames(providers).setRoundingName(roundingName).build());
068        if(op==null) {
069            throw new MonetaryException("No rounding provided with rounding name: " + roundingName);
070        }
071        return op;
072    }
073
074
075    /**
076     * Query a specific rounding with the given query. If multiple roundings match the query the first one is
077     * selected, since the query allows to determine the providers and their ordering by setting {@link
078     * javax.money.RoundingQuery#getProviderNames()}.
079     *
080     * @param query the rounding query, not null.
081     * @return the rounding found, or null, if no rounding matches the query.
082     */
083    public MonetaryRounding getRounding(RoundingQuery query) {
084        Collection<MonetaryRounding> roundings = getRoundings(query);
085        if (roundings.isEmpty()) {
086            return null;
087        }
088        return roundings.iterator().next();
089    }
090
091    /**
092     * Checks if any {@link javax.money.MonetaryRounding} is matching the given query.
093     *
094     * @param query the rounding query, not null.
095     * @return true, if at least one rounding matches the query.
096     */
097    public boolean isRoundingAvailable(RoundingQuery query) {
098        return !getRoundings(query).isEmpty();
099    }
100
101    /**
102     * Checks if a {@link javax.money.MonetaryRounding} is available given a roundingId.
103     *
104     * @param roundingId The rounding identifier.
105     * @param providers  the providers and ordering to be used. By default providers and ordering as defined in
106     *                   #getDefaultProviders is used.
107     * @return true, if a corresponding {@link javax.money.MonetaryRounding} is available.
108     * @throws IllegalArgumentException if no such rounding is registered using a
109     *                                  {@link javax.money.spi.RoundingProviderSpi} instance.
110     */
111    public boolean isRoundingAvailable(String roundingId, String... providers) {
112        return isRoundingAvailable(
113                RoundingQueryBuilder.of().setProviderNames(providers).setRoundingName(roundingId).build());
114    }
115
116    /**
117     * Checks if a {@link javax.money.MonetaryRounding} is available given a {@link javax.money.CurrencyUnit}.
118     *
119     * @param currencyUnit The currency, which determines the required precision. As {@link java.math.RoundingMode},
120     *                     by default, {@link java.math.RoundingMode#HALF_UP} is used.
121     * @param providers    the providers and ordering to be used. By default providers and ordering as defined in
122     *                     #getDefaultProviders is used.
123     * @return true, if a corresponding {@link javax.money.MonetaryRounding} is available.
124     * @throws IllegalArgumentException if no such rounding is registered using a
125     *                                  {@link javax.money.spi.RoundingProviderSpi} instance.
126     */
127    public boolean isRoundingAvailable(CurrencyUnit currencyUnit, String... providers) {
128        return isRoundingAvailable(RoundingQueryBuilder.of().setProviderNames(providers).setCurrency(currencyUnit).build());
129    }
130}