/* Copyright 2005-2006 Tim Fennell * * 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 net.sourceforge.stripes.format; import java.util.Date; import java.util.Locale; import java.util.Map; import net.sourceforge.stripes.config.Configuration; import net.sourceforge.stripes.util.Log; import net.sourceforge.stripes.util.TypeHandlerCache; /** * Implementation of {@link FormatterFactory} that contains a set of built-in formatters. Additional * formatters can be registered by calling {@link #add(Class, Class)}. If there is no registered * formatter for a specific class, then it attempts to find the best available formatter by * searching for a match against the target implemented interfaces, class's superclasses, and * interface superclasses. * * @author Tim Fennell */ public class DefaultFormatterFactory implements FormatterFactory { private static final Log log = Log.getInstance(DefaultFormatterFactory.class); /** Cache target type to Formatter class mappings. */ private TypeHandlerCache<Class<? extends Formatter<?>>> cache; /** Stores a reference to the Configuration passed in at initialization time. */ private Configuration configuration; /** Stores a reference to the configuration and configures the default formatters. */ public void init(Configuration configuration) throws Exception { this.configuration = configuration; this.cache = new TypeHandlerCache<Class<? extends Formatter<?>>>(); this.cache.setDefaultHandler(ObjectFormatter.class); add(Date.class, DateFormatter.class); add(Number.class, NumberFormatter.class); add(Enum.class, EnumFormatter.class); } /** Allows subclasses to access the stored configuration if needed. */ protected Configuration getConfiguration() { return this.configuration; } /** * Gets the (rather confusing) Map of Formatter objects. The Map uses the target class * as the key in the Map, and the Class object representing the Formatter as the value. * * @return the Map of Formatter classes */ protected Map<Class<?>,Class<? extends Formatter<?>>> getFormatters() { return cache.getHandlers(); } /** * Adds a Formatter to the set of registered Formatters, overriding an existing * formatter if one was registered for the type. * * @param targetType the type for which the formatter will handle formatting * @param formatterClass the implementation class that will handle the formatting */ public void add(Class<?> targetType, Class<? extends Formatter<?>> formatterClass) { cache.add(targetType, formatterClass); } /** * Check to see if the there is a Formatter for the specified clazz. If a Formatter is found an * instance is created, configured and returned. Otherwise returns null. * * @param clazz the type of object being formatted * @param locale the Locale into which the object should be formatted * @param formatType the type of output to produce (e.g. date, time etc.) * @param formatPattern a named format string, or a format pattern * @return Formatter an instance of a Formatter, or null */ public Formatter<?> getFormatter(Class<?> clazz, Locale locale, String formatType, String formatPattern) { Class<? extends Formatter<?>> formatterClass = cache.getHandler(clazz); if (formatterClass != null) { try { return getInstance(formatterClass, formatType, formatPattern, locale); } catch (Exception e) { log.error(e, "Unable to instantiate Formatter ", formatterClass); return null; } } else { log.trace("Couldn't find a formatter for ", clazz); return null; } } /** * Gets an instance of the Formatter class specified. * * @param clazz the Formatter type that is desired * @return an instance of the Formatter specified * @throws Exception if there is a problem instantiating the Formatter */ public Formatter<?> getInstance(Class<? extends Formatter<?>> clazz, String formatType, String formatPattern, Locale locale) throws Exception { Formatter<?> formatter = getConfiguration().getObjectFactory().newInstance(clazz); formatter.setFormatType(formatType); formatter.setFormatPattern(formatPattern); formatter.setLocale(locale); formatter.init(); return formatter; } }