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.util.*;
022import java.util.concurrent.ConcurrentHashMap;
023
024/**
025 * This class provides a programmatic singleton for globally registering new {@link java.util.Currency}  into the
026 * {@link javax.money.MonetaryCurrencies} singleton either by currency code, locale, or both.
027 */
028public class ConfigurableCurrencyUnitProvider implements CurrencyProviderSpi {
029    /**
030     * The currency units, identified by currency code.
031     */
032    private static Map<String, CurrencyUnit> currencyUnits = new ConcurrentHashMap<>();
033    /**
034     * The currency units identified by Locale.
035     */
036    private static Map<Locale, CurrencyUnit> currencyUnitsByLocale = new ConcurrentHashMap<>();
037
038
039    /**
040     * Return a {@link CurrencyUnit} instances matching the given
041     * {@link javax.money.CurrencyContext}.
042     *
043     * @param currencyQuery the {@link javax.money.CurrencyQuery} containing the parameters determining the query. not null.
044     * @return the corresponding {@link CurrencyUnit}, or null, if no such unit
045     * is provided by this provider.
046     */
047    public Set<CurrencyUnit> getCurrencies(CurrencyQuery currencyQuery) {
048        Set<CurrencyUnit> result = new HashSet<>(currencyUnits.size());
049        if (currencyQuery.getTimestamp() != null) {
050            return Collections.emptySet();
051        }
052        if (!currencyQuery.getCurrencyCodes().isEmpty()) {
053            for (String code : currencyQuery.getCurrencyCodes()) {
054                CurrencyUnit cu = currencyUnits.get(code);
055                if (cu != null) {
056                    result.add(cu);
057                }
058            }
059            return result;
060        }
061        if (!currencyQuery.getCountries().isEmpty()) {
062            for (Locale locale : currencyQuery.getCountries()) {
063                CurrencyUnit cu = currencyUnitsByLocale.get(locale);
064                if (cu != null) {
065                    result.add(cu);
066                }
067            }
068            return result;
069        }
070        result.addAll(currencyUnits.values());
071        return result;
072    }
073
074    /**
075     * Registers a bew currency unit under its currency code.
076     *
077     * @param currencyUnit the new currency to be registered, not null.
078     * @return any unit instance registered previously by this instance, or null.
079     */
080    public static CurrencyUnit registerCurrencyUnit(CurrencyUnit currencyUnit) {
081        Objects.requireNonNull(currencyUnit);
082        return ConfigurableCurrencyUnitProvider.currencyUnits.put(currencyUnit.getCurrencyCode(), currencyUnit);
083    }
084
085    /**
086     * Registers a bew currency unit under the given Locale.
087     *
088     * @param currencyUnit the new currency to be registered, not null.
089     * @param locale       the Locale, not null.
090     * @return any unit instance registered previously by this instance, or null.
091     */
092    public static CurrencyUnit registerCurrencyUnit(CurrencyUnit currencyUnit, Locale locale) {
093        Objects.requireNonNull(locale);
094        Objects.requireNonNull(currencyUnit);
095        return ConfigurableCurrencyUnitProvider.currencyUnitsByLocale.put(locale, currencyUnit);
096    }
097
098    /**
099     * Removes a CurrencyUnit.
100     *
101     * @param currencyCode the currency code, not null.
102     * @return any unit instance removed, or null.
103     */
104    public static CurrencyUnit removeCurrencyUnit(String currencyCode) {
105        Objects.requireNonNull(currencyCode);
106        return ConfigurableCurrencyUnitProvider.currencyUnits.remove(currencyCode);
107    }
108
109    /**
110     * Removes a CurrencyUnit.
111     *
112     * @param locale the Locale, not null.
113     * @return any unit instance removed, or null.
114     */
115    public static CurrencyUnit removeCurrencyUnit(Locale locale) {
116        Objects.requireNonNull(locale);
117        return ConfigurableCurrencyUnitProvider.currencyUnitsByLocale.remove(locale);
118    }
119
120    /*
121     * (non-Javadoc)
122     *
123     * @see java.lang.Object#toString()
124     */
125    @Override
126    public String toString() {
127        return "ConfigurableCurrencyUnitProvider [currencyUnits=" + currencyUnits + ", currencyUnitsByLocale=" +
128                currencyUnitsByLocale + ']';
129    }
130
131}