Revision: 1108
          http://stripes.svn.sourceforge.net/stripes/?rev=1108&view=rev
Author:   bengunter
Date:     2009-03-05 21:10:56 +0000 (Thu, 05 Mar 2009)

Log Message:
-----------
Fixed STS-663. TypeHandlerCache wasn't searching for type converters for the 
target type's annotations when hierarchy search was disabled. Added some unit 
tests.

Modified Paths:
--------------
    trunk/stripes/src/net/sourceforge/stripes/util/TypeHandlerCache.java
    
trunk/tests/src/net/sourceforge/stripes/validation/DefaultTypeConverterFactoryTest.java

Modified: trunk/stripes/src/net/sourceforge/stripes/util/TypeHandlerCache.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/util/TypeHandlerCache.java        
2009-03-05 18:25:25 UTC (rev 1107)
+++ trunk/stripes/src/net/sourceforge/stripes/util/TypeHandlerCache.java        
2009-03-05 21:10:56 UTC (rev 1108)
@@ -66,7 +66,7 @@
     private Set<Class<?>> negativeCache = new ConcurrentHashSet<Class<?>>();
 
     private T defaultHandler;
-    private boolean searchHierarchy = true;
+    private boolean searchHierarchy = true, searchAnnotations = true;
 
     /** Get the default handler to return if no handler is found for a 
requested target type. */
     public T getDefaultHandler() {
@@ -80,7 +80,7 @@
 
     /**
      * Indicates if the class hierarchy will be searched to find the best 
available handler in case
-     * a direct mapping is not available for a given target type.
+     * a direct mapping is not available for a given target type. Defaults to 
true.
      */
     public boolean isSearchHierarchy() {
         return searchHierarchy;
@@ -97,6 +97,21 @@
     }
 
     /**
+     * Indicates if the target type's annotations will be examined to find a 
handler registered for
+     * the annotation class. Defaults to true.
+     */
+    public boolean isSearchAnnotations() {
+        return searchAnnotations;
+    }
+
+    /**
+     * Set the flag that enables or disables searching for handlers for a 
target type's annotations.
+     */
+    public void setSearchAnnotations(boolean searchAnnotations) {
+        this.searchAnnotations = searchAnnotations;
+    }
+
+    /**
      * Gets the (rather confusing) map of handlers. The map uses the target 
type as the key in the
      * map, and the handler as the value.
      * 
@@ -150,8 +165,11 @@
     protected T findHandler(Class<?> targetType) {
         T handler = findInSuperclasses(targetType);
 
-        if (handler == null && isSearchHierarchy()) {
-            handler = findInInterfaces(targetType, targetType.getInterfaces());
+        if (handler == null) {
+            if (isSearchHierarchy())
+                handler = findInInterfaces(targetType, 
targetType.getInterfaces());
+            else
+                handler = cacheHandler(targetType, null);
         }
 
         return handler;
@@ -182,30 +200,33 @@
             if (handler != null)
                 return cacheHandler(targetType, handler);
         }
-        else if (!isSearchHierarchy()) {
-            return cacheHandler(targetType, null);
-        }
 
         // Check directly implemented interfaces
-        for (Class<?> iface : targetType.getInterfaces()) {
-            if ((handler = handlers.get(iface)) != null)
-                return cacheHandler(targetType, handler);
-            else if ((handler = indirectCache.get(iface)) != null)
-                return cacheHandler(targetType, handler);
+        if (isSearchHierarchy()) {
+            for (Class<?> iface : targetType.getInterfaces()) {
+                if ((handler = handlers.get(iface)) != null)
+                    return cacheHandler(targetType, handler);
+                else if ((handler = indirectCache.get(iface)) != null)
+                    return cacheHandler(targetType, handler);
+            }
         }
 
         // Check for annotations
-        for (Annotation annotation : targetType.getAnnotations()) {
-            Class<? extends Annotation> annotationType = 
annotation.annotationType();
-            if (handlers.containsKey(annotationType))
-                return cacheHandler(targetType, handlers.get(annotationType));
+        if (isSearchAnnotations()) {
+            for (Annotation annotation : targetType.getAnnotations()) {
+                Class<? extends Annotation> annotationType = 
annotation.annotationType();
+                if (handlers.containsKey(annotationType))
+                    return cacheHandler(targetType, 
handlers.get(annotationType));
+            }
         }
 
         // Check superclasses
-        Class<?> parent = targetType.getSuperclass();
-        if (parent != null) {
-            if ((handler = findInSuperclasses(parent)) != null) {
-                return cacheHandler(targetType, handler);
+        if (isSearchHierarchy()) {
+            Class<?> parent = targetType.getSuperclass();
+            if (parent != null) {
+                if ((handler = findInSuperclasses(parent)) != null) {
+                    return cacheHandler(targetType, handler);
+                }
             }
         }
 

Modified: 
trunk/tests/src/net/sourceforge/stripes/validation/DefaultTypeConverterFactoryTest.java
===================================================================
--- 
trunk/tests/src/net/sourceforge/stripes/validation/DefaultTypeConverterFactoryTest.java
     2009-03-05 18:25:25 UTC (rev 1107)
+++ 
trunk/tests/src/net/sourceforge/stripes/validation/DefaultTypeConverterFactoryTest.java
     2009-03-05 21:10:56 UTC (rev 1108)
@@ -1,13 +1,18 @@
 package net.sourceforge.stripes.validation;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
 import java.util.Locale;
 
 import net.sourceforge.stripes.StripesTestFixture;
+import net.sourceforge.stripes.util.Log;
 
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 public class DefaultTypeConverterFactoryTest {
+       private static final Log log = 
Log.getInstance(DefaultTypeConverterFactoryTest.class);
 
     @SuppressWarnings("unchecked")
        @Test(groups="fast")
@@ -21,4 +26,51 @@
        typeConverter = factory.getTypeConverter(Character.TYPE, 
Locale.getDefault());
         Assert.assertEquals(CharacterTypeConverter.class, 
typeConverter.getClass());
     }
+
+    /*
+     * Some tests to make sure we're getting the right type converters.
+     */
+
+       @Retention(RetentionPolicy.RUNTIME) public static @interface Ann {}
+    public static interface A {}
+    public static class B implements A {}
+    public static class C extends B {}
+    public static class D extends C {}
+    @Ann public static class E extends D {}
+    @Ann public static class F {}
+
+    public static abstract class BaseTC<T> implements TypeConverter<T> {
+        public T convert(String input, Class<? extends T> targetType, 
Collection<ValidationError> errors) { return null; }
+               public void setLocale(Locale locale) {}
+    }
+    public static class ATC extends BaseTC<A> {}
+    public static class DTC extends BaseTC<D> {}
+    public static class AnnTC extends BaseTC<Ann> {}
+
+    protected void checkTypeConverter(TypeConverterFactory factory, Class<?> 
targetType,
+            Class<?> expect) throws Exception {
+        log.debug("Checking type converter for ", targetType.getSimpleName(), 
" is ",
+                expect == null ? "null" : ATC.class.getSimpleName());
+        TypeConverter<?> tc = factory.getTypeConverter(targetType, null);
+        if (expect != null) {
+            Assert.assertNotNull(tc);
+            Assert.assertSame(tc.getClass(), expect);
+        }
+    }
+
+    @Test(groups = "fast")
+    public void testTypeConverters() throws Exception {
+        DefaultTypeConverterFactory factory = new 
DefaultTypeConverterFactory();
+        factory.init(StripesTestFixture.getDefaultConfiguration());
+        factory.add(A.class, ATC.class);
+        factory.add(D.class, DTC.class);
+        factory.add(Ann.class, AnnTC.class);
+
+        checkTypeConverter(factory, A.class, ATC.class);
+        checkTypeConverter(factory, B.class, null);
+        checkTypeConverter(factory, C.class, null);
+        checkTypeConverter(factory, D.class, DTC.class);
+        checkTypeConverter(factory, E.class, AnnTC.class);
+        checkTypeConverter(factory, F.class, AnnTC.class);
+    }
 }


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

------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to