Revision: 661
          http://stripes.svn.sourceforge.net/stripes/?rev=661&view=rev
Author:   bengunter
Date:     2007-12-10 22:23:42 -0800 (Mon, 10 Dec 2007)

Log Message:
-----------
Fixed STS-456: TypeConverterFactory and FormatterFactory should handle 
subclasses of their target type. If no formatter is found that exactly matches 
the target type then the set of registered formatters is searched for the first 
one that can format a superclass or implemented interface of the target type. 
The result (null or not) is cached for the target type so that future lookups 
are very fast.

Modified Paths:
--------------
    
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java

Modified: 
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java   
    2007-12-11 04:55:00 UTC (rev 660)
+++ 
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java   
    2007-12-11 06:23:42 UTC (rev 661)
@@ -15,7 +15,7 @@
 package net.sourceforge.stripes.format;
 
 import java.util.Date;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Locale;
 import java.util.Map;
 
@@ -31,7 +31,7 @@
 public class DefaultFormatterFactory implements FormatterFactory {
     /** A rather generic-heavy Map that maps target type to Formatter. */
     private Map<Class<?>, Class<? extends Formatter<?>>> formatters =
-        new HashMap<Class<?>, Class<? extends Formatter<?>>>();
+        new LinkedHashMap<Class<?>, Class<? extends Formatter<?>>>();
 
     /** Stores a reference to the Configuration passed in at initialization 
time. */
     private Configuration configuration;
@@ -79,11 +79,17 @@
      * @return Formatter an instance of a Formatter, or null
      */
     public Formatter<?> getFormatter(Class<?> clazz, Locale locale, String 
formatType, String formatPattern) {
-        Formatter<?> formatter = null;
-
         // Figure out if we have a type we can format
+        Class<? extends Formatter<?>> formatterClass = null;
         if (formatters.containsKey(clazz)) {
-            Class<? extends Formatter<?>> formatterClass = 
formatters.get(clazz);
+            formatterClass = formatters.get(clazz);
+        }
+        else {
+            formatterClass = findFormatterClass(clazz);
+        }
+
+        // If a formatter class was found then instantiate and initialize it
+        if (formatterClass != null) {
             try {
                 return getInstance(formatterClass, formatType, formatPattern, 
locale);
             }
@@ -92,33 +98,51 @@
                 return null;
             }
         }
-        else if (Date.class.isAssignableFrom(clazz)) {
-            formatter = new DateFormatter();
-            formatter.setFormatType(formatType);
-            formatter.setFormatPattern(formatPattern);
-            formatter.setLocale(locale);
-            formatter.init();
-            return formatter;
-        }
-        else if (Number.class.isAssignableFrom(clazz)) {
-            formatter = new NumberFormatter();
-            formatter.setFormatType(formatType);
-            formatter.setFormatPattern(formatPattern);
-            formatter.setLocale(locale);
-            formatter.init();
-            return formatter;
-        }
-        else if (Enum.class.isAssignableFrom(clazz)) {
-            formatter = new EnumFormatter();
-            formatter.init();
-            return formatter;
-        }
         else {
             return null;
         }
     }
 
     /**
+     * Searches all registered formatters looking for the first one that can 
format an object of
+     * type [EMAIL PROTECTED] targetClass}. First searches formatters added by 
calls to
+     * [EMAIL PROTECTED] #add(Class, Class)} and then searches the set of 
built-in formatters. Any formatter
+     * that can format a superclass or implemented interface of [EMAIL 
PROTECTED] targetClass} is considered a
+     * match. Thus, the order in which formatters are registered through 
[EMAIL PROTECTED] #add(Class, Class)}
+     * may be important.
+     * 
+     * @param targetClass the class of the object that needs to be formatted
+     * @return the first applicable formatter found or null if no match could 
be found
+     */
+    protected Class<? extends Formatter<?>> findFormatterClass(Class<?> 
targetClass) {
+        // check the formatters that have been added
+        Class<? extends Formatter<?>> formatterClass = null;
+        for (Map.Entry<Class<?>, Class<? extends Formatter<?>>> entry : 
formatters.entrySet()) {
+            if (entry.getKey().isAssignableFrom(targetClass)) {
+                formatterClass = entry.getValue();
+                break;
+            }
+        }
+
+        // if none found, then check the built-in formatters
+        if (formatterClass == null) {
+            if (Number.class.isAssignableFrom(targetClass)) {
+                formatterClass = NumberFormatter.class;
+            }
+            else if (Date.class.isAssignableFrom(targetClass)) {
+                formatterClass = DateFormatter.class;
+            }
+            else if (Enum.class.isAssignableFrom(targetClass)) {
+                formatterClass = EnumFormatter.class;
+            }
+        }
+
+        // cache it, even if it's null
+        formatters.put(targetClass, formatterClass);
+        return formatterClass;
+    }
+
+    /**
      * Gets an instance of the Formatter class specified.
      *
      * @param clazz the Formatter type that is desired


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
SF.Net email is sponsored by: 
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to