javax.money.Monetary Maven / Gradle / Ivy
Show all versions of money-api-bp Show documentation
/*
* CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE
* CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT.
* PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY
* DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE
* AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE"
* BUTTON AT THE BOTTOM OF THIS PAGE.
*
* Specification: JSR-354 Money and Currency API ("Specification")
*
* Copyright (c) 2012-2013, Credit Suisse All rights reserved.
*/
package javax.money;
import javax.money.spi.Bootstrap;
import javax.money.spi.CurrencyProviderSpi;
import javax.money.spi.MonetaryAmountsSingletonQuerySpi;
import javax.money.spi.MonetaryAmountsSingletonSpi;
import javax.money.spi.MonetaryCurrenciesSingletonSpi;
import javax.money.spi.MonetaryRoundingsSingletonSpi;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Factory singleton for {@link CurrencyUnit} instances as provided by the
* different registered {@link CurrencyProviderSpi} instances.
*
* This class is thread safe.
*
* @author Anatole Tresch
* @version 0.8
*/
public final class Monetary {
/**
* The used {@link javax.money.spi.MonetaryCurrenciesSingletonSpi} instance.
*/
private static final MonetaryCurrenciesSingletonSpi monetaryCurrenciesSpi = loadMonetaryCurrenciesSingletonSpi();
/**
* The used {@link javax.money.spi.MonetaryAmountsSingletonSpi} instance.
*/
private static final MonetaryAmountsSingletonSpi monetaryAmountsSingletonSpi = loadMonetaryAmountsSingletonSpi();
/**
* The used {@link javax.money.spi.MonetaryAmountsSingletonSpi} instance.
*/
private static final MonetaryAmountsSingletonQuerySpi monetaryAmountsSingletonQuerySpi =
loadMonetaryAmountsSingletonQuerySpi();
/**
* The used {@link javax.money.spi.MonetaryCurrenciesSingletonSpi} instance.
*/
private static final MonetaryRoundingsSingletonSpi monetaryRoundingsSpi = loadMonetaryRoundingsSingletonSpi();
/**
* Required for deserialization only.
*/
private Monetary() {
}
/**
* Loads the SPI backing bean.
*
* @return the {@link MonetaryCurrenciesSingletonSpi} backing bean to be used.
*/
private static MonetaryCurrenciesSingletonSpi loadMonetaryCurrenciesSingletonSpi() {
try {
MonetaryCurrenciesSingletonSpi spi = Bootstrap
.getService(MonetaryCurrenciesSingletonSpi.class);
if(spi==null) {
spi = new DefaultMonetaryCurrenciesSingletonSpi();
}
return spi;
} catch (Exception e) {
Logger.getLogger(Monetary.class.getName())
.log(Level.INFO, "Failed to load MonetaryCurrenciesSingletonSpi, using default.", e);
return new DefaultMonetaryCurrenciesSingletonSpi();
}
}
/**
* Loads the SPI backing bean.
*
* @return the MonetaryAmountsSingletonSpi bean from the bootstrapping logic.
*/
private static MonetaryAmountsSingletonSpi loadMonetaryAmountsSingletonSpi() {
try {
return Bootstrap.getService(MonetaryAmountsSingletonSpi.class);
} catch (Exception e) {
Logger.getLogger(Monetary.class.getName())
.log(Level.SEVERE, "Failed to load MonetaryAmountsSingletonSpi.", e);
return null;
}
}
/**
* Loads the SPI backing bean.
*
* @return the MonetaryAmountsSingletonQuerySpi bean from the bootstrapping logic.
*/
private static MonetaryAmountsSingletonQuerySpi loadMonetaryAmountsSingletonQuerySpi() {
try {
return Bootstrap.getService(MonetaryAmountsSingletonQuerySpi.class);
} catch (Exception e) {
Logger.getLogger(Monetary.class.getName()).log(Level.SEVERE, "Failed to load " +
"MonetaryAmountsSingletonQuerySpi, " +
"query functionality will not be " +
"available.", e);
return null;
}
}
/**
* Loads the SPI backing bean.
*
* @return an instance of MonetaryRoundingsSingletonSpi.
*/
private static MonetaryRoundingsSingletonSpi loadMonetaryRoundingsSingletonSpi() {
try {
MonetaryRoundingsSingletonSpi spi = Bootstrap
.getService(MonetaryRoundingsSingletonSpi.class);
if(spi==null) {
spi = new DefaultMonetaryRoundingsSingletonSpi();
}
return spi;
} catch (Exception e) {
Logger.getLogger(Monetary.class.getName())
.log(Level.SEVERE, "Failed to load MonetaryCurrenciesSingletonSpi, using default.", e);
return new DefaultMonetaryRoundingsSingletonSpi();
}
}
/**
* Access a new instance based on the currency code. Currencies are
* available as provided by {@link CurrencyProviderSpi} instances registered
* with the {@link javax.money.spi.Bootstrap}.
*
* @param currencyCode the ISO currency code, not {@code null}.
* @param providers the (optional) specification of providers to consider.
* @return the corresponding {@link CurrencyUnit} instance.
* @throws UnknownCurrencyException if no such currency exists.
*/
public static CurrencyUnit getCurrency(String currencyCode, String... providers) {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getCurrency(currencyCode, providers);
}
/**
* Access a new instance based on the {@link java.util.Locale}. Currencies are
* available as provided by {@link CurrencyProviderSpi} instances registered
* with the {@link javax.money.spi.Bootstrap}.
*
* @param locale the target {@link java.util.Locale}, typically representing an ISO
* country, not {@code null}.
* @param providers the (optional) specification of providers to consider.
* @return the corresponding {@link CurrencyUnit} instance.
* @throws UnknownCurrencyException if no such currency exists.
*/
public static CurrencyUnit getCurrency(Locale locale, String... providers) {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getCurrency(locale, providers);
}
/**
* Access a new instance based on the {@link java.util.Locale}. Currencies are
* available as provided by {@link CurrencyProviderSpi} instances registered
* with the {@link javax.money.spi.Bootstrap}.
*
* @param locale the target {@link java.util.Locale}, typically representing an ISO
* country, not {@code null}.
* @param providers the (optional) specification of providers to consider.
* @return the corresponding {@link CurrencyUnit} instance.
* @throws UnknownCurrencyException if no such currency exists.
*/
public static Set getCurrencies(Locale locale, String... providers) {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getCurrencies(locale, providers);
}
/**
* Allows to check if a {@link CurrencyUnit} instance is defined, i.e.
* accessible from {@link Monetary#getCurrency(String, String...)}.
*
* @param code the currency code, not {@code null}.
* @param providers the (optional) specification of providers to consider.
* @return {@code true} if {@link Monetary#getCurrency(String, String...)}
* would return a result for the given code.
*/
public static boolean isCurrencyAvailable(String code, String... providers) {
if(monetaryCurrenciesSpi==null){
throw new IllegalStateException("No Monetary Spi loaded.");
}
return monetaryCurrenciesSpi.isCurrencyAvailable(code, providers);
}
/**
* Allows to check if a {@link CurrencyUnit} instance is
* defined, i.e. accessible from {@link #getCurrency(String, String...)}.
*
* @param locale the target {@link java.util.Locale}, not {@code null}.
* @param providers the (optional) specification of providers to consider.
* @return {@code true} if {@link #getCurrencies(java.util.Locale, String...)} would return a
* result containing a currency with the given code.
*/
public static boolean isCurrencyAvailable(Locale locale, String... providers) {
if(monetaryCurrenciesSpi==null){
throw new IllegalStateException("No Monetary Spi loaded.");
}
return monetaryCurrenciesSpi.isCurrencyAvailable(locale, providers);
}
/**
* Access all currencies known.
*
* @param providers the (optional) specification of providers to consider.
* @return the list of known currencies, never null.
*/
public static Collection getCurrencies(String... providers) {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getCurrencies(providers);
}
/**
* Query all currencies matching the given query.
*
* @param query The {@link CurrencyQuery}, not null.
* @return the list of known currencies, never null.
*/
public static CurrencyUnit getCurrency(CurrencyQuery query) {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getCurrency(query);
}
/**
* Query all currencies matching the given query.
*
* @param query The {@link CurrencyQuery}, not null.
* @return the list of known currencies, never null.
*/
public static Collection getCurrencies(CurrencyQuery query) {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getCurrencies(query);
}
/**
* Query all currencies matching the given query.
*
* @return the list of known currencies, never null.
*/
public static Set getCurrencyProviderNames() {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getProviderNames();
}
/**
* Query the list and ordering of provider names modelling the default provider chain to be used, if no provider
* chain was explicitly set..
*
* @return the orderend list provider names, modelling the default provider chain used, never null.
*/
public static List getDefaultCurrencyProviderChain() {
if(monetaryCurrenciesSpi==null) {
throw new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.");
}
return monetaryCurrenciesSpi.getDefaultProviderChain();
}
/**
* Access an {@link MonetaryAmountFactory} for the given {@link MonetaryAmount} implementation
* type.
*
* @param amountType {@link MonetaryAmount} implementation type, nor {@code null}.
* @return the corresponding {@link MonetaryAmountFactory}, never {@code null}.
* @throws MonetaryException if no {@link MonetaryAmountFactory} targeting the given {@link MonetaryAmount}
* implementation class is registered.
*/
public static MonetaryAmountFactory getAmountFactory(Class amountType) {
if(monetaryAmountsSingletonQuerySpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonQuerySpi loaded, query functionality is not available.");
}
MonetaryAmountFactory factory = monetaryAmountsSingletonSpi.getAmountFactory(amountType);
if(factory==null){
throw new MonetaryException("No AmountFactory available for type: " + amountType.getName());
}
return factory;
}
/**
* Access the default {@link MonetaryAmountFactory} as defined by
* {@link javax.money.spi.MonetaryAmountsSingletonSpi#getDefaultAmountFactory()}.
*
* @return the {@link MonetaryAmountFactory} corresponding to default amount type,
* never {@code null}.
* @throws MonetaryException if no {@link MonetaryAmountFactory} targeting the default amount type
* implementation class is registered.
*/
public static MonetaryAmountFactory getDefaultAmountFactory() {
if(monetaryAmountsSingletonSpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonSpi loaded, query functionality is not available.");
}
return monetaryAmountsSingletonSpi.getDefaultAmountFactory();
}
/**
* Access all currently available {@link MonetaryAmount} implementation classes that are
* accessible from this {@link MonetaryAmount} singleton.
*
* @return all currently available {@link MonetaryAmount} implementation classes that have
* corresponding {@link MonetaryAmountFactory} instances provided, never {@code null}
*/
public static Collection> getAmountFactories() {
if(monetaryAmountsSingletonSpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonSpi loaded, query functionality is not available.");
}
return monetaryAmountsSingletonSpi.getAmountFactories();
}
/**
* Access all currently available {@link MonetaryAmount} implementation classes that are
* accessible from this {@link MonetaryAmount} singleton.
*
* @return all currently available {@link MonetaryAmount} implementation classes that have
* corresponding {@link MonetaryAmountFactory} instances provided, never {@code null}
*/
public static Collection> getAmountTypes() {
if(monetaryAmountsSingletonSpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonSpi loaded, query functionality is not available.");
}
return monetaryAmountsSingletonSpi.getAmountTypes();
}
/**
* Access the default {@link MonetaryAmount} implementation class that is
* accessible from this {@link MonetaryAmount} singleton.
*
* @return all current default {@link MonetaryAmount} implementation class, never {@code null}
*/
public static Class getDefaultAmountType() {
if(monetaryAmountsSingletonSpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonSpi loaded, query functionality is not available.");
}
return monetaryAmountsSingletonSpi.getDefaultAmountType();
}
/**
* Executes the query and returns the factory found, if there is only one factory.
* If multiple factories match the query, one is selected.
*
* @param query the factory query, not null.
* @return the factory found, or null.
*/
public static MonetaryAmountFactory getAmountFactory(MonetaryAmountFactoryQuery query) {
if(monetaryAmountsSingletonQuerySpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonQuerySpi loaded, query functionality is not available.");
}
return monetaryAmountsSingletonQuerySpi.getAmountFactory(query);
}
/**
* Returns all factory instances that match the query.
*
* @param query the factory query, not null.
* @return the instances found, never null.
*/
public static Collection> getAmountFactories(MonetaryAmountFactoryQuery query) {
if(monetaryAmountsSingletonQuerySpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonQuerySpi loaded, query functionality is not available.");
}
return monetaryAmountsSingletonQuerySpi.getAmountFactories(query);
}
/**
* Allows to check if any of the getXXX methods return non empty/non null results of {@link MonetaryAmountFactory}.
*
* @param query the factory query, not null.
* @return true, if at least one {@link MonetaryAmountFactory} matches the query.
*/
public static boolean isAvailable(MonetaryAmountFactoryQuery query) {
if(monetaryAmountsSingletonQuerySpi==null){
throw new MonetaryException(
"No MonetaryAmountsSingletonQuerySpi loaded, query functionality is not available.");
}
return monetaryAmountsSingletonQuerySpi.isAvailable(query);
}
/**
* Creates a rounding that can be added as {@link MonetaryOperator} to
* chained calculations. The instance will lookup the concrete
* {@link MonetaryOperator} instance from {@link Monetary}
* based on the input {@link MonetaryAmount}'s {@link CurrencyUnit}.
*
* @return the (shared) default rounding instance.
*/
public static MonetaryRounding getDefaultRounding() {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getDefaultRounding();
}
/**
* Creates an {@link MonetaryOperator} for rounding {@link MonetaryAmount}
* instances given a currency.
*
* @param currencyUnit The currency, which determines the required scale. As
* {@link java.math.RoundingMode}, by default, {@link java.math.RoundingMode#HALF_UP}
* is used.
* @param providers the providers and ordering to be used. By default providers and ordering as defined in
* #getDefaultProviders is used.
* @return a new instance {@link MonetaryOperator} implementing the
* rounding, never {@code null}.
*/
public static MonetaryRounding getRounding(CurrencyUnit currencyUnit, String... providers) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getRounding(currencyUnit, providers);
}
/**
* Access an {@link MonetaryOperator} for custom rounding
* {@link MonetaryAmount} instances.
*
* @param roundingName The rounding identifier.
* @param providers the providers and ordering to be used. By default providers and ordering as defined in
* #getDefaultProviders is used.
* @return the corresponding {@link MonetaryOperator} implementing the
* rounding, never {@code null}.
* @throws IllegalArgumentException if no such rounding is registered using a
* {@link javax.money.spi.RoundingProviderSpi} instance.
*/
public static MonetaryRounding getRounding(String roundingName, String... providers) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getRounding(roundingName, providers);
}
/**
* Access a {@link MonetaryRounding} using a possibly complex query.
*
* @param roundingQuery The {@link RoundingQuery} that may contains arbitrary parameters to be
* evaluated.
* @return the corresponding {@link MonetaryRounding}, never {@code null}.
* @throws IllegalArgumentException if no such rounding is registered using a
* {@link javax.money.spi.RoundingProviderSpi} instance.
*/
public static MonetaryRounding getRounding(RoundingQuery roundingQuery) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getRounding(roundingQuery);
}
/**
* Checks if a {@link MonetaryRounding} is available given a roundingId.
*
* @param roundingName The rounding identifier.
* @param providers the providers and ordering to be used. By default providers and ordering as defined in
* #getDefaultProviders is used.
* @return true, if a corresponding {@link MonetaryRounding} is available.
* @throws IllegalArgumentException if no such rounding is registered using a
* {@link javax.money.spi.RoundingProviderSpi} instance.
*/
public static boolean isRoundingAvailable(String roundingName, String... providers) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.isRoundingAvailable(roundingName, providers);
}
/**
* Checks if a {@link MonetaryRounding} is available given a roundingId.
*
* @param currencyUnit The currency, which determines the required scale. As {@link java.math.RoundingMode},
* by default, {@link java.math.RoundingMode#HALF_UP} is used.
* @param providers the providers and ordering to be used. By default providers and ordering as defined in
* #getDefaultProviders is used.
* @return true, if a corresponding {@link MonetaryRounding} is available.
* @throws IllegalArgumentException if no such rounding is registered using a
* {@link javax.money.spi.RoundingProviderSpi} instance.
*/
public static boolean isRoundingAvailable(CurrencyUnit currencyUnit, String... providers) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.isRoundingAvailable(currencyUnit, providers);
}
/**
* Checks if a {@link MonetaryRounding} matching the query is available.
*
* @param roundingQuery The {@link RoundingQuery} that may contains arbitrary parameters to be
* evaluated.
* @return true, if a corresponding {@link MonetaryRounding} is available.
* @throws IllegalArgumentException if no such rounding is registered using a
* {@link javax.money.spi.RoundingProviderSpi} instance.
*/
public static boolean isRoundingAvailable(RoundingQuery roundingQuery) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.isRoundingAvailable(roundingQuery);
}
/**
* Access multiple {@link MonetaryRounding} instances using a possibly complex query
*
* @param roundingQuery The {@link RoundingQuery} that may contains arbitrary parameters to be
* evaluated.
* @return all {@link MonetaryRounding} instances macthing the query, never {@code null}.
*/
public static Collection getRoundings(RoundingQuery roundingQuery) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getRoundings(roundingQuery);
}
/**
* Allows to access the names of the current defined roundings.
*
* @param providers the providers and ordering to be used. By default providers and ordering as defined in
* #getDefaultProviders is used.
* @return the set of custom rounding ids, never {@code null}.
*/
public static Set getRoundingNames(String... providers) {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getRoundingNames(providers);
}
/**
* Allows to access the names of the current registered providers.
*
* @return the set of provider names, never {@code null}.
*/
public static Set getRoundingProviderNames() {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getProviderNames();
}
/**
* Allows to access the default providers chain usef if no provider chain was passed explicitly..
*
* @return the chained list of provider names, never {@code null}.
*/
public static List getDefaultRoundingProviderChain() {
if(monetaryRoundingsSpi==null){
throw new MonetaryException("No MonetaryRoundingsSpi loaded, query functionality is not available.");
}
return monetaryRoundingsSpi.getDefaultProviderChain();
}
}