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

com.ibm.icu.impl.ICUCurrencyDisplayInfoProvider Maven / Gradle / Ivy

There is a newer version: 2.12.15
Show newest version
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2009-2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
package com.ibm.icu.impl;

import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.TreeMap;

import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo;
import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfoProvider;
import com.ibm.icu.impl.CurrencyData.CurrencyFormatInfo;
import com.ibm.icu.impl.CurrencyData.CurrencySpacingInfo;
import com.ibm.icu.impl.ICUResourceBundle.OpenType;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;

public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvider {
    public ICUCurrencyDisplayInfoProvider() {
    }

    @Override
    public CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback) {
        ICUResourceBundle rb;
        if (withFallback) {
            rb = ICUResourceBundle.getBundleInstance(
                    ICUData.ICU_CURR_BASE_NAME, locale, OpenType.LOCALE_DEFAULT_ROOT);
        } else {
            try {
                rb = ICUResourceBundle.getBundleInstance(
                        ICUData.ICU_CURR_BASE_NAME, locale, OpenType.LOCALE_ONLY);
            } catch (MissingResourceException e) {
                return null;
            }
        }
        return new ICUCurrencyDisplayInfo(rb, withFallback);
    }

    @Override
    public boolean hasData() {
        return true;
    }

    static class ICUCurrencyDisplayInfo extends CurrencyDisplayInfo {
        private final boolean fallback;
        private final ICUResourceBundle rb;
        private final ICUResourceBundle currencies;
        private final ICUResourceBundle plurals;
        private SoftReference> _symbolMapRef;
        private SoftReference> _nameMapRef;

        public ICUCurrencyDisplayInfo(ICUResourceBundle rb, boolean fallback) {
            this.fallback = fallback;
            this.rb = rb;
            this.currencies = rb.findTopLevel("Currencies");
            this.plurals = rb.findTopLevel("CurrencyPlurals");
       }

        @Override
        public ULocale getULocale() {
            return rb.getULocale();
        }

        @Override
        public String getName(String isoCode) {
            return getName(isoCode, false);
        }

        @Override
        public String getSymbol(String isoCode) {
            return getName(isoCode, true);
        }

        private String getName(String isoCode, boolean symbolName) {
            if (currencies != null) {
                ICUResourceBundle result = currencies.findWithFallback(isoCode);
                if (result != null) {
                    if (!fallback && !rb.isRoot() && result.isRoot()) {
                        return null;
                    }
                    return result.getString(symbolName ? 0 : 1);
                }
            }

            return fallback ? isoCode : null;
        }

        @Override
        public String getPluralName(String isoCode, String pluralKey ) {
            // See http://unicode.org/reports/tr35/#Currencies, especially the fallback rule.
            if (plurals != null) {
                ICUResourceBundle pluralsBundle = plurals.findWithFallback(isoCode);
                if (pluralsBundle != null) {
                    String pluralName = pluralsBundle.findStringWithFallback(pluralKey);
                    if (pluralName == null) {
                        if (!fallback) {
                            return null;
                        }
                        pluralName = pluralsBundle.findStringWithFallback("other");
                        if (pluralName == null) {
                            return getName(isoCode);
                        }
                    }
                    return pluralName;
                }
            }

            return fallback ? getName(isoCode) : null;
        }

        @Override
        public Map symbolMap() {
            Map map = _symbolMapRef == null ? null : _symbolMapRef.get();
            if (map == null) {
                map = _createSymbolMap();
                // atomic and idempotent
                _symbolMapRef = new SoftReference>(map);
            }
            return map;
        }

        @Override
        public Map nameMap() {
            Map map = _nameMapRef == null ? null : _nameMapRef.get();
            if (map == null) {
                map = _createNameMap();
                // atomic and idempotent
                _nameMapRef = new SoftReference>(map);
            }
            return map;
        }

        @Override
        public Map getUnitPatterns() {
            Map result = new HashMap();

            ULocale locale = rb.getULocale();
            for (;locale != null; locale = locale.getFallback()) {
                ICUResourceBundle r = (ICUResourceBundle) UResourceBundle.getBundleInstance(
                        ICUData.ICU_CURR_BASE_NAME, locale);
                if (r == null) {
                    continue;
                }
                ICUResourceBundle cr = r.findWithFallback("CurrencyUnitPatterns");
                if (cr == null) {
                    continue;
                }
                for (int index = 0, size = cr.getSize(); index < size; ++index) {
                    ICUResourceBundle b = (ICUResourceBundle) cr.get(index);
                    String key = b.getKey();
                    if (result.containsKey(key)) {
                        continue;
                    }
                    result.put(key, b.getString());
                }
            }

            // Default result is the empty map. Callers who require a pattern will have to
            // supply a default.
            return Collections.unmodifiableMap(result);
        }

        @Override
        public CurrencyFormatInfo getFormatInfo(String isoCode) {
            ICUResourceBundle crb = currencies.findWithFallback(isoCode);
            if (crb != null && crb.getSize() > 2) {
                crb = crb.at(2);
                if (crb != null) {
                  String pattern = crb.getString(0);
                  String separator = crb.getString(1);
                  String groupingSeparator = crb.getString(2);
                  return new CurrencyFormatInfo(pattern, separator, groupingSeparator);
                }
            }
            return null;
        }

        @Override
        public CurrencySpacingInfo getSpacingInfo() {
            SpacingInfoSink sink = new SpacingInfoSink();
            rb.getAllItemsWithFallback("currencySpacing", sink);
            return sink.getSpacingInfo(fallback);
        }

        private final class SpacingInfoSink extends UResource.Sink {
            CurrencySpacingInfo spacingInfo = new CurrencySpacingInfo();
            boolean hasBeforeCurrency = false;
            boolean hasAfterCurrency = false;

            /*
             *  currencySpacing{
             *      afterCurrency{
             *          currencyMatch{"[:^S:]"}
             *          insertBetween{" "}
             *          surroundingMatch{"[:digit:]"}
             *      }
             *      beforeCurrency{
             *          currencyMatch{"[:^S:]"}
             *          insertBetween{" "}
             *          surroundingMatch{"[:digit:]"}
             *      }
             *  }
             */
            @Override
            public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
                UResource.Table spacingTypesTable = value.getTable();
                for (int i = 0; spacingTypesTable.getKeyAndValue(i, key, value); ++i) {
                    CurrencySpacingInfo.SpacingType type;
                    if (key.contentEquals("beforeCurrency")) {
                        type = CurrencySpacingInfo.SpacingType.BEFORE;
                        hasBeforeCurrency = true;
                    } else if (key.contentEquals("afterCurrency")) {
                        type = CurrencySpacingInfo.SpacingType.AFTER;
                        hasAfterCurrency = true;
                    } else {
                        continue;
                    }

                    UResource.Table patternsTable = value.getTable();
                    for (int j = 0; patternsTable.getKeyAndValue(j, key, value); ++j) {
                        CurrencySpacingInfo.SpacingPattern pattern;
                        if (key.contentEquals("currencyMatch")) {
                            pattern = CurrencySpacingInfo.SpacingPattern.CURRENCY_MATCH;
                        } else if (key.contentEquals("surroundingMatch")) {
                            pattern = CurrencySpacingInfo.SpacingPattern.SURROUNDING_MATCH;
                        } else if (key.contentEquals("insertBetween")) {
                            pattern = CurrencySpacingInfo.SpacingPattern.INSERT_BETWEEN;
                        } else {
                            continue;
                        }

                        spacingInfo.setSymbolIfNull(type, pattern, value.getString());
                    }
                }
            }

            CurrencySpacingInfo getSpacingInfo(boolean fallback) {
                if (hasBeforeCurrency && hasAfterCurrency) {
                    return spacingInfo;
                } else if (fallback) {
                    return CurrencySpacingInfo.DEFAULT;
                } else {
                    return null;
                }
            }
        }

        private Map _createSymbolMap() {
            Map result = new HashMap();

            for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) {
                ICUResourceBundle bundle = (ICUResourceBundle)
                    UResourceBundle.getBundleInstance(ICUData.ICU_CURR_BASE_NAME, locale);
                ICUResourceBundle curr = bundle.findTopLevel("Currencies");
                if (curr == null) {
                    continue;
                }
                for (int i = 0; i < curr.getSize(); ++i) {
                    ICUResourceBundle item = curr.at(i);
                    String isoCode = item.getKey();
                    if (!result.containsKey(isoCode)) {
                        // put the code itself
                        result.put(isoCode, isoCode);
                        // 0 == symbol element
                        String symbol = item.getString(0);
                        result.put(symbol, isoCode);
                    }
                }
            }

            return Collections.unmodifiableMap(result);
        }

        private Map _createNameMap() {
            // ignore case variants
            Map result = new TreeMap(String.CASE_INSENSITIVE_ORDER);

            Set visited = new HashSet();
            Map> visitedPlurals = new HashMap>();
            for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) {
                ICUResourceBundle bundle = (ICUResourceBundle)
                    UResourceBundle.getBundleInstance(ICUData.ICU_CURR_BASE_NAME, locale);
                ICUResourceBundle curr = bundle.findTopLevel("Currencies");
                if (curr != null) {
                    for (int i = 0; i < curr.getSize(); ++i) {
                        ICUResourceBundle item = curr.at(i);
                        String isoCode = item.getKey();
                        if (!visited.contains(isoCode)) {
                            visited.add(isoCode);
                            // 1 == name element
                            String name = item.getString(1);
                            result.put(name, isoCode);
                        }
                    }
                }

                ICUResourceBundle plurals = bundle.findTopLevel("CurrencyPlurals");
                if (plurals != null) {
                    for (int i = 0; i < plurals.getSize(); ++i) {
                        ICUResourceBundle item = plurals.at(i);
                        String isoCode = item.getKey();
                        Set pluralSet = visitedPlurals.get(isoCode);
                        if (pluralSet == null) {
                            pluralSet = new HashSet();
                            visitedPlurals.put(isoCode, pluralSet);
                        }
                        for (int j = 0; j < item.getSize(); ++j) {
                            ICUResourceBundle plural = item.at(j);
                            String pluralType = plural.getKey();
                            if (!pluralSet.contains(pluralType)) {
                                String pluralName = plural.getString();
                                result.put(pluralName, isoCode);
                                pluralSet.add(pluralType);
                            }
                        }
                    }
                }
            }

            return Collections.unmodifiableMap(result);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy