From 2dc805be659b2f3926da1df37c095c4cdd548259 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Tue, 18 Oct 2011 15:14:22 +0200 Subject: [PATCH] remove currency thing again, has errors --- .../src/main/scala/code/lib/Currency.scala | 1047 ----------------- 1 file changed, 1047 deletions(-) delete mode 100644 MavLift/src/main/scala/code/lib/Currency.scala diff --git a/MavLift/src/main/scala/code/lib/Currency.scala b/MavLift/src/main/scala/code/lib/Currency.scala deleted file mode 100644 index 1efcc7c42..000000000 --- a/MavLift/src/main/scala/code/lib/Currency.scala +++ /dev/null @@ -1,1047 +0,0 @@ -/* - * Copyright (c) 2009 Thomas Knierim - * http://www.thomasknierim.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package currency - -import java.math.{BigDecimal => BigDec} - -/** Represents an immutable, arbitrary-precision currency value with fixed point - * arithmetic.

A Currency value consists of a numeric value, - * an optional currency designation, and an optional number of decimal places. - * The default number of positions after the decimal point is 2 or respectively - * the number of decimal places commonly used for the specified currency.

- * - *

Its numeric value is internally represented by a 128-bit java.math.BigDecimal - * with 34 significant decimal places. This allows high-precision computations over - * a large range of values. As an added benefit of using java.math.BigDecimal, - * the Currency type gives users complete control over rounding behaviour. - * The default rounding more is ROUND_HALF_UP which is commonly used in - * commercial applications. The ROUND_HALF_EVEN mode may be useful for statistical - * applications.

- * - *

Computations are carried out with a precision of n positions after the decimal - * point, whereas n is specified by the decimals parameter. The position - * at n + 1 is rounded according to the specified rounding mode.

- * - *

The Currency class distinguishes between specific and non-specific - * currencies. Specific currencies carry a designation that is specified by the respective - * ISO 4217 three-letter currency code. Non-specific values are values without currency code. - * Non-specific values can be added to or subtracted from specific values. Used with - * non-specific values only, the Currency class offers general purpose - * fixed-point arithmetic.

- * - * @author Thomas Knierim - * @version 1.0 - * - * 20090506 tk v first release - * 20100312 tk f fixed errors in country code map - * - */ -@serializable -class Currency (value: BigDec, val currencyCode: String, val decimals: Int, - val roundingMode: Currency.RoundingMode.Value) extends Ordered[Currency]{ - - if (decimals < 0) - throw new IllegalArgumentException("Currency decimal places must not be negative.") - -/** Contains the amount of the Currency value as - * java.math.BigDecimal. - */ - val amount = value.setScale(decimals, roundingMode.id) - -/** Returns a new Currency value with the specified number of decimals - * after the decimal point whose value is equal to this value. If the - * number of decimals is decreased, loss of precision may incur and the last position - * is rounded according to the specified round mode (ROUND_HALF_UP by - * default). - * - * @param d number of decimal places in the result value. - * @return this Currency value with d decimal places. - */ - def setDecimals(d: Int) = new Currency(amount, currencyCode, d, roundingMode) - -/** Compares this Currency value with the specified value for equality. - * Two currency values are considered equal if they have the same currency code - * and the same numeric value. Decimals and rounding mode are not regarded. - * Note that this means that equal currency values can have different string - * representations, e.g. "10 USD" == "10.00 USD". - * - * @param the Currency value to comapare to this value. - * @return true if the values are equal, false otherwise. - */ - override def equals(that: Any): Boolean = that match { - case that: Currency => this.currencyCode == that.currencyCode && - this.amount.compareTo(that.amount) == 0 - case _ => false - } - -/* Trims trailing zeros from decimal positions of a numeric String - */ - private def trimZeros(s: String) = { - if (s.indexOf('.') > -1) { - var i = s.length - while(i > 0 && s(i - 1) == '0') i -= 1 - if (s(i - 1) == '.') i -= 1 - s.substring(0, i) - } - else s - } - -/** Returns a hash code for this Currency value. - * - * @return hash code for this value. - */ - override def hashCode: Int = - 41 * (41 + trimZeros(amount.toString).hashCode) + currencyCode.hashCode - -/** Compares this Currency value with the specified value. - * Throws MismatchedCurrencyException if two values with - * different currency codes are compared. - * - * @param that Currency value to which this value is compared. - * @return -1, 0, or 1 as this Currency value is less than, equal to, or - * greater than that. - * @throws MismatchedCurrencyException if currency codes don't match. - */ - def compare(that: Currency): Int = - if (this.currencyCode != that.currencyCode) - throw new MismatchedCurrencyException - else - this.amount.compareTo(that.amount) - -/** Returns the smaller of this Currency value and the given value. - * If both values are equal, this is returned. - * - * @param that Currency value to compare to. - * @return the smaller Currency value. - * @throws MismatchedCurrencyException if currency codes don't match. - */ - def min (that: Currency): Currency = - if (this.compare(that) <= 0) this else that - -/** Returns the larger of this Currency value and the given value. - * If both values are equal, this is returned. - * - * @param that Currency value to compare to. - * @return the larger Currency value. - * @throws MismatchedCurrencyException if currency codes don't match. - */ - def max (that: Currency): Currency = - if (this.compare(that) >= 0) this else that - -/** Adds a Currency value to this value and returns the sum as a new - * Currency value. The number of decimal places in the result is - * automatically adjusted to that of the summand with the wider scale. Currency - * codes need to be regarded: - * - * - * @param that Currency value to add. - * @return the sum of both Currency values. - * @throws MismatchedCurrencyException if currency codes don't match. - * - */ - def + (that: Currency): Currency = { - var code = this.currencyCode - if (code.isEmpty) - code = that.currencyCode - else if (this.currencyCode != that.currencyCode && !that.currencyCode.isEmpty) - throw new MismatchedCurrencyException - val result = this.amount.add(that.amount) - new Currency(result, code, result.scale, this.roundingMode) - } - -/** Subtracts a Currency value from this value and returns the difference - * as a new Currency value. The number of decimal places in the result is - * automatically adjusted to that of the argument with the wider scale. Currency - * codes need to be regarded: - * - * - * @param that Currency value to subtract. - * @return the value of this - that. - * @throws MismatchedCurrencyException if currency codes don't match. - */ - def - (that: Currency): Currency = { - var code = this.currencyCode - if (code.isEmpty) - code = that.currencyCode - else if (this.currencyCode != that.currencyCode && !that.currencyCode.isEmpty) - throw new MismatchedCurrencyException - val result = this.amount.subtract(that.amount) - new Currency(result, code, result.scale, this.roundingMode) - } - -/** Multiplies this Currency value with a java.math.BigDecimal - * scalar value and returns a new Currency value. - * - * @param that the mulitiplier. - * @return the value of this * that. - */ - def * (that: BigDec): Currency = - new Currency(this.amount.multiply(that), currencyCode, decimals, roundingMode) - -/** Multiplies this Currency value with a Double - * scalar value and returns a new Currency value. - * - * @param that the mulitiplier. - * @return the value of this * that. - */ - def * (that: Double): Currency = this * BigDec.valueOf(that) - -/** Multiplies this Currency value with a Long - * scalar value and returns a new Currency value. - * - * @param that the mulitiplier. - * @return the value of this * that. - */ - def * (that: Long): Currency = this * BigDec.valueOf(that) - -/** Divides this Currency value by a java.math.BigDecimal - * scalar value and returns a new Currency value. - * - * @param that the divisor. - * @return the value of this / that. - */ - def / (that: BigDec): Currency = - new Currency(this.amount.divide(that, roundingMode.id), currencyCode, decimals, roundingMode) - -/** Divides this Currency value by a Double - * scalar value and returns a new Currency value. - * - * @param that the divisor. - * @return the value of this / that. - */ - def / (that: Double): Currency = this / BigDec.valueOf(that) - -/** Divides this Currency value by a Long - * scalar value and returns a new Currency value. - * - * @param that the divisor. - * @return the value of this / that. - */ - def / (that: Long): Currency = this / BigDec.valueOf(that) - - /** Returns a Currency whose value is -this. - * - * @return -this. - */ - def unary_- : Currency = new Currency(amount.negate(), currencyCode, decimals, roundingMode) - - /** Returns a Currency whose value is the absolute value of this - * Currency. - * - * @return abs(this). - * - */ - def abs: Currency = new Currency(amount.abs(), currencyCode, decimals, roundingMode) - -/** Returns a Currency whose value is this * p / 100. - * - * @param p the percentage. - * @return the result of the applied percentage. - */ - def percent(p: Double) = (this * p) / 100 - -/** Returns a Currency whose value is the integer part of this value. - * Example: Currency(2.50).integral returns Currency(2.00). - * - * @return the integral part of this value. - */ - def integral = new Currency(amount.divideToIntegralValue(new BigDec("1")), - currencyCode, decimals, roundingMode) - -/** Returns a Currency whose value is the fractional part of this value. - * Example: Currency(2.50).fraction returns Currency(0.50). - * - * @return the fractionalal part of this value. - */ - def fraction = new Currency(amount.subtract(integral.amount), - currencyCode, decimals, roundingMode) - -/** Returns a Currency whose value is (thisexp). - * - * @param exp the power to raise this Currency value to. - * @return thisexp. - */ - def pow(exp: Int) = new Currency(amount.pow(exp), currencyCode, decimals, roundingMode) - -/** Returns a canonical String representation of the Currency - * value with 3-letter ISO currency code. - * - * @return formatted String with decimals positions after decimal point. - */ - override def toString = { - amount.toString + - (if (currencyCode.isEmpty) "" else " " + currencyCode) - } - -/** Returns the amount of the Currency value as Double value. - * If this value has too great a magnitude represent as a Double, it will - * be converted to Double.NEGATIVE_INFINITY or - * Double.POSITIVE_INFINITY as appropriate. - * - * @return this Currency value converted to a Double. - */ - def toDouble = amount.doubleValue - -/** Returns the amount of the Currency value as Float value. - * If this value has too great a magnitude represent as a Float, it will - * be converted to Float.NEGATIVE_INFINITY or - * Float.POSITIVE_INFINITY as appropriate. - * - * @return this Currency value converted to a Float. - */ - def toFloat = amount.floatValue - -/** Returns the amount of the Currency value as Long value. - * Any fractional part will be discarded. If this value is too big to fit in a - * Long, only the low-order 64 bits are returned. - * - * @return this Currency value converted to a Long. - */ - def toLong = amount.longValue - -/** Returns the amount of the Currency value as an Int value. - * Any fractional part will be discarded. If this value is too big to fit in an - * Int, only the low-order 32 bits are returned. - * - * @return this Currency value converted to an Int. - */ - def toInt = amount.intValue - -/** Returns the currency symbol for this Currency, or the empty - * string if this is a non-specific Currency value. - * - * @return Unicode currency symbol. - * - */ - def symbol = { - if (currencyCode.isEmpty) - "" - else { - var symbol = Currency.getSymbolFor(this.currencyCode) - if (symbol.isEmpty) - currencyCode - else - symbol - } - } - -/** Returns the English name for this Currency, or the empty - * string if this is a non-specific Currency value. - * - * @return currency name. - */ - def name = Currency.getNameFor(this.currencyCode) - -/** Formats a currency value according to default locale. - * See java.util.Locale and java.text.NumberFormat for details. - */ - def format: String = { - val nf = java.text.NumberFormat.getCurrencyInstance() - nf.setCurrency(java.util.Currency.getInstance("USD")) - nf.format(amount).replace("USD", symbol).replace("$", symbol) - } - -/** Formats a currency value according to given locale. - * See java.util.Locale and java.text.NumberFormat for details. - */ - def format(locale: java.util.Locale): String = { - val nf = java.text.NumberFormat.getCurrencyInstance(locale) - nf.setCurrency(java.util.Currency.getInstance("USD")) - nf.format(amount).replace("USD", symbol).replace("$", symbol) - } - -/** Formats a currency value according to the given pattern. - * See java.text.DecimalFormat for details on format patterns. - * - * @param pattern a decimal number pattern string. - * @throws IllegalArgumentException if the given pattern is invalid. - */ - def format(pattern: String): String = { - new java.text.DecimalFormat(pattern. - replace("\u00A4\u00A4", currencyCode). - replace("\u00A4", symbol)). - format(amount) - } - -/** Formats a currency value according to the given pattern and with the - * given decimal symbols. See java.text.DecimalFormat for - * details on format patterns and symbols. - * - * @param pattern a decimal number pattern string. - * @param symbols the set of symbols to be used. - * @throws IllegalArgumentException if the given pattern is invalid. - */ - def format(pattern: String, symbols: java.text.DecimalFormatSymbols): String = { - new java.text.DecimalFormat(pattern. - replace("\u00A4\u00A4", currencyCode). - replace("\u00A4", symbol), symbols). - format(amount) - } - -/** Formats a currency value according to the given DecimalFormat object. - * This method gives you the most fine-grained control over the format output. It is - * also the most efficient one for repetitive formatting of Currency values. - * See java.text.DecimalFormat for details. - * - * @param format custom format object. - * @throws IllegalArgumentException if the given custom format cannot be applied. - */ - def format(format: java.text.DecimalFormat): String = format.format(amount) - -/** Verbalises this Currency value in the English language. The amount is - * spelled out with integral and fractional units and with currency name. Only numbers - * that fit into a 64-bit Long integer can be verbalised. Larger numbers - * are returned as numeric strings. - * - * @return this Currency value in words. - */ - def say: String = say(java.util.Locale.ENGLISH) - -/** Verbalises this Currency value in the given language. The amount is - * spelled out with integral and fractional units and with currency name. Only numbers - * that fit into a 64-bit Long integer can be verbalised. Larger numbers - * are returned as numeric strings. Currently only English, French, Spanish and - * German are supported. - * - * @return this Currency value in words. - * @throws IllegalArgumentException if the language is not supported. - */ - def say(locale: java.util.Locale): String = - { - val num = amount.divideAndRemainder(new BigDec("1")) - val result = try { - val integral = num(0).longValueExact() - val fraction = num(1).movePointRight(decimals).abs.longValue() - val language = locale.getLanguage() - VerbaliseNumber.toWords(integral, language) + " " + - Currency.getNameFor(currencyCode) + - (if (language == "en" && Math.abs(integral) > 1) "s" else "") + - (if (fraction != 0L) - " " + VerbaliseNumber.toWords(fraction, locale.getLanguage()) + " " + - Currency.getFractNameFor(currencyCode) + - (if (language == "en" && fraction > 1) "s" else "") - else "") - } catch { - case e: ArithmeticException => amount.toString + " " + Currency.getNameFor(currencyCode) - } - result - } - -/** Verbalises this Currency value in the English language. The integral - * part of the amount is spelled out and the fractional part is written in the - * form xx/100. Only numbers that fit into a 64-bit Long - * integer can be verbalised. Larger numbers are returned as numeric strings. - * Currently only English, French, Spanish and German are supported. - * - * @return this Currency value in words. - */ - def sayNumber: String = sayNumber(java.util.Locale.ENGLISH) - -/** Verbalises this Currency value in the given language. The integral - * part of the amount is spelled out and the fractional part is written in the - * form xx/100. Only numbers that fit into a 64-bit Long - * integer can be verbalised. Larger numbers are returned as numeric strings. - * Currently only English, French, Spanish and German are supported. - * - * @return this Currency value in words. - * @throws IllegalArgumentException if the language is not supported. - */ - def sayNumber(locale: java.util.Locale): String = - { - val num = amount.divideAndRemainder(new BigDec("1")) - val result = try { - val integral = num(0).longValueExact() - val fraction = num(1).movePointRight(decimals).abs.longValue() - VerbaliseNumber.toWords(integral, locale.getLanguage()) + - (if (fraction != 0L) - " " + fraction.toString + "/" + Math.pow(10,decimals).toLong.toString - else "") - } catch { - case e: ArithmeticException => amount.toString + " " + Currency.getNameFor(currencyCode) - } - result - } - -} - -/** This exception is thrown if an arithmetic operation is attempted on - * two values with currencies that don't match. - */ -class MismatchedCurrencyException extends Exception - -/** This exception is thrown if a currency with an unknown ISO ISO 4217 currency - * code is created or requested. - */ -class UnknownCurrencyException extends Exception - -object Currency { - - @serializable - object RoundingMode extends Enumeration { - type RoundingMode = Value - -/** Rounding mode to round away from zero. Always increments the digit prior to - * a nonzero discarded fraction. Note that this rounding mode never decreases - * the magnitude of the calculated value. - */ - val ROUND_UP = Value; - -/** Rounding mode to round towards zero. Never increments the digit prior to a - * discarded fraction (i.e., truncates). Note that this rounding mode never - * increases the magnitude of the calculated value. - */ - val ROUND_DOWN = Value; - -/** Rounding mode to round towards positive infinity. If the Currency - * value is positive, behaves as for ROUND_UP; if negative, behaves as for - * ROUND_DOWN. Note that this rounding mode never decreases the calculated value. - */ - val ROUND_CEILING = Value; - -/** Rounding mode to round towards negative infinity. If the Currency - * value is positive, behave as for ROUND_DOWN; if negative, behave as for - * ROUND_UP. Note that this rounding mode never increases the calculated value. - */ - val ROUND_FLOOR = Value; - -/** Rounding mode to round towards "nearest neighbor" unless both neighbors - * are equidistant, in which case round up. Behaves as for ROUND_UP if the - * discarded fraction is >= 0.5; otherwise, behaves as for ROUND_DOWN. Note - * that this is the rounding mode that most of us were taught in grade school. - *

Also known as common rounding.

- */ - val ROUND_HALF_UP = Value; - -/** Rounding mode to round towards "nearest neighbor" unless both neighbors are - * equidistant, in which case round down. Behaves as for ROUND_UP if the discarded - * fraction is > 0.5; otherwise, behaves as for ROUND_DOWN. - */ - val ROUND_HALF_DOWN = Value; - -/** Rounding mode to round towards the "nearest neighbor" unless both neighbors - * are equidistant, in which case, round towards the even neighbor. Behaves as - * for ROUND_HALF_UP if the digit to the left of the discarded fraction is odd; - * behaves as for ROUND_HALF_DOWN if it's even. Note that this is the rounding - * mode that minimizes cumulative error when applied repeatedly over a sequence - * of calculations.

Also known as Banker's Rounding.

- */ - val ROUND_HALF_EVEN = Value; - - /** Rounding mode to assert that the requested operation has an exact result, - * hence no rounding is necessary. If this rounding mode is specified on an - * operation that yields an inexact result, an ArithmeticException is thrown. - */ - val ROUND_UNNECESSARY = Value; - } - - import Currency.RoundingMode._ - -/* ----- CURRENCY DATA ----- */ - - private val currencies = Map( - "AED" -> ("", 784, 2, "Fils", "UAE Dirham", "AE"), - "AFN" -> ("", 971, 2, "Pul", "Afghani", "AF"), - "ALL" -> ("L", 8, 2, "Qintar", "Lek", "AL"), - "AMD" -> ("դր", 51, 0, "Luma", "Armenian Dram", "AM"), - "ANG" -> ("ƒ", 532, 2, "Cent", "Netherlands Antillean Guilder", "AN"), - "AOA" -> ("Kz", 973, 1, "Cêntimo", "Kwanza", "AO"), - "ARS" -> ("$", 32, 2, "Centavo", "Argentine Peso", "AR"), - "AUD" -> ("$", 36, 2, "Cent", "Australian Dollar", "AU"), - "AWG" -> ("ƒ", 533, 2, "Cent", "Aruban Florin", "AW"), - "AZN" -> ("", 944, 2, "Qəpik", "Azerbaijanian Manat", "AZ"), - "BAM" -> ("КМ", 977, 2, "Fening", "Convertible Marks", "BA"), - "BBD" -> ("$", 52, 2, "Cent", "Barbados Dollar", "BB"), - "BDT" -> ("৳", 50, 2, "Paisa", "Bangladeshi Taka", "BD"), - "BGN" -> ("лв", 975, 2, "Stotinka", "Bulgarian Lev", "BG"), - "BHD" -> ("", 48, 3, "Fils", "Bahraini Dinar", "BH"), - "BIF" -> ("Fr", 108, 0, "Centime", "Burundian Franc", "BI"), - "BMD" -> ("$", 60, 2, "Cent", "Bermuda Dollar", "BM"), - "BND" -> ("$", 96, 2, "Sen", "Brunei Dollar", "BN"), - "BOB" -> ("Bs.", 68, 2, "Centavo", "Boliviano", "BO"), - "BRL" -> ("R$", 986, 2, "Centavo", "Brazilian Real", "BR"), - "BSD" -> ("$", 44, 2, "Cent", "Bahamian Dollar", "BS"), - "BTN" -> ("", 64, 2, "Chertrum", "Ngultrum", "BT"), - "BWP" -> ("P", 72, 2, "Thebe", "Pula", "BW"), - "BYR" -> ("Br", 974, 0, "Kapyeyka", "Belarussian Ruble", "BY"), - "BZD" -> ("$", 84, 2, "Cent", "Belize Dollar", "BZ"), - "CAD" -> ("$", 124, 2, "Cent", "Canadian Dollar", "CA"), - "CDF" -> ("Fr", 976, 2, "Centime", "Franc Congolais", "CD"), - "CHF" -> ("Fr", 756, 2, "Rappen", "Swiss Franc", "CH"), - "CLP" -> ("$", 152, 0, "Centavo", "Chilean Peso", "CL"), - "CNY" -> ("¥", 156, 1, "Fen", "Yuan", "CN"), - "COP" -> ("$", 170, 0, "Centavo", "Colombian Peso", "CO"), - "CRC" -> ("₡", 188, 2, "Céntimo", "Costa Rican Colon", "CR"), - "CUP" -> ("$", 192, 2, "Centavo", "Cuban Peso", "CU"), - "CVE" -> ("Esc", 132, 2, "Centavo", "Cape Verde Escudo", "CV"), - "CZK" -> ("Kč", 203, 2, "Haléř", "Czech Koruna", "CZ"), - "DJF" -> ("Fr", 262, 0, "Centime", "Djibouti Franc", "DJ"), - "DKK" -> ("kr", 208, 2, "Øre", "Danish Krone", "DK"), - "DOP" -> ("$", 214, 2, "Centavo", "Dominican Peso", "DO"), - "DZD" -> ("", 12, 2, "Centime", "Algerian Dinar", "DZ"), - "EEK" -> ("KR", 233, 2, "Sent", "Kroon", "EE"), - "EGP" -> ("£", 818, 2, "Piastre", "Egyptian Pound", "EG"), - "ERN" -> ("Nfk", 232, 2, "Cent", "Nakfa", "ER"), - "ETB" -> ("", 230, 2, "Santim", "Ethiopian Birr", "ET"), - "EUR" -> ("€", 978, 2, "Cent", "Euro", "AT,BE,CY,ES,FI,FR,DE,GR,IE,IT,LU,MT,NL,PT,SI,SK"), - "FJD" -> ("$", 242, 2, "Cent", "Fiji Dollar", "FJ"), - "FKP" -> ("£", 238, 2, "Penny", "Falkland Islands Pound", "FK"), - "GBP" -> ("£", 826, 2, "Penny", "Pound Sterling", "UK"), - "GEL" -> ("ლ", 981, 2, "Tetri", "Lari", "GE"), - "GHS" -> ("₵", 936, 2, "Pesewa", "Cedi", "GH"), - "GIP" -> ("£", 292, 2, "Penny", "Gibraltar Pound", "GI"), - "GMD" -> ("D", 270, 2, "Butut", "Dalasi", "GM"), - "GNF" -> ("Fr", 324, 0, "Centime", "Guinea Franc", "GQ"), - "GTQ" -> ("Q", 320, 2, "Centavo", "Quetzal", "GT"), - "GYD" -> ("$", 328, 2, "Cent", "Guyana Dollar", "GY"), - "HKD" -> ("$", 344, 1, "cent", "Hong Kong Dollar", "HK"), - "HNL" -> ("L", 340, 2, "Centavo", "Lempira", "HN"), - "HRK" -> ("kn", 191, 2, "Lipa", "Croatian Kuna", "HR"), - "HTG" -> ("G", 332, 2, "Centime", "Haiti Gourde", "HT"), - "HUF" -> ("Ft", 348, 0, "Penny", "Fillér", "HU"), - "IDR" -> ("Rp", 360, 0, "Sen", "Rupiah", "ID"), - "ILS" -> ("₪", 376, 2, "Agora", "Israeli New Sheqel", "IL"), - "INR" -> ("₨", 356, 2, "Penny", "Paisa", "IN"), - "IQD" -> ("", 368, 0, "Fils", "Iraqi Dinar", "IQ"), - "IRR" -> ("", 364, 0, "Dinar", "Iranian Rial", "IR"), - "ISK" -> ("kr", 352, 0, "Eyrir", "Iceland Krona", "IS"), - "JMD" -> ("$", 388, 2, "Cent", "Jamaican Dollar", "JM"), - "JOD" -> ("", 400, 3, "Piastre", "Jordanian Dinar", "JO"), - "JPY" -> ("¥", 392, 0, "Sen", "Japanese Yen", "JP"), - "KES" -> ("Sh", 404, 2, "Cent", "Kenyan Shilling", "KE"), - "KGS" -> ("", 417, 2, "Tyiyn", "Som", "KG"), - "KHR" -> ("", 116, 0, "Sen", "Riel", "KH"), - "KMF" -> ("Fr", 174, 0, "Centime", "Comoro Franc", "KM"), - "KPW" -> ("₩", 408, 0, "Chŏn", "North Korean Won", "KP"), - "KRW" -> ("₩", 410, 0, "Jeon", "South Korean Won", "KR"), - "KWD" -> ("", 414, 3, "Fils", "Kuwaiti Dinar", "KW"), - "KYD" -> ("$", 136, 2, "Cent", "Cayman Islands Dollar", "KY"), - "KZT" -> ("〒", 398, 2, "Tiyn", "Tenge", "KZ"), - "LAK" -> ("₭", 418, 0, "Att", "Kip", "LA"), - "LBP" -> ("", 422, 0, "Piastre", "Lebanese Pound", "LB"), - "LKR" -> ("Rs", 144, 2, "Cent", "Sri Lanka Rupee", "LK"), - "LRD" -> ("$", 430, 2, "Cent", "Liberian Dollar", "LR"), - "LSL" -> ("L", 426, 2, "Sente", "Lesotho Loti", "LS"), - "LTL" -> ("Lt", 440, 2, "Centas", "Lithuanian Litas", "LT"), - "LVL" -> ("Ls", 428, 2, "Santīms", "Latvian Lats", "LV"), - "LYD" -> ("", 434, 3, "Dirham", "Libyan Dinar", "LY"), - "MAD" -> ("", 504, 2, "Centime", "Moroccan Dirham", "MA"), - "MDL" -> ("L", 498, 2, "Ban", "Moldovan Leu", "MD"), - "MGA" -> ("", 969, 1, "Iraimbilanja", "Malagasy Ariary", "MG"), - "MKD" -> ("ден", 807, 2, "Deni", "Denar", "MK"), - "MMK" -> ("K", 104, 0, "Pya", "Kyat", "MM"), - "MNT" -> ("₮", 496, 2, "Möngö", "Tugrik", "MN"), - "MOP" -> ("", 446, 1, "Penny", "Pataca", "MO"), - "MRO" -> ("P", 478, 1, "Avo", "Ouguiya", "MR"), - "MUR" -> ("₨", 480, 2, "Cent", "Mauritius Rupee", "MU"), - "MVR" -> ("", 462, 2, "Lari", "Rufiyaa", "MV"), - "MWK" -> ("MK", 454, 2, "Tambala", "Kwacha", "MW"), - "MXN" -> ("$", 484, 2, "Centavo", "Mexican Peso", "MX"), - "MYR" -> ("RM", 458, 2, "Sen", "Malaysian Ringgit", "MY"), - "MZN" -> ("MTn", 943, 2, "Centavo", "Metical", "MZ"), - "NAD" -> ("$", 516, 2, "Cent", "Namibian Dollar", "NA"), - "NGN" -> ("₦", 566, 2, "Kobo", "Naira", "NG"), - "NIO" -> ("C$", 558, 2, "Centavo", "Cordoba Oro", "NI"), - "NOK" -> ("kr", 578, 2, "Øre", "Norwegian Krone", "NO"), - "NPR" -> ("₨", 524, 2, "Paisa", "Nepalese Rupee", "NP"), - "NZD" -> ("$", 554, 2, "Cent", "New Zealand Dollar", "NZ"), - "OMR" -> ("", 512, 3, "Baisa", "Rial Omani", "OM"), - "PAB" -> ("B/.", 590, 2, "Centésimo", "Balboa", "PA"), - "PEN" -> ("S/.", 604, 2, "Céntimo", "Nuevo Sol", "PE"), - "PGK" -> ("K", 598, 2, "Toea", "Kina Papua", "PG"), - "PHP" -> ("₱", 608, 2, "Centavo", "Philippine Peso", "PH"), - "PKR" -> ("₨", 586, 2, "Paisa", "Pakistan Rupee", "PK"), - "PLN" -> ("zł", 985, 2, "Grosz", "Złoty", "PL"), - "PYG" -> ("₲", 600, 0, "Céntimo", "Guarani", "PY"), - "QAR" -> ("", 634, 2, "Dirham", "Qatari Rial", "QA"), - "RON" -> ("L", 946, 2, "Ban", "Romanian Leu", "RO"), - "RSD" -> ("din.", 941, 2, "Para", "Serbian Dinar", "RS"), - "RUB" -> ("р.", 643, 2, "Kopek", "Russian Rouble", "RU"), - "RWF" -> ("Fr", 646, 0, "Centime", "Rwanda Franc", "RW"), - "SAR" -> ("", 682, 2, "Hallallah", "Saudi Riyal", "SA"), - "SBD" -> ("$", 90, 2, "Cent", "Solomon Islands Dollar", "SB"), - "SCR" -> ("₨", 690, 2, "Cent", "Seychelles Rupee", "SC"), - "SDG" -> ("£", 938, 2, "Piastre", "Sudanese Pound", "SD"), - "SEK" -> ("kr", 752, 2, "Öre", "Swedish Krona", "SE"), - "SGD" -> ("$", 702, 2, "Cent", "Singapore Dollar", "SG"), - "SHP" -> ("£", 654, 2, "Penny", "Saint Helena Pound", "SH"), - "SLL" -> ("Le", 694, 0, "Cent", "Leone", "SL"), - "SOS" -> ("Sh", 706, 2, "Cent", "Somali Shilling", "SO"), - "SRD" -> ("$", 968, 2, "Cent", "Surinam Dollar", "SR"), - "STD" -> ("Db", 678, 0, "Cêntimo", "Dobra", "ST"), - "SYP" -> ("£", 760, 2, "Piastre", "Syrian Pound", "SY"), - "SZL" -> ("L", 748, 2, "Cent", "Lilangeni", "SZ"), - "THB" -> ("฿", 764, 2, "Satang", "Baht", "TH"), - "TJS" -> ("ЅМ", 972, 2, "Diram", "Somoni", "TJ"), - "TMM" -> ("m", 934, 2, "Tennesi", "Manat", "TM"), - "TND" -> ("", 788, 3, "Millime", "Tunisian Dinar", "TN"), - "TOP" -> ("T$", 776, 2, "Seniti", "Pa'anga", "TO"), - "TRY" -> ("₤", 949, 2, "kuruş", "Turkish Lira", "TR"), - "TTD" -> ("$", 780, 2, "Cent", "Trinidad and Tobago Dollar", "TT"), - "TWD" -> ("$", 901, 1, "Cent", "New Taiwan Dollar", "TW"), - "TZS" -> ("Sh", 834, 2, "Cent", "Tanzanian Shilling", "TZ"), - "UAH" -> ("₴", 980, 2, "Kopiyka", "Hryvnia", "UA"), - "UGX" -> ("Sh", 800, 0, "Cent", "Uganda Shilling", "UG"), - "USD" -> ("$", 840, 2, "Cent", "Dollar", "US"), - "UYU" -> ("$", 858, 2, "Centésimo", "Peso Uruguayo", "UY"), - "UZS" -> ("", 860, 2, "Tiyin", "Uzbekistan Som", "UZ"), - "VEF" -> ("Bs F", 937, 2, "Céntimo", "Venezuelan Bolívar", "VE"), - "VND" -> ("₫", 704, 0, "Hào", "Vietnamese Dồng", "VN"), - "VUV" -> ("Vt", 548, 0, "", "Vatu", "VU"), - "WST" -> ("T", 882, 2, "Sene", "Samoan Tala", "WS"), - "XAF" -> ("Fr", 950, 0, "Centime", "Central African CFA Franc", "CM,CF,CD,GQ,GA,TD"), - "XCD" -> ("$", 951, 2, "Cent", "East Caribbean Dollar", "AG,DM,GD,KN,LC,VC"), - "XOF" -> ("Fr", 952, 0, "Centime", "CFA Franc BCEAO", "BJ,BF,CI,GW,ML,NE,SN,TG"), - "XPF" -> ("Fr", 953, 0, "Centime", "CFP Franc", "PF"), - "YER" -> ("", 886, 0, "Fils", "Yemeni Rial", "YE"), - "ZAR" -> ("R", 710, 2, "Cent", "South African Rand", "ZA"), - "ZMK" -> ("ZK", 894, 0, "Ngwee", "Kwacha", "ZM"), - "ZWR" -> ("$", 932, 2, "Cent", "Zimbabwe Dollar", "ZW") - ) - -/* Verfies that the given currency code is in the currency list. - */ - private def checkCurrencyCode(currencyCode: String): String = - if (currencyCode.isEmpty) - "" - else if (currencies.contains(currencyCode)) - currencyCode - else - throw new UnknownCurrencyException - -/** Returns the currency symbol for the specified currency. - * For example, returns $ for USD, kr for Swedish Krona, Rs for Indian - * Rupees, etc. - * - * @param currencyCode ISO 4217 three-letter currency code. - * @return currency symbol as string or empty string. - * @throws UnknownCurrencyException if currencyCode - * is not valid. - */ - def getSymbolFor(currencyCode: String): String = - if (currencies.contains(currencyCode)) - currencies(currencyCode)._1 - else if (currencyCode.isEmpty) - "" - else - throw new UnknownCurrencyException - -/** Returns the ISO 4217 numeric code for the specified currency. - * - * @param currencyCode ISO 4217 three-letter currency code. - * @return ISO 4217 numeric currency code. - * @throws UnknownCurrencyException if currencyCode - * is not valid. - */ - def getNumericCodeFor(currencyCode: String): Int = - if (currencies.contains(currencyCode)) - currencies(currencyCode)._2 - else - throw new UnknownCurrencyException - -/** Returns the default number of fraction digits used with the specified currency. - * - * @param currencyCode ISO 4217 three-letter currency code. - * @return number of decimal places for this currency. - * @throws UnknownCurrencyException if currencyCode - * is not valid. - */ - def getDecimalsFor(currencyCode: String): Int = - if (currencies.contains(currencyCode)) - currencies(currencyCode)._3 - else if (currencyCode.isEmpty) - 2 - else - throw new UnknownCurrencyException - -/** Returns the English currency name for the fractional unit of the specified - * currency, e.g. Cent for Euro, Penny for Pound Sterling, - * etc. Always returns empty String for unknown currencies. - * - * @param currencyCode ISO 4217 three-letter currency code. - * @return name of the currency. - * @throws UnknownCurrencyException if currencyCode - * is not valid. - */ - def getFractNameFor(currencyCode: String): String = - if (currencies.contains(currencyCode)) - currencies(currencyCode)._4 - else if (currencyCode.isEmpty) - "" - else - throw new UnknownCurrencyException - -/** Returns the English currency name for the specified currency. - * - * @param currencyCode ISO 4217 three-letter currency code. - * @return name of the currency. - * @throws UnknownCurrencyException if currencyCode - * is not valid. - */ - def getNameFor(currencyCode: String): String = - if (currencies.contains(currencyCode)) - currencies(currencyCode)._5 - else if (currencyCode.isEmpty) - "" - else - throw new UnknownCurrencyException - -/** Returns one or more two-letter ISO 3166-1 country code(s) that indicate where - * the specified currency is in use. - * - * @param currencyCode ISO 4217 three-letter currency code. - * @return Array of String with one or more country code(s). - * @throws UnknownCurrencyException if currencyCode - * is not valid. - */ - def getCountriesFor(currencyCode: String): Array[String] = - if (currencies.contains(currencyCode)) - currencies(currencyCode)._6.split(",") - else - throw new UnknownCurrencyException - -/** Returns a Set containing all 3-letter ISO currency codes as - * Strings. - * - * @return all currency codes. - */ - def getAllCurrencies = currencies.keySet - -/* ----- FACTORY METHODS (String) ----- */ - -/** Constructs a Currency value from a numeric String value. - * - * @param amount specified amount as String value. - * @param currencyCode ISO 4217 three-letter currency code. - * @param decimals number of decimal places. - * @param roundingMode rounding mode to apply. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: String, currencyCode: String, decimals: Int, roundingMode: RoundingMode): Currency = - new Currency(new BigDec(amount), checkCurrencyCode(currencyCode), decimals, roundingMode) - -/** Constructs a Currency value from a numeric String value - * with default rounding mode (ROUND_HALF_UP). - * - * @param amount specified amount as String value. - * @param currencyCode ISO 4217 three-letter currency code. - * @param decimals number of decimal places. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: String, currencyCode: String, decimals: Int): Currency = - new Currency(new BigDec(amount), checkCurrencyCode(currencyCode), decimals, ROUND_HALF_UP) - -/** Constructs a Currency value from a numeric String value - * with default rounding mode (ROUND_HALF_UP) and default number of - * decimal places. The number of decimal places is determined by the designated - * currency (e.g. 2 for most currencies, 1 for Chinese Yuan, 0 for Colombian Peso, etc.) - * - * @param amount specified amount as String value. - * @param currencyCode ISO 4217 three-letter currency code. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: String, currencyCode: String): Currency = - new Currency(new BigDec(amount), checkCurrencyCode(currencyCode), getDecimalsFor(currencyCode), ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a numeric String value. - * - * @param amount specified amount as String value. - */ - def apply(amount: String): Currency = - new Currency(new BigDec(amount), "", getDecimalsFor(""), ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a numeric String value - * with the given number of decimal places. - * - * @param amount specified amount as String value. - * @param decimals number of decimal places. - */ - def apply(amount: String, decimals: Int): Currency = - new Currency(new BigDec(amount), "", decimals, ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a numeric String value - * with the given rounding mode. - * - * @param amount specified amount as String value. - * @param roundingMode rounding mode to apply. - */ - def apply(amount: String, roundingMode: RoundingMode): Currency = - new Currency(new BigDec(amount), "", getDecimalsFor(""), roundingMode) - -/** Constructs a non-specific Currency value from a numeric String value - * with the given number of decimal places and the given rounding mode. - * - * @param amount specified amount as String value. - * @param decimals number of decimal places. - * @param roundingMode rounding mode to apply. - */ - def apply(amount: String, decimals: Int, roundingMode: RoundingMode): Currency = - new Currency(new BigDec(amount), "", decimals, roundingMode) - -/* ----- FACTORY METHODS (Double) ----- */ - -/** Constructs a Currency value from a Double value. - * - * @param amount specified amount as Double value. - * @param currencyCode ISO 4217 three-letter currency code. - * @param decimals number of decimal places. - * @param roundingMode rounding mode to apply. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: Double, currencyCode: String, decimals: Int, roundingMode: RoundingMode): Currency = - new Currency(BigDec.valueOf(amount), checkCurrencyCode(currencyCode), decimals, roundingMode) - -/** Constructs a Currency value from a Double value - * with default rounding mode (ROUND_HALF_UP). - * - * @param amount specified amount as Double value. - * @param currencyCode ISO 4217 three-letter currency code. - * @param decimals number of decimal places. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: Double, currencyCode: String, decimals: Int): Currency = - new Currency(BigDec.valueOf(amount), checkCurrencyCode(currencyCode), decimals, ROUND_HALF_UP) - -/** Constructs a Currency value from a Double value - * with default rounding mode (ROUND_HALF_UP) and default number - * of decimal places. The number of decimal places is determined by the designated - * currency (e.g. 2 for most currencies, 1 for Chinese Yuan, 0 for Colombian Peso, etc.) - * - * @param amount specified amount as Double value. - * @param currencyCode ISO 4217 three-letter currency code. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: Double, currencyCode: String): Currency = - new Currency(BigDec.valueOf(amount), checkCurrencyCode(currencyCode), getDecimalsFor(currencyCode), ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a Double value. - * - * @param amount specified amount as Double value. - */ - def apply(amount: Double): Currency = - new Currency(BigDec.valueOf(amount), "", getDecimalsFor(""), ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a Double value - * with the given number of decimal places. - * - * @param amount specified amount as Double value. - * @param decimals number of decimal places. - */ - def apply(amount: Double, decimals: Int): Currency = - new Currency(BigDec.valueOf(amount), "", decimals, ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a Double value - * with the given rounding mode. - * - * @param amount specified amount as Double value. - * @param roundingMode rounding mode to apply. - */ - def apply(amount: Double, roundingMode: RoundingMode): Currency = - new Currency(BigDec.valueOf(amount), "", getDecimalsFor(""), roundingMode) - -/** Constructs a non-specific Currency value from a Double value - * with the given number of decimal places and the given rounding mode. - * - * @param amount specified amount as Double value. - * @param decimals number of decimal places. - * @param roundingMode rounding mode to apply. - */ - def apply(amount: Double, decimals: Int, roundingMode: RoundingMode): Currency = - new Currency(BigDec.valueOf(amount), "", decimals, roundingMode) - -/* ----- FACTORY METHODS (Long) ----- */ - -/** Constructs a Currency value from a Long value. - * - * @param amount specified amount as Long value. - * @param currencyCode ISO 4217 three-letter currency code. - * @param decimals number of decimal places. - * @param roundingMode rounding mode to apply. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: Long, currencyCode: String, decimals: Int, roundingMode: RoundingMode): Currency = - new Currency(BigDec.valueOf(amount), checkCurrencyCode(currencyCode), decimals, roundingMode) - -/** Constructs a Currency value from a Long value - * with default rounding mode (ROUND_HALF_UP). - * - * @param amount specified amount as Long value. - * @param currencyCode ISO 4217 three-letter currency code. - * @param decimals number of decimal places. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: Long, currencyCode: String, decimals: Int): Currency = - new Currency(BigDec.valueOf(amount), checkCurrencyCode(currencyCode), decimals, ROUND_HALF_UP) - -/** Constructs a Currency value from a Long value - * with default rounding mode (ROUND_HALF_UP) and default number of - * decimal places. The number of decimal places is determined by the designated - * currency (e.g. 2 for most currencies, 1 for Chinese Yuan, 0 for Colombian Peso, etc.) - * - * @param amount specified amount as Long value. - * @param currencyCode ISO 4217 three-letter currency code. - * @throws UnknownCurrencyException if currency code is not recognised. - */ - def apply(amount: Long, currencyCode: String): Currency = - new Currency(BigDec.valueOf(amount), checkCurrencyCode(currencyCode), getDecimalsFor(currencyCode), ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a Long value. - * - * @param amount specified amount as Long value. - */ - def apply(amount: Long): Currency = - new Currency(BigDec.valueOf(amount), "", getDecimalsFor(""), ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a Long value - * with the given number of decimal places. - * - * @param amount specified amount as Long value. - * @param decimals number of decimal places. - */ - def apply(amount: Long, decimals: Int): Currency = - new Currency(BigDec.valueOf(amount), "", decimals, ROUND_HALF_UP) - -/** Constructs a non-specific Currency value from a Long value - * with the given rounding mode. - * - * @param amount specified amount as Double value. - * @param roundingMode rounding mode to apply. - */ - def apply(amount: Long, roundingMode: RoundingMode): Currency = - new Currency(BigDec.valueOf(amount), "", getDecimalsFor(""), roundingMode) - -/** Constructs a non-specific Currency value from a Long value - * with the given number of decimal places and the given rounding mode. - * - * @param amount specified amount as Long value. - * @param decimals number of decimal places. - * @param roundingMode rounding mode to apply. - */ - def apply(amount: Long, decimals: Int, roundingMode: RoundingMode): Currency = - new Currency(BigDec.valueOf(amount), "", decimals, roundingMode) - -}