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