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