I'm trying to format an amount using the correct formatting rules, given the ISO 4217 numeric currency code.
For example, given an amount of 99.99 and numeric code 840, I expect to produce a string 'USD 99.99' or similar.
Looking at the JSR 354 implementation, it seems that i need to first find the appropriate currency unit. However, I cant seem to compose a valid CurrencyQuery for this purpose.
Given
CurrencyQuery query = CurrencyQueryBuilder.of().setNumericCodes(840).build();
CurrencyUnit cu = Monetary.getCurrency(query);
MonetaryAmount amount = FastMoney.of(99.99, cu);
System.out.println(MonetaryFormats.getAmountFormat(Locale.ENGLISH).format(amount));
I receive the following exception:
Exception in thread "main" javax.money.MonetaryException: Ambiguous request for CurrencyUnit: CurrencyQuery (
{Query.numericCodes=[840]}), found: [BIF, ARS, DZD, COP, CVE, CHF, HRK, IQD, LAK, XPF, DKK, BAM, ZMK, ITL, XBB, XUA, XPT, BRL, CAD, NZD, SEK, USN, XTS, IEP, SRG, STD, BHD, USS, XAF, AUD, CDF, MTL, QAR, AOA, MGA, TOP, LYD, BOV, ISK, ADP, HTG, IDR, ANG, XXX, BTN, KHR, LTL, KES, INR, MGF, OMR, BEF, EUR, BOB, JPY, XBA, AED, SOS, XPD, SKK, FKP, XBC, CRC, SCR, MYR, MZN, LVL, GYD, XDR, GHS, XCD, MDL, MRO, ZWN, LSL, PEN, ATS, XOF, AZM, BYB, TRY, SRD, TTD, IRR, NOK, BZD, TRL, BDT, KZT, CLF, SLL, USD, ETB, BSD, SDD, UYU, ESP, VEB, TMM, CUP, NAD, DOP, NPR, TJS, VND, ZWR, AMD, FRF, TWD, LUF, GNF, MOP, MKD, JMD, CZK, PTE, LBP, ZWD, RSD, FIM, AZN, SDG, GHC, THB, MMK, BBD, PLN, ROL, NGN, RON, TZS, ERN, GBP, TPE, UZS, XBD, SGD, MXV, SVC, FJD, GWP, CNY, BYR, RUB, CSD, XAG, HKD, BND, SHP, KPW, CLP, KYD, DJF, ILS, RUR, LRD, SYP, SAR, ZWL, VUV, DEM, XSU, SIT, PHP, PYG, TND, HNL, ZAR, XFO, BMD, MWK, ZMW, UGX, NLG, JOD, KWD, YER, GMD, CUC, BGL, RWF, UAH, MVR, AWG, MZM, LKR, CYP, VEF, BWP, MXN, KRW, TMT, GIP, MUR, MNT, EEK, GTQ, PKR, PAB, KGS, GRD, YUM, SZL, GEL, WST, MAD, EGP, SBD, ALL, PGK, NIO, AFA, BGN, XAU, SSP, AFN, HUF, XFU, AYM, KMF]
How should I compose the currency query? Is there a better way?
TestCurrencyQuery.java:
package test;
import java.util.Locale;
import javax.money.CurrencyQuery;
import javax.money.CurrencyQueryBuilder;
import javax.money.CurrencyUnit;
import javax.money.Monetary;
import javax.money.MonetaryAmount;
import javax.money.format.MonetaryFormats;
import org.javamoney.moneta.FastMoney;
public class TestCurrencyQuery {
public static void main(String[] args) {
System.out.println(System.getProperty("java.vm.name"));
System.out.println(System.getProperty("java.version"));
System.out.println(System.getProperty("java.specification.vendor"));
CurrencyQuery query = CurrencyQueryBuilder.of().setNumericCodes(840).build();
CurrencyUnit cu = Monetary.getCurrency(query);
MonetaryAmount amount = FastMoney.of(99.99, cu);
System.out.println(MonetaryFormats.getAmountFormat(Locale.ENGLISH).format(amount));
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test-jsr354</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.javamoney</groupId>
<artifactId>moneta</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>
Console output:
Java HotSpot(TM) 64-Bit Server VM
1.8.0_31
Oracle Corporation
Exception in thread "main" javax.money.MonetaryException: Ambiguous request for CurrencyUnit: CurrencyQuery (
{Query.numericCodes=[840]}), found: [KHR, RON, XTS, FJD, LRD, MVR, BRL, ZMK, PKR, LBP, LYD, SDG, MXV, AED, XDR, STD, CDF, QAR, ISK, SHP, CSD, FRF, BMD, PTE, PLN, XUA, UYU, GYD, LAK, ZAR, ZMW, MKD, XSU, XAF, EEK, ILS, UGX, ITL, XPT, ROL, MUR, INR, TWD, KES, FIM, CHF, HNL, ARS, BGL, KRW, SBD, PHP, RUR, PYG, SRD, AWG, MXN, MGA, SGD, TRL, MZN, SOS, MOP, XBA, IRR, CZK, XFU, TRY, UZS, XFO, TTD, SDD, SCR, COP, ALL, XAU, SYP, USN, PAB, CUC, JMD, GNF, BHD, ANG, IDR, GWP, DEM, SLL, SVC, HRK, NLG, TMT, KZT, MTL, CUP, VEF, ZWN, NOK, LVL, CLF, TMM, BEF, VEB, MZM, DOP, GHS, BBD, XPF, CYP, UAH, BAM, TPE, BND, BYB, MGF, SIT, BWP, XBD, XCD, LSL, AYM, RUB, ADP, SEK, YUM, AOA, WST, GBP, ZWD, THB, ZWL, ESP, MAD, USS, ETB, NGN, AUD, TZS, XAG, VND, BTN, JOD, PGK, XBB, DKK, VUV, BYR, NZD, EGP, SSP, KMF, CNY, MWK, AZM, SAR, CVE, HUF, HTG, SRG, AZN, GIP, LUF, DJF, GEL, RWF, TJS, TOP, TND, ERN, OMR, GRD, MMK, LKR, FKP, NIO, ATS, KPW, PEN, AMD, IEP, BZD, XXX, BIF, GTQ, KYD, EUR, LTL, CRC, HKD, BGN, RSD, SZL, USD, KWD, CLP, MYR, BOB, AFA, GHC, JPY, AFN, GMD, MDL, IQD, BSD, MNT, NPR, MRO, XPD, DZD, NAD, CAD, BOV, KGS, ZWR, SKK, XOF, YER, BDT, XBC]
at javax.money.spi.MonetaryCurrenciesSingletonSpi.getCurrency(MonetaryCurrenciesSingletonSpi.java:173)
at javax.money.Monetary.getCurrency(Monetary.java:506)
at test.TestCurrencyQuery.main(TestCurrencyQuery.java:21)
As already mentioned, you're not able to access CurrencyUnit via Currency Code using this implementation. If your task is strictly accept currency code as parameter, you can create your own mapping. The better approach is to using database where you can store mapping between numeric codes and currency codes.
package test;
import java.util.Locale;
import javax.money.CurrencyQuery;
import javax.money.CurrencyQueryBuilder;
import javax.money.CurrencyUnit;
import javax.money.Monetary;
import javax.money.MonetaryAmount;
import javax.money.format.MonetaryFormats;
import org.javamoney.moneta.FastMoney;
public class TestCurrencyQuery {
public static void main(String[] args) {
System.out.println(System.getProperty("java.vm.name"));
System.out.println(System.getProperty("java.version"));
System.out.println(System.getProperty("java.specification.vendor"));
CurrencyQuery query = CurrencyQueryBuilder.of().setCurrencyCodes(getCurrencyCodesFromNumeric(840)).build();
CurrencyUnit cu = Monetary.getCurrency(query);
MonetaryAmount amount = FastMoney.of(99.99, cu);
System.out.println(MonetaryFormats.getAmountFormat(Locale.ENGLISH).format(amount));
}
public String[] getCurrencyCodesFromNumeric(int... codes) {
Collection<String> currencyCodes = // query db and return associated String currency codes;
return currencyCodes.toArray(new String[currencyCodes.size()]);
}
}