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. 008 * 009 * Specification: JSR-354 Money and Currency API ("Specification") 010 * 011 * Copyright (c) 2012-2013, Credit Suisse All rights reserved. 012 */ 013package org.javamoney.moneta.spi.base; 014 015import javax.money.CurrencyQuery; 016import javax.money.CurrencyQueryBuilder; 017import javax.money.CurrencyUnit; 018import javax.money.MonetaryException; 019import javax.money.UnknownCurrencyException; 020import javax.money.spi.MonetaryCurrenciesSingletonSpi; 021import java.util.Collection; 022import java.util.Locale; 023import java.util.Objects; 024import java.util.Set; 025 026/** 027 * Factory singleton backing interface for {@link javax.money.Monetary} that provides access to 028 * different registered {@link javax.money.spi.CurrencyProviderSpi} instances. 029 * <p> 030 * Implementations of this interface must be thread safe. 031 * 032 * @author Anatole Tresch 033 * @version 0.8 034 */ 035public abstract class BaseMonetaryCurrenciesSingletonSpi implements MonetaryCurrenciesSingletonSpi{ 036 037 /** 038 * Access a new instance based on the currency code. Currencies are 039 * available as provided by {@link javax.money.spi.CurrencyProviderSpi} instances registered 040 * with the {@link javax.money.spi.Bootstrap}. 041 * 042 * @param currencyCode the ISO currency code, not {@code null}. 043 * @param providers the (optional) specification of providers to consider. If not set (empty) the providers 044 * as defined by #getDefaultRoundingProviderChain() should be used. 045 * @return the corresponding {@link javax.money.CurrencyUnit} instance. 046 * @throws javax.money.UnknownCurrencyException if no such currency exists. 047 */ 048 public CurrencyUnit getCurrency(String currencyCode, String... providers) { 049 Objects.requireNonNull(currencyCode, "Currency Code may not be null"); 050 Collection<CurrencyUnit> found = 051 getCurrencies(CurrencyQueryBuilder.of().setCurrencyCodes(currencyCode).setProviderNames(providers).build()); 052 if (found.isEmpty()) { 053 throw new UnknownCurrencyException(currencyCode); 054 } 055 if (found.size() > 1) { 056 throw new MonetaryException("Ambiguous CurrencyUnit for code: " + currencyCode + ": " + found); 057 } 058 return found.iterator().next(); 059 } 060 061 /** 062 * Access a new instance based on the currency code. Currencies are 063 * available as provided by {@link javax.money.spi.CurrencyProviderSpi} instances registered 064 * with the {@link javax.money.spi.Bootstrap}. 065 * 066 * @param country the ISO currency's country, not {@code null}. 067 * @param providers the (optional) specification of providers to consider. If not set (empty) the providers 068 * as defined by #getDefaultRoundingProviderChain() should be used. 069 * @return the corresponding {@link javax.money.CurrencyUnit} instance. 070 * @throws javax.money.UnknownCurrencyException if no such currency exists. 071 */ 072 public CurrencyUnit getCurrency(Locale country, String... providers) { 073 Collection<CurrencyUnit> found = 074 getCurrencies(CurrencyQueryBuilder.of().setCountries(country).setProviderNames(providers).build()); 075 if (found.isEmpty()) { 076 throw new MonetaryException("No currency unit found for locale: " + country); 077 } 078 if (found.size() > 1) { 079 throw new MonetaryException("Ambiguous CurrencyUnit for locale: " + country + ": " + found); 080 } 081 return found.iterator().next(); 082 } 083 084 /** 085 * Provide access to all currently known currencies. 086 * 087 * @param locale the target {@link java.util.Locale}, typically representing an ISO country, 088 * not {@code null}. 089 * @param providers the (optional) specification of providers to consider. If not set (empty) the providers 090 * as defined by #getDefaultRoundingProviderChain() should be used. 091 * @return a collection of all known currencies, never null. 092 */ 093 public Set<CurrencyUnit> getCurrencies(Locale locale, String... providers) { 094 return getCurrencies(CurrencyQueryBuilder.of().setCountries(locale).setProviderNames(providers).build()); 095 } 096 097 /** 098 * Allows to check if a {@link javax.money.CurrencyUnit} instance is defined, i.e. 099 * accessible from {@link BaseMonetaryCurrenciesSingletonSpi#getCurrency(String, String...)}. 100 * 101 * @param code the currency code, not {@code null}. 102 * @param providers the (optional) specification of providers to consider. If not set (empty) the providers 103 * as defined by #getDefaultRoundingProviderChain() should be used. 104 * @return {@code true} if {@link BaseMonetaryCurrenciesSingletonSpi#getCurrency(String, String...)} 105 * would return a result for the given code. 106 */ 107 public boolean isCurrencyAvailable(String code, String... providers) { 108 return !getCurrencies(CurrencyQueryBuilder.of().setCurrencyCodes(code).setProviderNames(providers).build()) 109 .isEmpty(); 110 } 111 112 /** 113 * Allows to check if a {@link javax.money.CurrencyUnit} instance is 114 * defined, i.e. accessible from {@link #getCurrency(String, String...)}. 115 * 116 * @param locale the target {@link java.util.Locale}, not {@code null}. 117 * @param providers the (optional) specification of providers to consider. If not set (empty) the providers 118 * as defined by #getDefaultRoundingProviderChain() should be used. 119 * @return {@code true} if {@link #getCurrencies(java.util.Locale, String...)} would return a 120 * non empty result for the given code. 121 */ 122 public boolean isCurrencyAvailable(Locale locale, String... providers) { 123 return !getCurrencies(CurrencyQueryBuilder.of().setCountries(locale).setProviderNames(providers).build()).isEmpty(); 124 } 125 126 /** 127 * Provide access to all currently known currencies. 128 * 129 * @param providers the (optional) specification of providers to consider. If not set (empty) the providers 130 * as defined by #getDefaultRoundingProviderChain() should be used. 131 * @return a collection of all known currencies, never null. 132 */ 133 public Set<CurrencyUnit> getCurrencies(String... providers) { 134 return getCurrencies(CurrencyQueryBuilder.of().setProviderNames(providers).build()); 135 } 136 137 /** 138 * Access a single currency by query. 139 * 140 * @param query The currency query, not null. 141 * @return the {@link javax.money.CurrencyUnit} found, never null. 142 * @throws javax.money.MonetaryException if multiple currencies match the query. 143 */ 144 public CurrencyUnit getCurrency(CurrencyQuery query) { 145 Set<CurrencyUnit> currencies = getCurrencies(query); 146 if (currencies.isEmpty()) { 147 return null; 148 } 149 if (currencies.size() == 1) { 150 return currencies.iterator().next(); 151 } 152 throw new MonetaryException("Ambiguous request for CurrencyUnit: " + query + ", found: " + currencies); 153 } 154}