All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java.util.Currency.scala Maven / Gradle / Ivy

package java.util

import scala.collection.{ Map => SMap, Set => SSet }
import locales.cldr.{ CurrencyDataFractionsInfo, CurrencyType }
import locales.LocalesDb
import scala.jdk.CollectionConverters._

object Currency {
  private val countryCodeToCurrencyCodeMap: SMap[String, String] =
    LocalesDb.currencydata.regions.map { r =>
      r.countryCode -> r.currencies
        .find(_.to.isEmpty)
        .orElse(r.currencies.headOption)
        .map(_.currencyCode)
        .get
    }.toMap

  private val all: SSet[Currency] = LocalesDb.currencydata.currencyTypes.map {
    (currencyType: CurrencyType) =>
      val fractions: CurrencyDataFractionsInfo =
        LocalesDb.currencydata.fractions
          .find(_.currencyCode == currencyType.currencyCode)
          .orElse(LocalesDb.currencydata.fractions.find(_.currencyCode == "DEFAULT"))
          .get

      val numericCode: Int =
        LocalesDb.currencydata.numericCodes
          .find(_.currencyCode == currencyType.currencyCode)
          .map(_.numericCode)
          .getOrElse(0)

      Currency(
        currencyType.currencyCode,
        numericCode,
        fractions.digits,
        currencyType.currencyName,
        None
      )
  }.toSet

  private val currencyCodeMap: SMap[String, Currency] =
    all.toSeq.groupBy(_.getCurrencyCode()).map {
      case (currencyCode: String, matches: Seq[Currency]) => currencyCode -> matches.head
    }

  def getAvailableCurrencies(): java.util.Set[Currency] = all.asJava

  // NullPointerException - if locale or its country code is null
  // IllegalArgumentException - if the country of the given locale is not a supported ISO 3166 country code.
  def getInstance(locale: Locale): Currency = {
    if (locale.getCountry() == null || locale.getCountry().isEmpty) throw new NullPointerException

    countryCodeToCurrencyCodeMap
      .get(locale.getCountry())
      .flatMap(currencyCodeMap.get)
      .getOrElse(
        throw new IllegalArgumentException(s"No currency available for ${locale.toLanguageTag()}")
      )
  }

  def getInstance(currencyCode: String): Currency = currencyCodeMap(currencyCode)
}

final case class Currency private (
  currencyCode:   String,
  numericCode:    Int,
  fractionDigits: Int,
  defaultName:    String,
  currencyLocale: Option[Locale]
) {

  def defaultLocale: Locale = currencyLocale.getOrElse(Locale.getDefault())

  // Gets the ISO 4217 currency code of this currency.
  def getCurrencyCode(): String = currencyCode

  // Gets the default number of fraction digits used with this currency.
  def getDefaultFractionDigits(): Int = fractionDigits

  // Gets the name that is suitable for displaying this currency for the default DISPLAY locale.
  def getDisplayName(): String = getDisplayName(defaultLocale)

  // Gets the name that is suitable for displaying this currency for the specified locale.
  def getDisplayName(locale: Locale): String =
    LocalesDb
      .ldml(locale)
      .flatMap { ldml =>
        ldml.getNumberCurrencyDescription(currencyCode).find(_.count.isEmpty).map(_.name)
      }
      .getOrElse(currencyCode)

  // Returns the ISO 4217 numeric code of this currency.
  def getNumericCode(): Int = numericCode

  // Gets the symbol of this currency for the default DISPLAY locale.
  def getSymbol(): String = getSymbol(defaultLocale)

  // Gets the symbol of this currency for the specified locale.
  def getSymbol(locale: Locale): String =
    LocalesDb
      .ldml(locale)
      .flatMap { ldml =>
        val symbols = ldml.getNumberCurrencySymbol(currencyCode)

        // TODO: might need a more sophisticated symbol-matcher
        // The tests from the JVM indicate we prefer the "wide" over "narrow" symbol

        symbols
          .find(_.alt.isEmpty)
          .orElse(symbols.find(_.alt.exists(_ == "narrow")))
          .map(_.symbol)
      }
      .getOrElse(currencyCode)

  // Returns the ISO 4217 currency code of this currency.
  override def toString(): String = currencyCode
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy