/*
* Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil.
*
* 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 org.javamoney.format;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Locale;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.javamoney.format.spi.TokenizeableFormatsSingletonSpi;
/**
* This singleton accessor provides access to the formatting logic of JavaMoney. *
* <p>
* {@link ItemFormat} instances are not required to be thread-safe. Basically
* when accessing an {@link ItemFormat} from the {@link ItemFormats}
* singleton a new instance should be created on each access.<br/>
* This class itself is thread-safe, delegating its calls to the
* {@link org.javamoney.format.spi.TokenizeableFormatsSingletonSpi} registered using the
* {@link ServiceLoader}.
*
* @author Anatole Tresch
*/
public final class ItemFormats{
/** SPI implementation loaded loaded from ServiceLodaer. */
private static TokenizeableFormatsSingletonSpi monetaryFormatSpi = loadMonetaryFormatSpi();
/**
* Singleton constructor.
*/
private ItemFormats() {
}
/**
* Loads the MonetaryFormatSpi the {@link org.javamoney.format.spi.TokenizeableFormatsSingletonSpi} used.
*
* @return the MonetaryFormatSpi to be used.
*/
private static TokenizeableFormatsSingletonSpi loadMonetaryFormatSpi() {
TokenizeableFormatsSingletonSpi spi = null;
try {
// try loading directly from ServiceLoader
Iterator<TokenizeableFormatsSingletonSpi> instances = ServiceLoader
.load(TokenizeableFormatsSingletonSpi.class).iterator();
if (instances.hasNext()) {
spi = instances.next();
if (instances.hasNext()) {
throw new IllegalStateException(
"Ambigous reference to spi (only "
+ "one can be registered: "
+ TokenizeableFormatsSingletonSpi.class
.getName());
}
return spi;
}
} catch (Exception e) {
Logger.getLogger(ItemFormats.class.getName()).log(Level.INFO,
"No MonetaryFormatSpi found, using default.", e);
}
return new DefaultTokenizeableFormatsSpi();
}
/**
* Return the style id's supported by this {@link ItemFormatterFactorySpi}
* instance.
*
* @see LocalizationContext#getId()
* @param targetType
* the target type, never {@code null}.
* @return the supported style ids, never {@code null}.
*/
public static Collection<String> getSupportedStyleIds(Class<?> targetType) {
Collection<String> styleIDs = monetaryFormatSpi
.getSupportedStyleIds(targetType);
if (styleIDs == null) {
Logger.getLogger(ItemFormats.class.getName()).log(
Level.WARNING,
"MonetaryFormatSpi.getSupportedStyleIds returned null for "
+ targetType);
return Collections.emptySet();
}
return styleIDs;
}
/**
* Method allows to check if a named style is supported.
*
* @param targetType
* the target type, never {@code null}.
* @param styleId
* The style id.
* @return true, if a spi implementation is able to provide an
* {@link ItemFormat} for the given style.
*/
public static boolean isSupportedStyle(Class<?> targetType, String styleId) {
return monetaryFormatSpi.isSupportedStyle(targetType, styleId);
}
/**
* Access a default {@link LocalizationContext}.
*
* @param targetType
* the target type.
* @return the default style, as defined for the targetType.
*/
public static LocalizationContext getLocalizationStyle(Class<?> targetType) {
return monetaryFormatSpi.getLocalizationStyle(targetType,
LocalizationContext.DEFAULT_ID);
}
/**
* Access the configuring {@link LocalizationContext},
*
* @param targetType
* the target type.
* @param styleId
* the style's identifier.
* @return the style instance found.
*/
public static LocalizationContext getLocalizationStyle(Class<?> targetType,
String styleId) {
return monetaryFormatSpi.getLocalizationStyle(targetType, styleId);
}
/**
* This method returns an instance of an {@link ItemFormat} .
*
* @param targetType
* the target type, never {@code null}.
* @param style
* the {@link LocalizationContext} to be attached to this
* {@link ItemFormat}, which also contains the target
* {@link Locale} instances to be used, as well as other
* attributes configuring this instance.
* @return the formatter required, if available.
* @throws ItemFormatException
* if the {@link LocalizationContext} passed can not be used for
* configuring the {@link ItemFormat} and no matching
* {@link ItemFormat} could be provided.
*/
public static <T> ItemFormat<T> getItemFormat(Class<T> targetType)
throws ItemFormatException {
LocalizationContext style = getLocalizationStyle(targetType,
LocalizationContext.DEFAULT_ID);
if (style == null) {
throw new ItemFormatException("No default style present for "
+ targetType);
}
return getItemFormat(targetType, style);
}
/**
* This method returns an instance of an {@link ItemFormat} .
*
* @param targetType
* the target type, never {@code null}.
* @param style
* the {@link LocalizationContext} to be attached to this
* {@link ItemFormat}, which also contains the target
* {@link Locale} instances to be used, as well as other
* attributes configuring this instance.
* @return the formatter required, if available.
* @throws ItemFormatException
* if the {@link LocalizationContext} passed can not be used for
* configuring the {@link ItemFormat} and no matching
* {@link ItemFormat} could be provided.
*/
public static <T> ItemFormat<T> getItemFormat(Class<T> targetType,
String styleId) throws ItemFormatException {
return getItemFormat(targetType,
getLocalizationStyle(targetType, styleId));
}
/**
* This method returns an instance of an {@link ItemFormat} .
*
* @param targetType
* the target type, never {@code null}.
* @param style
* the {@link LocalizationContext} to be attached to this
* {@link ItemFormat}, which also contains the target
* {@link Locale} instances to be used, as well as other
* attributes configuring this instance.
* @return the formatter required, if available.
* @throws ItemFormatException
* if the {@link LocalizationContext} passed can not be used for
* configuring the {@link ItemFormat} and no matching
* {@link ItemFormat} could be provided.
*/
public static <T> ItemFormat<T> getItemFormat(Class<T> targetType,
LocalizationContext style)
throws ItemFormatException {
if (style == null) {
style = LocalizationContext.of(targetType);
}
if (targetType == null) {
throw new IllegalArgumentException("targetType required.");
}
try {
ItemFormat<T> f = monetaryFormatSpi
.getItemFormat(targetType, style);
if (f != null) {
return f;
}
throw new ItemFormatException("No formatter available for "
+ targetType + " and " + style);
} catch (Exception e) {
throw new ItemFormatException("Error accessing formatter for "
+ targetType + " and " + style, e);
}
}
/**
* Default SPI implementation of {@link org.javamoney.format.spi.TokenizeableFormatsSingletonSpi}, only
* used when no corresponding SPI was registered into {@link ServiceLoader}.
*
* @author Anatole Tresch
*/
private static final class DefaultTokenizeableFormatsSpi implements TokenizeableFormatsSingletonSpi{
/*
* (non-Javadoc)
*
* @see
* javax.money.format.spi.TokenizeableFormatsSingletonSpi#getSupportedStyleIds
* (java.lang.Class)
*/
@Override
public Collection<String> getSupportedStyleIds(Class<?> targetType) {
return LocalizationContext.getSupportedStyleIds(targetType);
}
/*
* (non-Javadoc)
*
* @see
* javax.money.format.spi.TokenizeableFormatsSingletonSpi#isSupportedStyle
* (java.lang.Class, java.lang.String)
*/
@Override
public boolean isSupportedStyle(Class<?> targetType, String styleId) {
return false;
}
/*
* (non-Javadoc)
*
* @see
* javax.money.format.spi.TokenizeableFormatsSingletonSpi#getItemFormat(
* java.lang.Class, javax.money.format.LocalizationStyle)
*/
@Override
public <T> ItemFormat<T> getItemFormat(Class<T> targetType,
LocalizationContext style) throws ItemFormatException {
throw new ItemFormatException("No MonetaryFormatSpi registered.");
}
/*
* (non-Javadoc)
*
* @see
* javax.money.format.spi.TokenizeableFormatsSingletonSpi#getLocalizationStyle
* (java.lang.Class, java.lang.String)
*/
@Override
public LocalizationContext getLocalizationStyle(Class<?> targetType,
String styleId) {
return LocalizationContext.of(targetType, styleId);
}
}
}