Skip to content
This repository was archived by the owner on Jun 27, 2021. It is now read-only.

Commit b4c525e

Browse files
committed
JAVAMONEY-97: Merged singletons into single Monetary singleton.
1 parent 13f06e2 commit b4c525e

28 files changed

+974
-990
lines changed

UserGuide.adoc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ Since a corresponding +MonetaryAmountFactory+ is registered, a new instance can
146146
[source,java]
147147
.Example Usage of MonetaryAmountFactory
148148
-------------------------------------------------------------------
149-
MonetaryAmountFactory<Money> fact = MonetaryAmounts.getAmountFactory(Money.class);
149+
MonetaryAmountFactory<Money> fact = Monetary.getAmountFactory(Money.class);
150150
Money m = fact.withCurrency("USD").with(200.50).create();
151151
-------------------------------------------------------------------
152152

@@ -156,7 +156,7 @@ default amount factory, which effective type instance is returned):
156156
[source,java]
157157
.Example Usage MonetaryAmountFactory
158158
-------------------------------------------------------------------
159-
MonetaryAmount amt = MonetaryAmounts.getDefaultAmountFactory()
159+
MonetaryAmount amt = Monetary.getDefaultAmountFactory()
160160
.withCurrency("USD").with(200.50).create();
161161
-------------------------------------------------------------------
162162

@@ -202,9 +202,9 @@ mentioned also external functionality can be chained, e.g. using instances of +M
202202
.Example Function Chaining footnote:[+MonetaryFunctions+ is not part of the JSR, its just for illustration purposes.]
203203
-------------------------------------------------------------------
204204
MonetaryAmount amt = ...;
205-
amt = amt.multiply(2.12345).with(MonetaryRoundings.getDefaultRounding())
205+
amt = amt.multiply(2.12345).with(Monetary.getDefaultRounding())
206206
.with(MonetaryFunctions.minimal(100)).
207-
.multiply(2.12345).with(MonetaryRoundings.getDefaultRounding())
207+
.multiply(2.12345).with(Monetary.getDefaultRounding())
208208
.with(MonetaryFunctions.percent(23));
209209
-------------------------------------------------------------------
210210

@@ -217,7 +217,7 @@ When accessing +MonetaryAmountFactory+ instances it is possible to configure the
217217
[source,java]
218218
.Example Configuring a +MonetaryAmountFactory+, using the RI class +Money+ as example.
219219
-------------------------------------------------------------------
220-
MonetaryAmountFactory<Money> fact = MonetaryAmounts.getAmountFactory(
220+
MonetaryAmountFactory<Money> fact = Monetary.getAmountFactory(
221221
MonetaryAmountFactoryQueryBuilder.of(Money.class)
222222
.set(new MathContext(250, RoundingMode.HALF_DOWN)).build()
223223
);
@@ -269,7 +269,7 @@ just replacing +FastMoney+ with +Money+:
269269
[source,java]
270270
.Usage Example - FastMoney
271271
-------------------------------------------------------------------
272-
MonetaryAmountFactory<FastMoney> fact = MonetaryAmounts.getAmountFactory(FastMoney.class);
272+
MonetaryAmountFactory<FastMoney> fact = Monetary.getAmountFactory(FastMoney.class);
273273
// Creates an instance of Money with the given MathContext
274274
MonetaryAmount m1 = fact.setCurrency("CHF").setNumber(250.34).create();
275275
FastMoney m2 = fact.setCurrency("CHF").setNumber(250.34).create();
@@ -326,7 +326,7 @@ public class Total implements MonetaryOperator{
326326
}
327327
328328
public <T extends MonetaryAmount> T getTotal(Class<T> amountType){
329-
return MonetaryAmounts.getAmountFactory(amountType).with(total).create();
329+
return Monetary.getAmountFactory(amountType).with(total).create();
330330
}
331331
332332
}
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/*
2+
* CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE
3+
* CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT.
4+
* PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY
5+
* DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE
6+
* AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE"
7+
* BUTTON AT THE BOTTOM OF THIS PAGE.
8+
*
9+
* Specification: JSR-354 Money and Currency API ("Specification")
10+
*
11+
* Copyright (c) 2012-2013, Credit Suisse All rights reserved.
12+
*/
13+
package javax.money;
14+
15+
import javax.money.spi.Bootstrap;
16+
import javax.money.spi.CurrencyProviderSpi;
17+
import javax.money.spi.MonetaryCurrenciesSingletonSpi;
18+
import java.util.ArrayList;
19+
import java.util.Collection;
20+
import java.util.Collections;
21+
import java.util.HashSet;
22+
import java.util.List;
23+
import java.util.Locale;
24+
import java.util.Objects;
25+
import java.util.Set;
26+
import java.util.logging.Level;
27+
import java.util.logging.Logger;
28+
29+
/**
30+
* Factory singleton for {@link javax.money.CurrencyUnit} instances as provided by the
31+
* different registered {@link javax.money.spi.CurrencyProviderSpi} instances.
32+
* <p>
33+
* This class is thread safe.
34+
*
35+
* @author Anatole Tresch
36+
* @version 0.8
37+
*/
38+
final class DefaultMonetaryCurrenciesSingletonSpi implements MonetaryCurrenciesSingletonSpi {
39+
40+
@Override
41+
public Set<CurrencyUnit> getCurrencies(CurrencyQuery query) {
42+
Set<CurrencyUnit> result = new HashSet<CurrencyUnit>();
43+
for (CurrencyProviderSpi spi : Bootstrap.getServices(CurrencyProviderSpi.class)) {
44+
try {
45+
result.addAll(spi.getCurrencies(query));
46+
} catch (Exception e) {
47+
Logger.getLogger(DefaultMonetaryCurrenciesSingletonSpi.class.getName())
48+
.log(Level.SEVERE, "Error loading currency provider names for " + spi.getClass().getName(),
49+
e);
50+
}
51+
}
52+
return result;
53+
}
54+
55+
/**
56+
* This default implementation simply returns all providers defined in arbitrary order.
57+
*
58+
* @return the default provider chain, never null.
59+
*/
60+
@Override
61+
public List<String> getDefaultProviderChain() {
62+
List<String> list = new ArrayList<String>();
63+
list.addAll(getProviderNames());
64+
Collections.sort(list);
65+
return list;
66+
}
67+
68+
/**
69+
* Get the names of the currently loaded providers.
70+
*
71+
* @return the names of the currently loaded providers, never null.
72+
*/
73+
@Override
74+
public Set<String> getProviderNames() {
75+
Set<String> result = new HashSet<String>();
76+
for (CurrencyProviderSpi spi : Bootstrap.getServices(CurrencyProviderSpi.class)) {
77+
try {
78+
result.add(spi.getProviderName());
79+
} catch (Exception e) {
80+
Logger.getLogger(DefaultMonetaryCurrenciesSingletonSpi.class.getName())
81+
.log(Level.SEVERE, "Error loading currency provider names for " + spi.getClass().getName(),
82+
e);
83+
}
84+
}
85+
return result;
86+
}
87+
88+
/**
89+
* Access a new instance based on the currency code. Currencies are
90+
* available as provided by {@link javax.money.spi.CurrencyProviderSpi} instances registered
91+
* with the {@link javax.money.spi.Bootstrap}.
92+
*
93+
* @param currencyCode the ISO currency code, not {@code null}.
94+
* @param providers the (optional) specification of providers to consider. If not set (empty) the providers
95+
* as defined by #getDefaultRoundingProviderChain() should be used.
96+
* @return the corresponding {@link javax.money.CurrencyUnit} instance.
97+
* @throws javax.money.UnknownCurrencyException if no such currency exists.
98+
*/
99+
public CurrencyUnit getCurrency(String currencyCode, String... providers) {
100+
Objects.requireNonNull(currencyCode, "Currency Code may not be null");
101+
Collection<CurrencyUnit> found =
102+
getCurrencies(CurrencyQueryBuilder.of().setCurrencyCodes(currencyCode).setProviderNames(providers).build());
103+
if (found.isEmpty()) {
104+
throw new UnknownCurrencyException(currencyCode);
105+
}
106+
if (found.size() > 1) {
107+
throw new MonetaryException("Ambiguous CurrencyUnit for code: " + currencyCode + ": " + found);
108+
}
109+
return found.iterator().next();
110+
}
111+
112+
/**
113+
* Access a new instance based on the currency code. Currencies are
114+
* available as provided by {@link javax.money.spi.CurrencyProviderSpi} instances registered
115+
* with the {@link javax.money.spi.Bootstrap}.
116+
*
117+
* @param country the ISO currency's country, not {@code null}.
118+
* @param providers the (optional) specification of providers to consider. If not set (empty) the providers
119+
* as defined by #getDefaultRoundingProviderChain() should be used.
120+
* @return the corresponding {@link javax.money.CurrencyUnit} instance.
121+
* @throws javax.money.UnknownCurrencyException if no such currency exists.
122+
*/
123+
public CurrencyUnit getCurrency(Locale country, String... providers) {
124+
Collection<CurrencyUnit> found =
125+
getCurrencies(CurrencyQueryBuilder.of().setCountries(country).setProviderNames(providers).build());
126+
if (found.isEmpty()) {
127+
throw new MonetaryException("No currency unit found for locale: " + country);
128+
}
129+
if (found.size() > 1) {
130+
throw new MonetaryException("Ambiguous CurrencyUnit for locale: " + country + ": " + found);
131+
}
132+
return found.iterator().next();
133+
}
134+
135+
/**
136+
* Provide access to all currently known currencies.
137+
*
138+
* @param locale the target {@link java.util.Locale}, typically representing an ISO country,
139+
* not {@code null}.
140+
* @param providers the (optional) specification of providers to consider. If not set (empty) the providers
141+
* as defined by #getDefaultRoundingProviderChain() should be used.
142+
* @return a collection of all known currencies, never null.
143+
*/
144+
public Set<CurrencyUnit> getCurrencies(Locale locale, String... providers) {
145+
return getCurrencies(CurrencyQueryBuilder.of().setCountries(locale).setProviderNames(providers).build());
146+
}
147+
148+
/**
149+
* Allows to check if a {@link javax.money.CurrencyUnit} instance is defined, i.e.
150+
* accessible from {@link javax.money.spi.MonetaryCurrenciesSingletonSpi#getCurrency(String, String...)}.
151+
*
152+
* @param code the currency code, not {@code null}.
153+
* @param providers the (optional) specification of providers to consider. If not set (empty) the providers
154+
* as defined by #getDefaultRoundingProviderChain() should be used.
155+
* @return {@code true} if {@link javax.money.spi.MonetaryCurrenciesSingletonSpi#getCurrency(String, String...)}
156+
* would return a result for the given code.
157+
*/
158+
public boolean isCurrencyAvailable(String code, String... providers) {
159+
return !getCurrencies(CurrencyQueryBuilder.of().setCurrencyCodes(code).setProviderNames(providers).build())
160+
.isEmpty();
161+
}
162+
163+
/**
164+
* Allows to check if a {@link javax.money.CurrencyUnit} instance is
165+
* defined, i.e. accessible from {@link #getCurrency(String, String...)}.
166+
*
167+
* @param locale the target {@link java.util.Locale}, not {@code null}.
168+
* @param providers the (optional) specification of providers to consider. If not set (empty) the providers
169+
* as defined by #getDefaultRoundingProviderChain() should be used.
170+
* @return {@code true} if {@link #getCurrencies(java.util.Locale, String...)} would return a
171+
* non empty result for the given code.
172+
*/
173+
public boolean isCurrencyAvailable(Locale locale, String... providers) {
174+
return !getCurrencies(CurrencyQueryBuilder.of().setCountries(locale).setProviderNames(providers).build()).isEmpty();
175+
}
176+
177+
/**
178+
* Provide access to all currently known currencies.
179+
*
180+
* @param providers the (optional) specification of providers to consider. If not set (empty) the providers
181+
* as defined by #getDefaultRoundingProviderChain() should be used.
182+
* @return a collection of all known currencies, never null.
183+
*/
184+
public Set<CurrencyUnit> getCurrencies(String... providers) {
185+
return getCurrencies(CurrencyQueryBuilder.of().setProviderNames(providers).build());
186+
}
187+
188+
/**
189+
* Access a single currency by query.
190+
*
191+
* @param query The currency query, not null.
192+
* @return the {@link javax.money.CurrencyUnit} found, never null.
193+
* @throws javax.money.MonetaryException if multiple currencies match the query.
194+
*/
195+
public CurrencyUnit getCurrency(CurrencyQuery query) {
196+
Set<CurrencyUnit> currencies = getCurrencies(query);
197+
if (currencies.isEmpty()) {
198+
return null;
199+
}
200+
if (currencies.size() == 1) {
201+
return currencies.iterator().next();
202+
}
203+
throw new MonetaryException("Ambiguous request for CurrencyUnit: " + query + ", found: " + currencies);
204+
}
205+
}

0 commit comments

Comments
 (0)