Revision: 1057
          http://stripes.svn.sourceforge.net/stripes/?rev=1057&view=rev
Author:   bengunter
Date:     2009-02-26 06:48:17 +0000 (Thu, 26 Feb 2009)

Log Message:
-----------
STS-614: Added a type parameter to ObjectPostProcessor interface to indicate 
the type it processes. This can still be overridden using @TargetTypes, but 
this will often make things easier on developers.

Modified Paths:
--------------
    
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java
    
trunk/stripes/src/net/sourceforge/stripes/controller/ObjectPostProcessor.java
    trunk/tests/src/net/sourceforge/stripes/controller/ObjectFactoryTests.java

Modified: 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java  
    2009-02-26 06:14:38 UTC (rev 1056)
+++ 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java  
    2009-02-26 06:48:17 UTC (rev 1057)
@@ -16,7 +16,9 @@
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -34,6 +36,7 @@
 import net.sourceforge.stripes.config.TargetTypes;
 import net.sourceforge.stripes.exception.StripesRuntimeException;
 import net.sourceforge.stripes.util.Log;
+import net.sourceforge.stripes.util.ReflectUtil;
 import net.sourceforge.stripes.util.TypeHandlerCache;
 
 /**
@@ -45,6 +48,7 @@
  * @author Ben Gunter
  * @since Stripes 1.5.1
  */
+...@suppresswarnings("unchecked")
 public class DefaultObjectFactory implements ObjectFactory {
     /**
      * An implementation of {...@link ConstructorWrapper} that calls back to
@@ -124,16 +128,30 @@
             postProcessors = new TypeHandlerCache<List<ObjectPostProcessor>>();
         }
 
+        // Determine target types from type arguments
+        List<Class<?>> targetTypes = new ArrayList<Class<?>>();
+        Type[] typeArguments = 
ReflectUtil.getActualTypeArguments(postProcessor.getClass(),
+                ObjectPostProcessor.class);
+        if ((typeArguments != null) && (typeArguments.length == 1)
+                && !typeArguments[0].equals(Object.class)) {
+            if (typeArguments[0] instanceof Class) {
+                targetTypes.add((Class<?>) typeArguments[0]);
+            }
+            else {
+                log.warn("Type parameter for non-abstract post-processor [", 
postProcessor
+                        .getClass().getName(), "] is not a class.");
+            }
+        }
+
         // Determine target types from annotation; if no annotation then 
process everything
         TargetTypes annotation = 
postProcessor.getClass().getAnnotation(TargetTypes.class);
-        Class<?>[] targetTypes;
-        if (annotation == null) {
-            targetTypes = new Class<?>[] { Object.class };
-        }
-        else {
-            targetTypes = annotation.value();
-        }
+        if (annotation != null)
+            targetTypes.addAll(Arrays.asList(annotation.value()));
 
+        // Default to Object
+        if (targetTypes.isEmpty())
+            targetTypes.add(Object.class);
+
         // Register post-processor for each target type
         for (Class<?> targetType : targetTypes) {
             List<ObjectPostProcessor> list = 
postProcessors.getHandler(targetType);
@@ -177,7 +195,6 @@
      * @throws InstantiationException if no implementation type has been 
configured
      * @throws IllegalAccessException if thrown by the JVM during class 
instantiation
      */
-    @SuppressWarnings("unchecked")
     public <T> T newInterfaceInstance(Class<T> interfaceType) throws 
InstantiationException,
             IllegalAccessException {
         Class impl = getImplementingClass(interfaceType);
@@ -308,7 +325,7 @@
             List<ObjectPostProcessor> list = 
postProcessors.getHandler(object.getClass());
             if (list != null) {
                 for (ObjectPostProcessor postProcessor : list) {
-                    object = postProcessor.postProcess(object);
+                    object = (T) postProcessor.postProcess(object);
                 }
             }
         }

Modified: 
trunk/stripes/src/net/sourceforge/stripes/controller/ObjectPostProcessor.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/controller/ObjectPostProcessor.java   
    2009-02-26 06:14:38 UTC (rev 1056)
+++ 
trunk/stripes/src/net/sourceforge/stripes/controller/ObjectPostProcessor.java   
    2009-02-26 06:48:17 UTC (rev 1057)
@@ -21,7 +21,7 @@
  * 
  * @author Ben Gunter
  */
-public interface ObjectPostProcessor {
+public interface ObjectPostProcessor<T> {
     /**
      * Do whatever post-processing is necessary on the object and return it. 
It is not absolutely
      * required that this method return exactly the same object that was 
passed to it, but it is
@@ -30,5 +30,5 @@
      * @param object The object to be processed.
      * @return The object that was passed in.
      */
-    <T> T postProcess(T object);
+    T postProcess(T object);
 }

Modified: 
trunk/tests/src/net/sourceforge/stripes/controller/ObjectFactoryTests.java
===================================================================
--- trunk/tests/src/net/sourceforge/stripes/controller/ObjectFactoryTests.java  
2009-02-26 06:14:38 UTC (rev 1056)
+++ trunk/tests/src/net/sourceforge/stripes/controller/ObjectFactoryTests.java  
2009-02-26 06:48:17 UTC (rev 1057)
@@ -25,7 +25,6 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 import net.sourceforge.stripes.StripesTestFixture;
-import net.sourceforge.stripes.config.TargetTypes;
 import net.sourceforge.stripes.controller.ObjectFactory.ConstructorWrapper;
 import net.sourceforge.stripes.exception.StripesRuntimeException;
 import net.sourceforge.stripes.util.Log;
@@ -182,12 +181,10 @@
     @Test(groups = "fast")
     public void classPostProcessor() {
         final String prefix = "Stripey!";
-        @TargetTypes(String.class)
-        class MyObjectPostProcessor implements ObjectPostProcessor {
-            @SuppressWarnings("unchecked")
-            public <T> T postProcess(T object) {
+        class MyObjectPostProcessor implements ObjectPostProcessor<String> {
+            public String postProcess(String object) {
                 log.debug("Altering '", object, "'");
-                return (T) (prefix + object);
+                return (prefix + object);
             }
         }
 
@@ -218,12 +215,10 @@
     @Test(groups = "fast")
     public void interfacePostProcessor() {
         final String prefix = "Stripey!";
-        @TargetTypes(CharSequence.class)
-        class MyObjectPostProcessor implements ObjectPostProcessor {
-            @SuppressWarnings("unchecked")
-            public <T> T postProcess(T object) {
+        class MyObjectPostProcessor implements 
ObjectPostProcessor<CharSequence> {
+            public CharSequence postProcess(CharSequence object) {
                 log.debug("Altering '", object, "'");
-                return (T) (prefix + object);
+                return (prefix + object);
             }
         }
 
@@ -259,14 +254,11 @@
     @Test(groups = "fast")
     public void multipleSequentialPostProcessors() {
         final AtomicInteger counter = new AtomicInteger(0);
-        @TargetTypes(StringBuilder.class)
-        class MyObjectPostProcessor implements ObjectPostProcessor {
-            @SuppressWarnings("unchecked")
-            public <T> T postProcess(T object) {
+        class MyObjectPostProcessor implements 
ObjectPostProcessor<StringBuilder> {
+            public StringBuilder postProcess(StringBuilder object) {
                 log.debug("Altering '", object, "'");
-                return (T) ((StringBuilder) object).append("Touched by 
").append(
-                        this.toString().replaceAll(".*@", "")).append(" 
(counter=").append(
-                        counter.addAndGet(1)).append(") ... ");
+                return object.append("Touched by 
").append(this.toString().replaceAll(".*@", ""))
+                        .append(" 
(counter=").append(counter.addAndGet(1)).append(") ... ");
             }
         }
 


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