@@ -1495,26 +1495,12 @@ This runtime exception +extends MonetaryException+ and is thrown whenever
1495
1495
* a +Locale+ given cannot be resolved into a corresponding +CurrencyUnit+ instance. The unresolvable +Locale+ passed is
1496
1496
provided as a property on the exception as +public Locale getLocale();+.
1497
1497
1498
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1499
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1501
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1503
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1504
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1506
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1507
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1508
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1509
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1510
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1511
-
1512
1498
[[CurrencyConversion]]
1513
1499
=== Currency Conversion
1514
- Currency conversion is an important aspects when dealing with monetary amounts. Unfortunately currency conversion has
1500
+ Currency conversion is an important aspect when dealing with monetary amounts. Unfortunately currency conversion has
1515
1501
a great variety of how it is implemented. Whereas a web shop may base its logic on an API provided by a financial
1516
- backend, that make explicit conversion even not necessary, in the financial industry, conversion is a very complex
1517
- aspects , since
1502
+ backend, that makes explicit conversion even not necessary, in the financial industry, conversion is a very complex
1503
+ concern , since
1518
1504
1519
1505
* conversion may be different based on the use case
1520
1506
* conversion may be different based on the provider of the exchange rates
@@ -1523,51 +1509,69 @@ aspects, since
1523
1509
* conversion rates are different related to the target timestamp
1524
1510
1525
1511
Hereby this list is not complete. Different companies may have further requirements and aspects to be considered.
1512
+ The API focuses on the common aspects of currency conversion such as:
1513
+
1514
+ * a source and a target currency
1515
+ * an exchange rate
1516
+ * providing conversion providers and having the possibiity to address and combine providers as needed.
1517
+
1518
+ Hereby currency conversion or the access of exchange rates can be parametrized with additional meta-data, similar
1519
+ to other models defined by this JSR. This allows to enrich the basic model with whatever complexity is required,
1520
+ hereby keeping the basic model as simple as possible.
1526
1521
1527
1522
[[AccessingConversions]]
1528
1523
==== Accessing Monetary Conversions
1529
- The API defines a singleton accessor, called +MonetaryConversions+, which provides access to all different aspects
1530
- related to currency conversion, such as
1524
+ Similar to other areas of this JSR a +MonetaryConversions+ singleoton is defined , which provides access to all different
1525
+ aspects related to currency conversion, such as
1531
1526
1532
- * access to providers that offer conversion rates, modelled as +<<ExchangeRate>>+.
1533
- * access to conversion operators (extending +MonetaryOperator+), that can be used with any +MonetaryAmount+ instances.
1527
+ * access to providers that offer conversion rates, modelled as +<<ExchangeRateProviders, ExchangeRate>>+.
1528
+ * access to conversion operators (+CurrencyConversion extends MonetaryOperator+), that can be used with any
1529
+ +MonetaryAmount+ instances.
1534
1530
* access to further information about the providers currently available.
1535
1531
1536
- The following sections give an overview about the functionality in more detail. Similar to other singletons in this API
1537
- the singleton is backed up by a +MonetaryConversionsSingletonSpi+ SPI to allow customized (contextual) implementation
1538
- of the functionality defined. Refer to the SPI section in this document for more details.
1532
+ The following sections give an overview about the functionality in more detail. Similar to other singletons also
1533
+ +MonetaryConversions+ is backed up by a +MonetaryConversionsSingletonSpi+ SPI to allow customized (e.g. contextual)
1534
+ implementation of the functionality defined. Refer to the << SPI>> section in this document for more details.
1539
1535
1540
1536
==== Converting Amounts
1541
- Basically converting of amounts is modelled by the +CurrencyConversion+ interface which + extends MonetaryOperator+,
1537
+ Basically converting of amounts is modelled by the +CurrencyConversion+ interface which extends + MonetaryOperator+,
1542
1538
hereby adding meta-data support, modelled by +ConversionContext+. Hereby a *conversion is always bound to a specific
1543
- terminating (target) currency*. So basically a +MonetaryAmount+ can simply be converted by
1539
+ terminating (target) currency*. So basically a +MonetaryAmount+ can simply be converted by passing a
1540
+ +CurrencyConversion+ to the amount's +with(MonetaryOperator)+ method:
1544
1541
1545
1542
[source,java]
1546
1543
.Usage Sample Currency Conversion
1547
1544
-------------------------------------------------------------------------------
1548
1545
MonetaryAmount amount = ...;
1546
+
1547
+ // Get a default conversion to Swiss Franc
1549
1548
CurrencyConversion conversion = MonetaryConversions.getConversion("CHF");
1549
+
1550
+ // Convert the amount
1550
1551
MonetaryAmount amount2 = amount.with(conversion);
1551
1552
-------------------------------------------------------------------------------
1552
1553
1553
1554
Using a fluent API style this can be written even shorter as:
1554
1555
1555
1556
[source,java]
1556
- .Usage Sample Currency Conversion, using the fluent API
1557
1557
-------------------------------------------------------------------------------
1558
1558
MonetaryAmount amount2 = amount.with(MonetaryConversions.getConversion("CHF"));
1559
1559
-------------------------------------------------------------------------------
1560
1560
1561
- A +CurrencyConversion+ instance hereby also allows to extract the +ExchangeRate+ instances used:
1561
+ A +CurrencyConversion+ instance hereby also allows to extract the concrete +ExchangeRate+ applied. This allows
1562
+ further pass the +ExchangeRate+ instance to any subsequent logic.
1562
1563
1563
1564
[source,java]
1564
- .Usage Sample Currency Conversion, accessing exchange rates
1565
+ .Currency Conversion, accessing exchange rates
1565
1566
-------------------------------------------------------------------------------
1566
1567
CurrencyConversion conversion = MonetaryConversions.getConversion("CHF");
1567
1568
MonetaryAmount amount = ...;
1568
1569
ExchangeRate rate = conversion.getExchangeRate(amount);
1569
1570
-------------------------------------------------------------------------------
1570
1571
1572
+ Nevertheless for accessing +ExchangeRate+ instances an +ExchangeRateProvider+ is much more effective. It can be accessed
1573
+ from the +MonetaryConversions+ singletons as well as from a +CurrencyConversion+.
1574
+
1571
1575
[[ExchangeRates]]
1572
1576
==== Exchange Rates and Rate Providers
1573
1577
===== Exchange Rates
@@ -1586,11 +1590,11 @@ Summarizing an +ExchangeRate+ is modelled as follows:
1586
1590
[source,java]
1587
1591
.Interface ExchangeRate
1588
1592
-------------------------------------------------------------------------------
1589
- public interface ExchangeRate{
1593
+ public interface ExchangeRate extends CurrencySupplier {
1590
1594
...
1591
1595
ConversionContext getConversionContext();
1592
- CurrencyUnit getBase ();
1593
- CurrencyUnit getTerm ();
1596
+ CurrencyUnit getBaseCurrency ();
1597
+ CurrencyUnit getCurrency ();
1594
1598
NumberValue getFactor();
1595
1599
// Support for chained rates
1596
1600
List<ExchangeRate> getExchangeRateChain();
@@ -1600,7 +1604,7 @@ public interface ExchangeRate{
1600
1604
1601
1605
Hereby
1602
1606
1603
- * +getBase (), getTerm (), getFactor()+ model basically the mapping from the base currency to the target currency.
1607
+ * +getBaseCurrency (), getCurrency (), getFactor()+ model basically the mapping from the base currency to the target currency.
1604
1608
* +isDerived()+ allows to check if the mapping in fact is backed up by a derived mapping, e.g. a triangular rate chain.
1605
1609
* +getExchangeRateChain()+ return the full rate chain. In case of a non derived rate, this chain must contain only
1606
1610
the single rate itself. In case of triangular rate the chain contains all contained subrates.
@@ -1624,8 +1628,8 @@ Implementations of +ExchangeRate+
1624
1628
. should be implemented as value types, with a fluent Builder pattern.
1625
1629
1626
1630
===== Exchange Rate Providers
1627
- We have seen in the previous section that an +ExchangeRate+ can be obtained from a +CurrencyConversion+. Hereby a
1628
- currency conversion is backed up by an +ExchangeRateProvider+. Such a provider allows
1631
+ We have seen in the previous section that an +ExchangeRate+ can be obtained from a +CurrencyConversion+ or from
1632
+ its backing +ExchangeRateProvider+. Such a provider allows
1629
1633
1630
1634
* to access +ExchangeRate+ instances, providing a base and a terminating (target) currency.
1631
1635
* to access +CurrencyConversion+ instances, providing a terminating (target) currency.
@@ -1637,20 +1641,20 @@ Summarizing an +ExchangeRateProvider+ is modelled as follows:
1637
1641
-------------------------------------------------------------------------------
1638
1642
public interface ExchangeRateProvider{
1639
1643
ProviderContext getProviderContext();
1640
- boolean isAvailable(CurrencyUnit base, CurrencyUnit term, ConversionContext conversionContext);
1641
- ExchangeRate getExchangeRate(CurrencyUnit base, CurrencyUnit term, ConversionContext conversionContext );
1642
- CurrencyConversion getCurrencyConversion(CurrencyUnit term, ConversionContext conversionContext );
1643
-
1644
- default boolean isAvailable(CurrencyUnit base, CurrencyUnit term){...}
1645
- default boolean isAvailable(String baseCode, String termCode){...}
1646
- default boolean isAvailable(String baseCode, String termCode, ConversionContext conversionContext){...}
1647
- default ExchangeRate getExchangeRate(CurrencyUnit base, CurrencyUnit term){...}
1648
- default ExchangeRate getExchangeRate(String baseCode, String termCode){...}
1649
- default ExchangeRate getExchangeRate(String baseCode, String termCode, ConversionContext conversionContext){...}
1650
- default ExchangeRate getReversed(ExchangeRate rate){...}
1651
- default CurrencyConversion getCurrencyConversion(CurrencyUnit term){...}
1652
- default CurrencyConversion getCurrencyConversion(String termCode){...}
1653
- default CurrencyConversion getCurrencyConversion(String termCode, ConversionContext conversionContext){...}
1644
+
1645
+ boolean isAvailable(ConversionQuery conversionQuery );
1646
+ ExchangeRate getExchangeRate(ConversionQuery conversionQuery );
1647
+ CurrencyConversion getCurrencyConversion(ConversionQuery conversionQuery);
1648
+
1649
+ default boolean isAvailable(CurrencyUnit base, CurrencyUnit term);
1650
+ default boolean isAvailable(String baseCode, String termCode);
1651
+ default ExchangeRate getExchangeRate(CurrencyUnit base, CurrencyUnit term);
1652
+ default ExchangeRate getExchangeRate(String baseCode, String termCode);
1653
+ default CurrencyConversion getCurrencyConversion(CurrencyUnit term);
1654
+ default CurrencyConversion getCurrencyConversion(String termCode);
1655
+
1656
+ default ExchangeRate getReversed(ExchangeRate rate);
1657
+
1654
1658
}
1655
1659
-------------------------------------------------------------------------------
1656
1660
@@ -1664,6 +1668,24 @@ Hereby
1664
1668
* the +getCurrencyConversion+ methods allow to access a +CurrencyConversion+ that is internally backed up by the
1665
1669
given rate provider instance.
1666
1670
1671
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1672
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1673
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1674
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1675
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1677
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1678
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1679
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1680
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1681
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1682
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1683
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1684
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1685
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1686
+
1687
+
1688
+
1667
1689
===== Conversion Context
1668
1690
The API allows additionally to pass a +ConversionContext+, which allow to pass any additional attributes/parameters
1669
1691
that may be required by a concrete +ExchangeRateProvider+ instance. This allows to support arbitrary complex use cases,
0 commit comments