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