OceanusDecimalLocale.java
/*******************************************************************************
* Oceanus: Java Utilities
* Copyright 2012,2025 Tony Washer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package net.sourceforge.joceanus.oceanus.decimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Currency;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* Locale constants.
*/
public class OceanusDecimalLocale {
/**
* The dollar.
*/
private static final String DOLLAR = "$";
/**
* The pound.
*/
private static final String POUND = "£";
/**
* The locale.
*/
private final Locale theLocale;
/**
* The currencies map.
*/
private final Map<String, Currency> theCurrencyMap;
/**
* The currency symbols map.
*/
private final Map<String, String> theSymbolMap;
/**
* The grouping size.
*/
private int theGroupingSize;
/**
* The grouping separator.
*/
private final String theGrouping;
/**
* The minus sign.
*/
private final char theMinusSign;
/**
* The perCent symbol.
*/
private final char thePerCent;
/**
* The perMille symbol.
*/
private final char thePerMille;
/**
* The decimal separator.
*/
private final String theDecimal;
/**
* The money decimal separator.
*/
private final String theMoneyDecimal;
/**
* The default currency.
*/
private final Currency theCurrency;
/**
* Constructor.
*/
protected OceanusDecimalLocale() {
/* Use default locale */
this(Locale.getDefault());
}
/**
* Constructor.
* @param pLocale the locale
*/
protected OceanusDecimalLocale(final Locale pLocale) {
/* Store the locale */
theLocale = pLocale;
/* Create currency maps */
theCurrencyMap = new HashMap<>();
theSymbolMap = new HashMap<>();
/* Access decimal formats */
final DecimalFormatSymbols mySymbols = DecimalFormatSymbols.getInstance(theLocale);
final DecimalFormat myFormat = (DecimalFormat) NumberFormat.getInstance(pLocale);
theGroupingSize = myFormat.getGroupingSize();
/* Access various interesting formats */
theMinusSign = mySymbols.getMinusSign();
thePerCent = mySymbols.getPercent();
thePerMille = mySymbols.getPerMill();
theGrouping = Character.toString(mySymbols.getGroupingSeparator());
theDecimal = Character.toString(mySymbols.getDecimalSeparator());
theMoneyDecimal = Character.toString(mySymbols.getMonetaryDecimalSeparator());
/* Access the default currency */
theCurrency = mySymbols.getCurrency();
final String myCurrSymbol = theCurrency.getSymbol(theLocale);
declareSymbol(myCurrSymbol, theCurrency);
/* Declare simplified USD/GBP if possible */
if (!DOLLAR.equals(myCurrSymbol)) {
declareSymbol(DOLLAR, Currency.getInstance(Locale.US));
}
if (!POUND.equals(myCurrSymbol)) {
declareSymbol(POUND, Currency.getInstance(Locale.UK));
}
}
/**
* Obtain the grouping size.
* @return the size
*/
protected int getGroupingSize() {
return theGroupingSize;
}
/**
* Obtain the grouping string.
* @return the string
*/
protected String getGrouping() {
return theGrouping;
}
/**
* Obtain the minus sign.
* @return the sign
*/
protected char getMinusSign() {
return theMinusSign;
}
/**
* Obtain the perCent sign.
* @return the sign
*/
protected char getPerCent() {
return thePerCent;
}
/**
* Obtain the perMille sign.
* @return the sign
*/
protected char getPerMille() {
return thePerMille;
}
/**
* Obtain the decimal string.
* @return the string
*/
protected String getDecimal() {
return theDecimal;
}
/**
* Obtain the grouping string.
* @return the string
*/
protected String getMoneyDecimal() {
return theMoneyDecimal;
}
/**
* Obtain the default currency.
* @return the currency
*/
protected Currency getDefaultCurrency() {
return theCurrency;
}
/**
* Parse currency symbol.
* @param pSymbol the symbol
* @return the currency
* @throws IllegalArgumentException on invalid currency
*/
protected Currency parseCurrencySymbol(final String pSymbol) {
/* Look for the currency in the map */
Currency myCurrency = theCurrencyMap.get(pSymbol);
/* If this is a new currency */
if (myCurrency == null) {
/* Loop through all the currencies */
for (Currency myCurr : Currency.getAvailableCurrencies()) {
/* If the symbol matches */
if (pSymbol.equals(myCurr.getSymbol(theLocale))) {
/* Record currency and break the loop */
myCurrency = myCurr;
declareSymbol(pSymbol, myCurrency);
break;
}
}
/* If we did not find a currency */
if (myCurrency == null) {
/* Reject the currency */
throw new IllegalArgumentException("Invalid currency: "
+ pSymbol);
}
}
/* Return the currency */
return myCurrency;
}
/**
* Declare symbol.
* @param pSymbol the symbol
* @param pCurrency the currency
*/
private void declareSymbol(final String pSymbol,
final Currency pCurrency) {
/* Store in currency map */
theCurrencyMap.put(pSymbol, pCurrency);
/* Store symbol if not already declared */
final String myCode = pCurrency.getCurrencyCode();
theSymbolMap.computeIfAbsent(myCode, c -> pSymbol);
}
/**
* Get currency symbol.
* @param pCurrency the currency
* @return the symbol
*/
protected String getSymbol(final Currency pCurrency) {
/* Look for the currency in the map */
final String mySymbol = theSymbolMap.get(pCurrency.getCurrencyCode());
return mySymbol == null
? pCurrency.getSymbol(theLocale)
: mySymbol;
}
}