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.spi;
017
018import org.javamoney.moneta.spi.base.BaseCurrencyProviderSpi;
019
020import java.util.*;
021import java.util.logging.Level;
022import java.util.logging.Logger;
023
024import javax.money.CurrencyQuery;
025import javax.money.CurrencyUnit;
026
027/**
028 * Default implementation of a {@link CurrencyUnit} based on the using the JDK's
029 * {@link Currency}.
030 *
031 * @version 0.5.1
032 * @author Anatole Tresch
033 * @author Werner Keil
034 */
035public class JDKCurrencyProvider extends BaseCurrencyProviderSpi {
036
037    /** Internal shared cache of {@link javax.money.CurrencyUnit} instances. */
038    private static final Map<String, CurrencyUnit> CACHED = loadCurrencies();
039
040    private static Map<String, CurrencyUnit> loadCurrencies() {
041        Set<Currency> availableCurrencies = Currency.getAvailableCurrencies();
042        Map<String, CurrencyUnit> result = new HashMap<>(availableCurrencies.size());
043        for (Currency jdkCurrency : availableCurrencies) {
044            CurrencyUnit cu = new JDKCurrencyAdapter(jdkCurrency);
045            result.put(cu.getCurrencyCode(), cu);
046        }
047        return Collections.unmodifiableMap(result);
048    }
049
050    @Override
051    public String getProviderName(){
052        return "default";
053    }
054
055    /**
056     * Return a {@link CurrencyUnit} instances matching the given
057     * {@link javax.money.CurrencyContext}.
058     *
059     * @param currencyQuery the {@link javax.money.CurrencyContext} containing the parameters determining the query. not null.
060     * @return the corresponding {@link CurrencyUnit}, or null, if no such unit
061     * is provided by this provider.
062     */
063    public Set<CurrencyUnit> getCurrencies(CurrencyQuery currencyQuery){
064        Set<CurrencyUnit> result = new HashSet<>();
065        if(!currencyQuery.getCurrencyCodes().isEmpty()) {
066            for (String code : currencyQuery.getCurrencyCodes()) {
067                CurrencyUnit cu = CACHED.get(code);
068                if (cu != null) {
069                    result.add(cu);
070                }
071            }
072            return result;
073        }
074        if(!currencyQuery.getCountries().isEmpty()) {
075            for (Locale country : currencyQuery.getCountries()) {
076                CurrencyUnit cu = getCurrencyUnit(country);
077                if (cu != null) {
078                    result.add(cu);
079                }
080            }
081            return result;
082        }
083        if(!currencyQuery.getNumericCodes().isEmpty()) {
084            for (Integer numCode : currencyQuery.getNumericCodes()) {
085                List<CurrencyUnit> cus = getCurrencyUnits(numCode);
086                result.addAll(cus);
087            }
088            return result;
089        }
090        // No constraints defined, return all.
091        result.addAll(CACHED.values());
092        return result;
093    }
094
095    private List<CurrencyUnit> getCurrencyUnits(int numCode) {
096        List<CurrencyUnit> result = new ArrayList<>();
097        for(Currency currency: Currency.getAvailableCurrencies()){
098            if(currency.getNumericCode()==numCode){
099                result.add(CACHED.get(currency.getCurrencyCode()));
100            }
101        }
102        return result;
103    }
104
105    private CurrencyUnit getCurrencyUnit(Locale locale) {
106                Currency cur;
107                try {
108                        cur = Currency.getInstance(locale);
109                        if (cur!=null) {
110                                return CACHED.get(cur.getCurrencyCode());
111                        }
112                } catch (Exception e) {
113                        if (Logger.getLogger(getClass().getName()).isLoggable(Level.FINEST)) {
114                                Logger.getLogger(getClass().getName()).finest(
115                                                "No currency for locale found: " + locale);
116                        }
117                }
118                return null;
119        }
120
121}