001/**
002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016package org.javamoney.moneta.internal;
017
018import javax.money.CurrencyQuery;
019import javax.money.CurrencyUnit;
020import javax.money.spi.CurrencyProviderSpi;
021import java.time.LocalDate;
022import java.time.LocalDateTime;
023import java.util.*;
024import java.util.concurrent.ConcurrentHashMap;
025
026/**
027 * This class provides a programmatic singleton for globally registering new {@link java.util.Currency}  into the
028 * {@link javax.money.Monetary} singleton either by currency code, locale, or both.
029 */
030public class ConfigurableCurrencyUnitProvider implements CurrencyProviderSpi {
031    /**
032     * The currency units, identified by currency code.
033     */
034    private static final Map<String, CurrencyUnit> CURRENCY_UNITS = new ConcurrentHashMap<>();
035    /**
036     * The currency units identified by Locale.
037     */
038    private static final Map<Locale, CurrencyUnit> CURRENCY_UNITS_BY_LOCALE = new ConcurrentHashMap<>();
039
040
041    /**
042     * Return a {@link CurrencyUnit} instances matching the given
043     * {@link javax.money.CurrencyContext}.
044     *
045     * @param currencyQuery the {@link javax.money.CurrencyQuery} containing the parameters determining the query. not null.
046     * @return the corresponding {@link CurrencyUnit}, or null, if no such unit
047     * is provided by this provider.
048     */
049    public Set<CurrencyUnit> getCurrencies(CurrencyQuery currencyQuery) {
050        Set<CurrencyUnit> result = new HashSet<>(CURRENCY_UNITS.size());
051        if (currencyQuery.get(LocalDateTime.class) != null || currencyQuery.get(LocalDate.class) != null) {
052            return Collections.emptySet();
053        }
054        if (!currencyQuery.getCurrencyCodes().isEmpty()) {
055            for (String code : currencyQuery.getCurrencyCodes()) {
056                CurrencyUnit cu = CURRENCY_UNITS.get(code);
057                if (cu != null) {
058                    result.add(cu);
059                }
060            }
061            return result;
062        }
063        if (!currencyQuery.getCountries().isEmpty()) {
064            for (Locale locale : currencyQuery.getCountries()) {
065                CurrencyUnit cu = CURRENCY_UNITS_BY_LOCALE.get(locale);
066                if (cu != null) {
067                    result.add(cu);
068                }
069            }
070            return result;
071        }
072        result.addAll(CURRENCY_UNITS.values());
073        return result;
074    }
075
076    /**
077     * Registers a bew currency unit under its currency code.
078     *
079     * @param currencyUnit the new currency to be registered, not null.
080     * @return any unit instance registered previously by this instance, or null.
081     */
082    public static CurrencyUnit registerCurrencyUnit(CurrencyUnit currencyUnit) {
083        Objects.requireNonNull(currencyUnit);
084        return ConfigurableCurrencyUnitProvider.CURRENCY_UNITS.put(currencyUnit.getCurrencyCode(), currencyUnit);
085    }
086
087    /**
088     * Registers a bew currency unit under the given Locale.
089     *
090     * @param currencyUnit the new currency to be registered, not null.
091     * @param locale       the Locale, not null.
092     * @return any unit instance registered previously by this instance, or null.
093     */
094    public static CurrencyUnit registerCurrencyUnit(CurrencyUnit currencyUnit, Locale locale) {
095        Objects.requireNonNull(locale);
096        Objects.requireNonNull(currencyUnit);
097        return ConfigurableCurrencyUnitProvider.CURRENCY_UNITS_BY_LOCALE.put(locale, currencyUnit);
098    }
099
100    /**
101     * Removes a CurrencyUnit.
102     *
103     * @param currencyCode the currency code, not null.
104     * @return any unit instance removed, or null.
105     */
106    public static CurrencyUnit removeCurrencyUnit(String currencyCode) {
107        Objects.requireNonNull(currencyCode);
108        return ConfigurableCurrencyUnitProvider.CURRENCY_UNITS.remove(currencyCode);
109    }
110
111    /**
112     * Removes a CurrencyUnit.
113     *
114     * @param locale the Locale, not null.
115     * @return any unit instance removed, or null.
116     */
117    public static CurrencyUnit removeCurrencyUnit(Locale locale) {
118        Objects.requireNonNull(locale);
119        return ConfigurableCurrencyUnitProvider.CURRENCY_UNITS_BY_LOCALE.remove(locale);
120    }
121
122    /*
123     * (non-Javadoc)
124     *
125     * @see java.lang.Object#toString()
126     */
127    @Override
128    public String toString() {
129        return "ConfigurableCurrencyUnitProvider [CURRENCY_UNITS=" + CURRENCY_UNITS + ", CURRENCY_UNITS_BY_LOCALE=" +
130                CURRENCY_UNITS_BY_LOCALE + ']';
131    }
132
133}