/*
 * Copyright 2012-2016 Credit Suisse
 * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package javax.money.format;

import javax.money.MonetaryException;
import javax.money.spi.Bootstrap;
import javax.money.spi.MonetaryAmountFormatProviderSpi;
import javax.money.spi.MonetaryFormatsSingletonSpi;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

This class models the singleton accessor for MonetaryAmountFormat instances.

This class is thread-safe.

Author:Anatole Tresch, Werner Keil
/** * This class models the singleton accessor for {@link MonetaryAmountFormat} instances. * <p> * This class is thread-safe. * * @author Anatole Tresch * @author Werner Keil */
public final class MonetaryFormats { private static MonetaryFormatsSingletonSpi getMonetaryFormatsSpi() { return loadMonetaryFormatsSingletonSpi(); }
Private singleton constructor.
/** * Private singleton constructor. */
private MonetaryFormats() { // Singleton }
Loads the SPI backing bean.
Returns:the instance of MonetaryFormatsSingletonSpi to be used by this singleton.
/** * Loads the SPI backing bean. * * @return the instance of MonetaryFormatsSingletonSpi to be used by this singleton. */
private static MonetaryFormatsSingletonSpi loadMonetaryFormatsSingletonSpi() { try { return Optional.ofNullable(Bootstrap.getService(MonetaryFormatsSingletonSpi.class)) .orElseGet(DefaultMonetaryFormatsSingletonSpi::new); } catch (Exception e) { Logger.getLogger(MonetaryFormats.class.getName()) .log(Level.WARNING, "Failed to load MonetaryFormatsSingletonSpi, using default.", e); return new DefaultMonetaryFormatsSingletonSpi(); } }
Checks if a MonetaryAmountFormat is available for the given Locale and providers.
Params:
  • locale – the target Locale, not null.
  • providers – The providers to be queried, if not set the providers as defined by #getDefaultCurrencyProviderChain() are queried.
Returns:true, if a corresponding MonetaryAmountFormat is accessible.
/** * Checks if a {@link MonetaryAmountFormat} is available for the given {@link Locale} and providers. * * @param locale the target {@link Locale}, not {@code null}. * @param providers The providers to be queried, if not set the providers as defined by #getDefaultCurrencyProviderChain() * are queried. * @return true, if a corresponding {@link MonetaryAmountFormat} is accessible. */
public static boolean isAvailable(Locale locale, String... providers) { return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) .isAvailable(locale, providers); }
Access the default MonetaryAmountFormat given a Locale.
Params:
  • locale – the target Locale, not null.
  • providers – The providers to be queried, if not set the providers as defined by #getDefaultCurrencyProviderChain() are queried.
Throws:
Returns:the matching MonetaryAmountFormat
/** * Access the default {@link MonetaryAmountFormat} given a {@link Locale}. * * @param locale the target {@link Locale}, not {@code null}. * @param providers The providers to be queried, if not set the providers as defined by #getDefaultCurrencyProviderChain() * are queried. * @return the matching {@link MonetaryAmountFormat} * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a * corresponding {@link MonetaryAmountFormat} instance. */
public static MonetaryAmountFormat getAmountFormat(Locale locale, String... providers) { return getAmountFormat(AmountFormatQueryBuilder.of(locale).setProviderNames(providers).setLocale(locale).build()); }
Checks if a MonetaryAmountFormat is available for the given AmountFormatQuery.
Params:
  • formatQuery – the required AmountFormatQuery, not null. If the query does not define any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() are used.
Returns:true, if a corresponding MonetaryAmountFormat is accessible.
/** * Checks if a {@link MonetaryAmountFormat} is available for the given {@link javax.money.format.AmountFormatQuery}. * * @param formatQuery the required {@link AmountFormatQuery}, not {@code null}. If the query does not define * any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() * are used. * @return true, if a corresponding {@link MonetaryAmountFormat} is accessible. */
public static boolean isAvailable(AmountFormatQuery formatQuery) { return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) .isAvailable(formatQuery); }
Access the default MonetaryAmountFormat given a Locale.
Params:
  • formatQuery – the required AmountFormatQuery, not null. If the query does not define any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() are used.
Throws:
Returns:the matching MonetaryAmountFormat
/** * Access the default {@link MonetaryAmountFormat} given a {@link Locale}. * * @param formatQuery the required {@link AmountFormatQuery}, not {@code null}. If the query does not define * any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() * are used. * @return the matching {@link MonetaryAmountFormat} * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a * corresponding {@link MonetaryAmountFormat} instance. */
public static MonetaryAmountFormat getAmountFormat(AmountFormatQuery formatQuery) { return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) .getAmountFormat(formatQuery); }
Access all MonetaryAmountFormat instances that match the given a AmountFormatQuery.
Params:
  • formatQuery – the required AmountFormatQuery, not null. If the query does not define any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() are used.
Throws:
Returns:the matching MonetaryAmountFormat
/** * Access all {@link MonetaryAmountFormat} instances that match the given a {@link AmountFormatQuery}. * * @param formatQuery the required {@link AmountFormatQuery}, not {@code null}. If the query does not define * any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() * are used. * @return the matching {@link MonetaryAmountFormat} * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a * corresponding {@link MonetaryAmountFormat} instance. */
public static Collection<MonetaryAmountFormat> getAmountFormats(AmountFormatQuery formatQuery) { return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) .getAmountFormats(formatQuery); }
Access the a MonetaryAmountFormat given its styleId.
Params:
  • formatName – the target format name, not null.
  • providers – The providers to be used, if not set the providers as defined by #getDefaultCurrencyProviderChain() are used.
Throws:
Returns:the matching MonetaryAmountFormat
/** * Access the a {@link MonetaryAmountFormat} given its styleId. * * @param formatName the target format name, not {@code null}. * @param providers The providers to be used, if not set the providers as defined by #getDefaultCurrencyProviderChain() are * used. * @return the matching {@link MonetaryAmountFormat} * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a * corresponding {@link MonetaryAmountFormat} instance. */
public static MonetaryAmountFormat getAmountFormat(String formatName, String... providers) { return getAmountFormat(AmountFormatQueryBuilder.of(formatName).setProviderNames(providers).build()); }
Get all available locales. This equals to MonetaryAmountFormatProviderSpi.getAvailableLocales().
Params:
  • providers – The providers to be used, if not set the providers as defined by #getDefaultCurrencyProviderChain() are used.
Returns:all available locales, never null.
/** * Get all available locales. This equals to {@link MonetaryAmountFormatProviderSpi#getAvailableLocales()}. * * @param providers The providers to be used, if not set the providers as defined by #getDefaultCurrencyProviderChain() are * used. * @return all available locales, never {@code null}. */
public static Set<Locale> getAvailableLocales(String... providers) { return getMonetaryFormatsSpi().getAvailableLocales(providers); }
Get the names of the currently registered format providers.
Returns:the provider names, never null.
/** * Get the names of the currently registered format providers. * * @return the provider names, never null. */
public static Collection<String> getFormatProviderNames() { Collection<String> providers = Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow( () -> new MonetaryException( "No MonetaryFormatsSingletonSpi loaded, query functionality is not available.")) .getProviderNames(); if (Objects.isNull(providers)) { Logger.getLogger(MonetaryFormats.class.getName()).warning( "No supported rate/conversion providers returned by SPI: " + getMonetaryFormatsSpi().getClass().getName()); return Collections.emptySet(); } return providers; }
Get the default provider chain, identified by the unique provider names in order as evaluated and used.
Returns:the default provider chain, never null.
/** * Get the default provider chain, identified by the unique provider names in order as evaluated and used. * * @return the default provider chain, never null. */
public static List<String> getDefaultFormatProviderChain() { return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) .getDefaultProviderChain(); }
This class models the singleton accessor for MonetaryAmountFormat instances.

This class is thread-safe.

Author:Anatole Tresch, Werner Keil
/** * This class models the singleton accessor for {@link javax.money.format.MonetaryAmountFormat} instances. * <p> * This class is thread-safe. * * @author Anatole Tresch * @author Werner Keil */
public static final class DefaultMonetaryFormatsSingletonSpi implements MonetaryFormatsSingletonSpi {
Params:
  • formatQuery – The format query defining the requirements of the formatter.
Throws:
Returns:the corresponding MonetaryAmountFormat
/** * Access an {@link javax.money.format.MonetaryAmountFormat} given a {@link javax.money.format * .AmountFormatContext}. * * @param formatQuery The format query defining the requirements of the formatter. * @return the corresponding {@link javax.money.format.MonetaryAmountFormat} * @throws javax.money.MonetaryException if no registered {@link javax.money.spi * .MonetaryAmountFormatProviderSpi} can provide a * corresponding {@link javax.money.format.MonetaryAmountFormat} instance. */
@Override public Collection<MonetaryAmountFormat> getAmountFormats(AmountFormatQuery formatQuery) { Collection<MonetaryAmountFormat> result = new ArrayList<>(); for (MonetaryAmountFormatProviderSpi spi : Bootstrap.getServices(MonetaryAmountFormatProviderSpi.class)) { Collection<MonetaryAmountFormat> formats = spi.getAmountFormats(formatQuery); if (Objects.nonNull(formats)) { result.addAll(formats); } } return result; } @Override public Set<String> getProviderNames() { return getSpisAsMap().keySet(); }
This default implementation simply returns all providers defined in arbitrary order.
Returns:the default provider chain, never null.
/** * This default implementation simply returns all providers defined in arbitrary order. * * @return the default provider chain, never null. */
@Override public List<String> getDefaultProviderChain() { List<String> list = new ArrayList<>(getProviderNames()); Collections.sort(list); return list; }
Get all available locales. This equals to MonetaryAmountFormatProviderSpi.getAvailableLocales().
Returns:all available locales, never null.
/** * Get all available locales. This equals to {@link javax.money.spi * .MonetaryAmountFormatProviderSpi#getAvailableLocales()}. * * @return all available locales, never {@code null}. */
@Override public Set<Locale> getAvailableLocales(String... providerNames) { Set<Locale> locales = new HashSet<>(); Collection<MonetaryAmountFormatProviderSpi> spis = getSpis(providerNames); for (MonetaryAmountFormatProviderSpi spi : spis) { locales.addAll(spi.getAvailableLocales()); } return locales; } private Map<String, MonetaryAmountFormatProviderSpi> getSpisAsMap() { Map<String, MonetaryAmountFormatProviderSpi> spis = new ConcurrentHashMap<>(); for (MonetaryAmountFormatProviderSpi spi : Bootstrap.getServices(MonetaryAmountFormatProviderSpi.class)) { if (spi.getProviderName() == null) { Logger.getLogger(MonetaryFormats.class.getName()).warning("MonetaryAmountFormatProviderSpi " + "returns null for " + "getProviderName: " + spi.getClass().getName()); } spis.put(spi.getProviderName(), spi); } return spis; } private Collection<MonetaryAmountFormatProviderSpi> getSpis(String... providerNames) { List<MonetaryAmountFormatProviderSpi> providers = new ArrayList<>(); Map<String, MonetaryAmountFormatProviderSpi> spis = getSpisAsMap(); if (providerNames.length == 0) { providers.addAll(spis.values()); } else { for (String provName : providerNames) { MonetaryAmountFormatProviderSpi spi = spis.get(provName); if (Objects.isNull(spi)) { throw new IllegalArgumentException("MonetaryAmountFormatProviderSpi not found: " + provName); } providers.add(spi); } } return providers; } } }